Setting request headers with values from a JWT

Hi, I’m currently trying the various existing workarounds but would love to see formal support introduced in future Istio versions.

The second proposal would fit our use case most clearly as we are trying to decouple application logic from authorization logic, but still need access to some of the JWT claims for auditing purposes. Thus being able to copy certain claims into the headers at the Request authentication step would allow us to then pass those variables around in the mTLS secured service to service environment, and remove the use of JWTs for service to service authz completely.

Hi guys,

I’m using Istio 1.13 / 1.14, it seems like no matter what I do, I always got
error envoy lua script log: [string “function envoy_on_request(request_handle)…”]:4: attempt to index global ‘“envoy’ (a nil value)

Here is my lua filter

apiVersion: networking.istio.io/v1alpha3
kind: EnvoyFilter
metadata:
  name: jwt-rule
  namespace: lab
spec:
  configPatches:
  - applyTo: HTTP_FILTER
    match:
      context: SIDECAR_INBOUND
      listener:
        filterChain:
          filter:
            name: "envoy.filters.network.http_connection_manager"
            subFilter:
              name: "envoy.filters.http.jwt_authn"
    patch:
      operation: INSERT_BEFORE
      value: 
       name: envoy.lua
       typed_config:
          "@type": "type.googleapis.com/envoy.extensions.filters.http.lua.v3.Lua"
          inlineCode: |
            function envoy_on_request(request_handle)
              request_handle:logCritical("test1")
              request_handle:headers():add("xxxxx", "xxxxxwwwww")
              meta=request_handle:streamInfo():dynamicMetadata():get(“envoy.filters.http.jwt_authn”)    ### this line got nil error prompt
            end

Hi - just working through this dicussion - I am using Istio v1.14 and the following worked for me.
First, I updated the access log output as suggested by @Thet_Ko to see that the data is picked-up and to check the meta key. Then I applied the envoy filter with updates to filter/name, filter/subfilter/name, typed_config as below (compared to the origianl version from @Thet_Ko). I only got it to work with context: GATEWAY
Also note that I was only interested in the claims.sub field of the token, which contains the user ID in my case. You can probably change that to any content / format you need as in previous posts.

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.filters.network.http_connection_manager"
            subFilter:
              name: "envoy.filters.http.router"
    patch:
      operation: INSERT_BEFORE
      value:
        name: envoy.lua
        typed_config:
          "@type": "type.googleapis.com/envoy.extensions.filters.http.lua.v3.Lua"
          inlineCode: |
            function envoy_on_request(request_handle)
              local meta = request_handle:streamInfo():dynamicMetadata():get("envoy.filters.http.jwt_authn")
              local claims = meta["https://xxxxxxxxxxxxx.com/"]
              local user = claims.sub
              request_handle:logInfo("userid"..user)
              request_handle:headers():add("userid", user)
            end