JWT 认证

此 HTTP 过滤器可用于验证 JSON Web Token(JWT)。它将验证其签名、受众(audience)和发行人。它还将检查其时间限制,例如到期时间和 nbf(not before 不早于)时间。如果 JWT 验证失败,其请求将被拒绝。如果 JWT 验证成功,则可以将其有效负载转发到上游,以按需进行进一步授权。

需要 JWKS 来验证 JWT 签名。它们可以在过滤器配置中指定,也可以从 JWKS 服务器远程获取。

以下是支持的 JWT alg:

ES256, ES384, ES512,
HS256, HS384, HS512,
RS256, RS384, RS512,
PS256, PS384, PS512,
EdDSA

配置

此过滤器应的名称应该配置为 envoy.filters.http.jwt_authn

此 HTTP 过滤器配置 包含两个字段:

  • 字段 providers 指定应如何验证 JWT,例如在哪里提取令牌,在哪里获取公共密钥(JWKS)以及在何处输出其有效负载。

  • 字段 rules 指定匹配的规则及其 requirements。如果请求符合规则,则应用其 requirement。该 requirement 指定应使用哪些 JWT providers。

JwtProvider

JwtProvider 指定应如何验证 JWT。它具有以下字段:

  • issuer: 发行 JWT 的主体,通常是 URL 或电子邮件地址。

  • audiences: 允许访问的 JWT 受众列表。包含任何这些受众的 JWT 将被接受。如果未指定,将不检查 JWT 中的受众。

  • local_jwks: 在本地数据源中获取 JWKS,可以在本地文件中或嵌入在内联字符串中。

  • remote_jwks: 从远程 HTTP 服务器获取 JWKS,还可以指定缓存持续时间。

  • forward: 如果为 true,则将 JWT 转发到上游。

  • from_headers: 从 HTTP 头部中提取 JWT。

  • from_params: 从查询参数中提取 JWT。

  • forward_payload_header: 在指定的 HTTP 头部中转发 JWT 有效负载。

默认提取位置

如果 from_headersfrom_params 为空,则默认从 HTTP 头部提取 JWT:

Authorization: Bearer <token>

和查询参数的 key access_token

/path?access_token=<JWT>

如果一个请求有两个 token,一个来自 HTTP 头部,另一个来自 HTTP 查询参数,则所有这些 token 都必须有效。

过滤器配置中providers 是一个映射,用于将 provider_name 映射到 JwtProviderprovider_name 必须是唯一的,它被 JwtRequirement 中的 provider_name 字段引用。

Important

对于 remote_jwksjwks_cluster cluster 字段是必须提供的。

由于上述要求,OpenID Connect 发现 是不支持的,因为要获取 JWKS 的 URL 是基于响应发现的。为动态 URL 设置集群配置并不容易。

远程 JWKS 配置示例

providers:
  provider_name1:
    issuer: https://example.com
    audiences:
    - bookstore_android.apps.googleusercontent.com
    - bookstore_web.apps.googleusercontent.com
    remote_jwks:
      http_uri:
        uri: https://example.com/jwks.json
        cluster: example_jwks_cluster
      cache_duration:
        seconds: 300

上面的示例使用 URL https://example.com/jwks.json 从远程服务器获取 JWSK。令牌将从默认提取位置提取。令牌不会转发到上游。JWT 有效负载不会添加到请求头部中。

需要以下 cluster example_jwks_cluster 来获取 JWKS。

cluster:
  name: example_jwks_cluster
  type: STRICT_DNS
  load_assignment:
    cluster_name: example_jwks_cluster
    endpoints:
    - lb_endpoints:
      - endpoint:
          address:
            socket_address:
              address: example.com
              port_value: 80

内联 JWKS 配置示例

使用内联 JWKS 的另一个配置示例:

providers:
  provider_name2:
    issuer: https://example2.com
    local_jwks:
      inline_string: PUBLIC-KEY
    from_headers:
    - name: jwt-assertion
    forward: true
    forward_payload_header: x-jwt-payload

上面的示例使用内联字符指定 JWKS。JWT 令牌将从下面的 HTTP 头部中提取:

jwt-assertion: <JWT>.

JWT 有效负载将以以下格式添加到请求头部:

x-jwt-payload: base64url_encoded(jwt_payload_in_JSON)

RequirementRule

RequirementRule 具有两个字段:

  • 字段 match 指定如何匹配请求;例如通过 HTTP 头部,查询参数或路径前缀。

  • 字段 requires 指定 JWT requirement,例如需要哪个 provider。

Important

  • 如果一个请求匹配多个规则,则将应用第一个匹配的规则。.

  • 如果匹配规则的 requires 字段为空,则不需要 JWT 验证

  • 如果请求不符合任何规则,则不需要 JWT 验证

单一 requirement 配置示例

providers:
  jwt_provider1:
    issuer: https://example.com
    audiences:
      audience1
    local_jwks:
      inline_string: PUBLIC-KEY
rules:
- match:
    prefix: /health
- match:
    prefix: /api
  requires:
    provider_and_audiences:
      provider_name: jwt_provider1
      audiences:
        api_audience
- match:
    prefix: /
  requires:
    provider_name: jwt_provider1

上面的配置使用单个 requirement 规则,每个规则可以具有空 requirement 或具有一个 provider 名称的单个 requirement。

组 requirement 配置示例

providers:
  provider1:
    issuer: https://provider1.com
    local_jwks:
      inline_string: PUBLIC-KEY
  provider2:
    issuer: https://provider2.com
    local_jwks:
      inline_string: PUBLIC-KEY
rules:
- match:
    prefix: /any
  requires:
    requires_any:
      requirements:
      - provider_name: provider1
      - provider_name: provider2
- match:
    prefix: /all
  requires:
    requires_all:
      requirements:
      - provider_name: provider1
      - provider_name: provider2

上面的配置使用更复杂的*组* requirements:

  • 第一条 rule 指定 requires_any;如果满足 provider1provider2 的 requirement,请求可以继续。

  • 第二条 rule 指定 requires_all;只有同时满足 provider1provider2 的 requirements,请求才能继续。