diff --git a/envoy/config/filter/http/jwt_authn/v2alpha/BUILD b/envoy/config/filter/http/jwt_authn/v2alpha/BUILD new file mode 100644 index 000000000..cc07bd29b --- /dev/null +++ b/envoy/config/filter/http/jwt_authn/v2alpha/BUILD @@ -0,0 +1,13 @@ +licenses(["notice"]) # Apache 2 + +load("//bazel:api_build_system.bzl", "api_proto_library") + +api_proto_library( + name = "jwt_authn", + srcs = ["config.proto"], + deps = [ + "//envoy/api/v2/core:base", + "//envoy/api/v2/core:http_uri", + "//envoy/api/v2/route", + ], +) diff --git a/envoy/config/filter/http/jwt_authn/v2alpha/README.md b/envoy/config/filter/http/jwt_authn/v2alpha/README.md new file mode 100644 index 000000000..d7aac1ad9 --- /dev/null +++ b/envoy/config/filter/http/jwt_authn/v2alpha/README.md @@ -0,0 +1,31 @@ +# JWT Authentication HTTP filter config + +## Overview + +1. The proto file in this folder defines an HTTP filter config for "jwt_authn" filter. + +2. This filter will verify the JWT in the HTTP request as: + - The signature should be valid + - JWT should not be expired + - Issuer and audiences are valid and specified in the filter config. + +3. [JWK](https://tools.ietf.org/html/rfc7517#appendix-A) is needed to verify JWT signature. It can be fetched from a remote server or read from a local file. If the JWKS is fetched remotely, it will be cached by the filter. + +3. If a JWT is valid, the user is authenticated and the request will be forwarded to the backend server. If a JWT is not valid, the request will be rejected with an error message. + +## The locations to extract JWT + +JWT will be extracted from the HTTP headers or query parameters. The default location is the HTTP header: +``` +Authorization: Bearer +``` +The next default location is in the query parameter as: +``` +?access_token= +``` + +If a custom location is desired, `from_headers` or `from_params` can be used to specify custom locations to extract JWT. + +## HTTP header to pass sucessfully verified JWT + +If a JWT is valid, its payload will be passed to the backend in a new HTTP header specified in `forward_payload_header` field. Its value is base64 encoded JWT payload in JSON. diff --git a/envoy/config/filter/http/jwt_authn/v2alpha/config.proto b/envoy/config/filter/http/jwt_authn/v2alpha/config.proto new file mode 100644 index 000000000..adab17168 --- /dev/null +++ b/envoy/config/filter/http/jwt_authn/v2alpha/config.proto @@ -0,0 +1,226 @@ + +syntax = "proto3"; + +package envoy.config.filter.http.jwt_authn.v2alpha; + +import "envoy/api/v2/core/base.proto"; +import "envoy/api/v2/core/http_uri.proto"; +import "envoy/api/v2/route/route.proto"; +import "google/protobuf/duration.proto"; +import "validate/validate.proto"; + +// This message specifies how a JSON Web Token (JWT) can be verified. JWT format is defined +// `here `_. Please see `OAuth2.0 +// `_ and `OIDC1.0 `_ for +// the authentication flow. +// +// Example: +// +// .. code-block:: yaml +// +// issuer: https://example.com +// audiences: +// - bookstore_android.apps.googleusercontent.com +// bookstore_web.apps.googleusercontent.com +// remote_jwks: +// - http_uri: +// - uri: https://example.com/.well-known/jwks.json +// cluster: example_jwks_cluster +// cache_duration: +// - seconds: 300 +// +// [#not-implemented-hide:] +message JwtRule { + // Identifies the principal that issued the JWT. See `here + // `_. Usually a URL or an email address. + // + // Example: https://securetoken.google.com + // Example: 1234567-compute@developer.gserviceaccount.com + // + string issuer = 1 [(validate.rules).string.min_bytes = 1]; + + // The list of JWT `audiences `_. that are + // allowed to access. A JWT containing any of these audiences will be accepted. If not specified, + // will not check audiences in the token. + // + // Example: + // + // .. code-block:: yaml + // + // audiences: + // - bookstore_android.apps.googleusercontent.com + // bookstore_web.apps.googleusercontent.com + // + repeated string audiences = 2; + + // `JSON Web Key Set `_ is needed. to validate + // signature of the JWT. This field specifies where to fetch JWKS. + oneof jwks_source_specifier { + option (validate.required) = true; + + // JWKS can be fetched from remote server via HTTP/HTTPS. This field specifies the remote HTTP + // URI and how the fetched JWKS should be cached. + // + // Example: + // + // .. code-block:: yaml + // + // remote_jwks: + // - http_uri: + // - uri: https://www.googleapis.com/oauth2/v1/certs + // cluster: jwt.www.googleapis.com|443 + // cache_duration: + // - seconds: 300 + // + RemoteJwks remote_jwks = 3; + + // JWKS is in local data source. It could be either in a local file or embedded in the + // inline_string. + // + // Example: local file + // + // .. code-block:: yaml + // + // local_jwks: + // - filename: /etc/envoy/jwks/jwks1.txt + // + // Example: inline_string + // + // .. code-block:: yaml + // + // local_jwks: + // - inline_string: "ACADADADADA" + // + envoy.api.v2.core.DataSource local_jwks = 4; + } + + // If false, the JWT is removed in the request after a success verification. If true, the JWT is + // not removed in the request. Default value is false. + bool forward = 5; + + // Two fields below define where to extract the JWT from an HTTP request. + // + // If no explicit location is specified, the following default locations are tried in order: + // + // 1. The Authorization header using the Bearer schema. See `here + // `_. Example: + // + // Authorization: Bearer . + // + // 2. `access_token` query parameter. See `this + // `_ + // + + // Multiple JWTs can be verified for a request. Each JWT has to be extracted from the locations + // its issuer specified or from the default locations. + + // Specify the HTTP headers to extract JWT token. For examples, following config: + // + // .. code-block:: yaml + // + // from_headers: + // - name: x-goog-iap-jwt-assertion + // + // can be used to extract token from header:: + // + // x-goog-iap-jwt-assertion: . + // + repeated JwtHeader from_headers = 6; + + // JWT is sent in a query parameter. `jwt_params` represents the query parameter names. + // + // For example, if config is: + // + // .. code-block:: yaml + // + // from_params: + // - jwt_token + // + // The JWT format in query parameter is:: + // + // /path?jwt_token= + // + repeated string from_params = 7; + + // This field specifies the header name to forward a successfully verified JWT payload to the + // backend. The forwarded data is:: + // + // base64_encoded(jwt_payload_in_JSON) + // + // If it is not specified, the payload will not be forwarded. + // Multiple JWTs in a request from different issuers will be supported. Multiple JWTs from the + // same issuer will not be supported. Each issuer can config this `forward_payload_header`. If + // multiple JWTs from different issuers want to forward their payloads, their + // `forward_payload_header` should be different. + string forward_payload_header = 8; +} + +// This message specifies how to fetch JWKS from remote and how to cache it. +message RemoteJwks { + // The HTTP URI to fetch the JWKS. For example: + // + // .. code-block:: yaml + // + // http_uri: + // - uri: https://www.googleapis.com/oauth2/v1/certs + // cluster: jwt.www.googleapis.com|443 + // + envoy.api.v2.core.HttpUri http_uri = 1; + + // Duration after which the cached JWKS should be expired. If not specified, default cache + // duration is 5 minutes. + google.protobuf.Duration cache_duration = 2; +} + +// This message specifies a header location to extract JWT token. +message JwtHeader { + // The HTTP header name. + string name = 1 [(validate.rules).string.min_bytes = 1]; + + // The value prefix. The value format is "value_prefix" + // For example, for "Authorization: Bearer ", value_prefix="Bearer " with a space at the + // end. + string value_prefix = 2; +} + +// This is the Envoy HTTP filter config for JWT authentication. +// [#not-implemented-hide:] +message JwtAuthentication { + // List of JWT rules to valide. + repeated JwtRule rules = 1; + + // If true, the request is allowed if JWT is missing or JWT verification fails. + // Default is false, a request without JWT or failed JWT verification is not allowed. + bool allow_missing_or_failed = 2; + + // This field lists the patterns allowed to bypass JWT verification. This only applies when + // `allow_missing_or_failed_jwt` is false. Under this config, if a request doesn't have JWT, it + // will be rejected. But some requests still needed to be forwarded without JWT, such as OPTIONS + // for CORS and some health checking paths. + // + // Examples: bypass all CORS options requests + // + // .. code-block:: yaml + // + // bypass: + // - headers: + // - name: :method + // value: OPTIONS + // - headers: + // - name: :path + // regex_match: /.* + // + // Examples: bypass /healthz check + // + // .. code-block:: yaml + // + // bypass: + // - headers: + // - name: :method + // value: GET + // - headers: + // - name: :path + // exact_match: /healthz + // + repeated envoy.api.v2.route.RouteMatch bypass = 3; +}