Setting request headers with values from a JWT

Before Istio 1.5 with the mixer it was easy to set headers related to values included in a JWT.

How can I do this in Istio 1.5?

Example:

  • Bearer token in a request includes the user id as [sub]
  • UserId should be included as header “X-user-id”
2 Likes

Do you want to inject request headers before JWT is forwarded to the application? One way you can do is to inject an EnvoyFilter after Istio authentication filter, and add your logic of settings headers there.

I found this yesterday looking for something else

1 Like

Hello,

This code works with istio 1.5.x.

Jwt auth and envoy filter

This works for me.

Envoy jwt auth adds the claims to the dynamic metadata. ISTIO by default uses the issuer as the key in the dynamic metadata.

step 1:
Update the access log so that you can see what values you get in the dynamic metadata.
add this to the access logs: “auth_jwt”:"%DYNAMIC_METADATA(envoy.filters.http.jwt_authn)%"

In this step you should be able to find out the key for which you can access your claims.

step2:
Create an envoy filter that uses the dynamic metadata to add headers to the request.

apiVersion: networking.istio.io/v1alpha3
kind: EnvoyFilter
metadata:
  name: jwt-to-header-filter
  namespace: istio-system
spec:
  workloadSelector:
    labels:
      app: istio-ingressgateway
  configPatches:
  - applyTo: HTTP_FILTER
    match:
      context: GATEWAY
      listener:
        filterChain:
          filter:
            name: "envoy.http_connection_manager"
            subFilter:
              name: "envoy.router"
    patch:
      operation: INSERT_BEFORE
      value:
        name: envoy.lua
        config: 
          inlineCode: |
            function envoy_on_request(request_handle)
              local meta = request_handle:streamInfo():dynamicMetadata():get("envoy.filters.http.jwt_authn")
              local claims = meta["{add the key here from step1. This is most likely your jwt issuer url.}"]
              local user = claims.iss.."/"..claims.username
              request_handle:logInfo("username"..user)
              request_handle:headers():add("x-jwt-user", user)
            end
2 Likes

You can use outputPayloadToHeader to have istio base64 encode the jwt payload and pass it along as a a header

1 Like

Wow!! This seems the best option!

apiVersion: "security.istio.io/v1beta1"
kind: "RequestAuthentication"
metadata:
  name: "jwt-echoserver"
  namespace: foo
spec:
  selector:
    matchLabels:
      app: echoserver
  jwtRules:
  - issuer: "testing@secure.istio.io"
    jwksUri: "https://raw.githubusercontent.com/istio/istio/release-1.7/security/tools/jwt/samples/jwks.json"
    outputPayloadToHeader: x-jwt

Thank you.