使用Envoy验证JWT中的声明

huangapple go评论54阅读模式
英文:

validate claims inside JWT using envoy

问题

{
"aud": "123123-1232-123123-2323-123",
"iss": "https://url",
"roles": ["default"]
}

我的JWT包含上述声明。我需要验证三个事项:

  1. 受众(aud):aud
  2. 发行者(iss):iss
  3. 角色(roles):'roles' 应该存在于JWT中,其值应该是一个包含 'default' 的数组。这可以通过Envoy实现如下:

我进行了一些研究,找到了一种验证受众 'aud' 和发行者 'iss' 的方法。

http_filters:
  - name: envoy.filters.http.jwt_authn
    typed_config: 
      "@type": type.googleapis.com/envoy.extensions.filters.http.jwt_authn.v3.JwtAuthentication
      providers:
        "auth-iam":
          issuer: https://url
          forward: true
          audiences:
          - 123123-1232-123123-2323-123
          remote_jwks:
            http_uri:
              uri: https://url/keys
              cluster: auth-iam
              timeout: 5s
            cache_duration:
              seconds: 900                        
      rules:  
        - match:
            prefix: /actuator/health
        - match:
            prefix: /
          requires:
            provider_name: auth-iam
英文:
{
  "aud": "123123-1232-123123-2323-123",
  "iss": "https://url",
  "iat": 2112,
  "nbf": 1212,
  "exp": 1212,
  "aio": "ewq32ee23e2e=",
  "azp": "123123-1232-123123-2323-123",
  "azpacr": "1",
  "oid": "123123-1232-123123-2323-123",
  "rh": "1.qqfn4wanflwf3aldAAA.",
  "roles": [
    "default"
  ],
  "sub": "123123-1232-123123-2323-123"
}

My JWT contains the above claims. i have to validate 3 things

  1. audience : aud
  2. issuer : iss
  3. roles : 'roles' should be present in JWT. Its value array should contain 'default'. How can this be achieved with envoy?

I researched a bit and found a way to validate audience 'aud' and issuer 'iss'.

  http_filters:
    - name: envoy.filters.http.jwt_authn
      typed_config: 
        "@type": type.googleapis.com/envoy.extensions.filters.http.jwt_authn.v3.JwtAuthentication
        providers:
          "auth-iam":
            issuer: https://url
            forward: true,
            audiences:
            - 123123-1232-123123-2323-123  # [audience]
            remote_jwks:
              http_uri:  # [3]
                uri: https://url/keys # [simple]
                cluster: auth-iam
                timeout: 5s
              cache_duration:
                seconds: 900                        
        rules:  
          - match:
              prefix: /actuator/health
          - match:
              prefix: /
            requires:
              provider_name: auth-iam

答案1

得分: 1

我通过添加一个Lua过滤器并编写一个Lua脚本来验证令牌声明,实现了上述操作。它分为以下2个步骤:

  1. 将JWT的有效载荷添加到变量 jwt_payload
- name: envoy.filters.http.jwt_authn
  typed_config:
    "@type": type.googleapis.com/envoy.extensions.filters.http.jwt_authn.v3.JwtAuthentication
    providers:
      "auth-iam":
        issuer: https://url,
        forward: true
        audiences:
        - 123123-1232-123123-2323-123
        remote_jwks:
          http_uri:
            uri: https://login.microsoftonline.com/common/discovery/v2.0/keys
            cluster: auth-iam
            timeout: 5s
        cache_duration:
          seconds: 900
        payload_in_metadata: jwt_payload
        rules: 
          - match:
              prefix: /health
          - match:
              prefix: /
            requires:
              provider_name: auth-iam
  1. 检索有效载荷并编写自定义逻辑来验证令牌声明。该过滤器应添加在 - name: envoy.filters.http.router 的上方。
- name: envoy.filters.http.lua
  typed_config:
    "@type": type.googleapis.com/envoy.extensions.filters.http.lua.v3.Lua
    inline_code: |
      function envoy_on_request(request_handle)
        local meta = request_handle:streamInfo():dynamicMetadata()
        for key, value in pairs(meta) do
          if (value.jwt_payload.roles == nil or value.jwt_payload.roles[1] ~= "default") then
            request_handle:respond({[":status"] = "403",}, "JWT验证失败。") 
          end
        end
      end      
英文:

i was able to acheive the above by adddding a lua filter and writing a lua script to validate token claims. it works in these 2 steps :

  1. add the payload from JWT to a variable jwt_payload.

    - name: envoy.filters.http.jwt_authn
      typed_config:
        "@type": type.googleapis.com/envoy.extensions.filters.http.jwt_authn.v3.JwtAuthentication
        providers:
          "auth-iam":
            issuer: https://url,
            forward: true
            audiences:
            - 123123-1232-123123-2323-123
            remote_jwks:
              http_uri:
                uri: https://login.microsoftonline.com/common/discovery/v2.0/keys
                cluster: auth-iam
                timeout: 5s
              cache_duration:
                seconds: 900
            payload_in_metadata: jwt_payload
            rules: 
              - match:
                  prefix: /health
              - match:
                  prefix: /
                requires:
                  provider_name: auth-iam
    
  2. retreive the payload and write custom logic to validate the token claims. the filter would be added just above - name: envoy.filters.http.router

    - name: envoy.filters.http.lua
      typed_config:
        "@type": type.googleapis.com/envoy.extensions.filters.http.lua.v3.Lua
        inline_code: |
          function envoy_on_request(request_handle)
            local meta = request_handle:streamInfo():dynamicMetadata()
            for key, value in pairs(meta) do
              -- request_handle:logInfo("extract dynamicMetadata key: "..key)
              -- request_handle:logInfo("extract dynamicMetadata value: "..value.jwt_payload.roles[1])
              if(value.jwt_payload.roles == nil or value.jwt_payload.roles[1] ~= "default")
              then
                request_handle:respond({[":status"] = "403",},"JWT validation failed.") 
              end
            end
          end
    

huangapple
  • 本文由 发表于 2023年2月6日 13:54:00
  • 转载请务必保留本文链接:https://go.coder-hub.com/75357764.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定