JWT Authentication
JWKS is needed to verify JWT signatures. They can be specified in the filter config or can be fetched remotely from a JWKS server.
Attention
ES256, ES384, ES512, HS256, HS384, HS512, RS256, RS384 and RS512 are supported for the JWT alg.
This filter should be configured with the name envoy.filters.http.jwt_authn.
This HTTP filter config has two fields:
Field providers specifies how a JWT should be verified, such as where to extract the token, where to fetch the public key (JWKS) and where to output its payload.
Field rules specifies matching rules and their requirements. If a request matches a rule, its requirement applies. The requirement specifies which JWT providers should be used.
specifies how a JWT should be verified. It has the following fields:
issuer: the principal that issued the JWT, usually a URL or an email address.
audiences: a list of JWT audiences allowed to access. A JWT containing any of these audiences will be accepted. If not specified, the audiences in JWT will not be checked.
local_jwks: fetch JWKS in local data source, either in a local file or embedded in the inline string.
remote_jwks: fetch JWKS from a remote HTTP server, also specify cache duration.
from_headers: extract JWT from HTTP headers.
from_params: extract JWT from query parameters.
forward_payload_header: forward the JWT payload in the specified HTTP header.
Default Extract Location
If from_headers and from_params is empty, the default location to extract JWT is from HTTP header:
If fails to extract a JWT from above header, then check query parameter key access_token as in this example:
In the , providers is a map, to map provider_name to a JwtProvider. The provider_name must be unique, it is referred in the JwtRequirement <envoy_api_msg_config.filter.http.jwt_authn.v2alpha.JwtRequirement> in its provider_name field.
Important
For remote_jwks, a jwks_cluster cluster is required.
Due to above requirement, is not supported since the URL to fetch JWKS is in the response of the discovery. It is not easy to setup a cluster config for a dynamic URL.
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:
Above example fetches JWSK from a remote server with URL https://example.com/jwks.json. The token will be extracted from the default extract locations. The token will not be forwarded to upstream. JWT payload will not be added to the request header.
Following cluster example_jwks_cluster is needed to fetch JWKS.
Inline JWKS config example
Another config example using inline 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
JWT payload will be added to the request header as following format:
RequirementRule has two fields:
Field match specifies how a request can be matched; e.g. by HTTP headers, or by query parameters, or by path prefixes.
Field requires specifies the JWT requirement, e.g. which provider is required.
Important
If a request matches multiple rules, the first matched rule will apply.
If the matched rule has empty requires field, JWT verification is not required.
If a request doesn’t match any rules, JWT verification is not required.
Single requirement config example
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
api_audience
- match:
prefix: /
requires:
provider_name: jwt_provider1
Above config uses single requirement rule, each rule may have either an empty requirement or a single requirement with one provider name.
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: provider2
Above config uses more complex group requirements:
The first rule specifies requires_any; if any of provider1 or provider2 requirement is satisfied, the request is OK to proceed.