JWT validation

Extensions for applying the protection:

  • x-42c-jwt-validation_0.1
  • x-42c-jwt-validation-ec_0.1
  • x-42c-jwt-validation-hmac_0.1
  • x-42c-jwt-validation-rsa_0.1
  • x-42c-jwt-validation_0.2
  • x-42c-jwt-validation-ec_0.2
  • x-42c-jwt-validation-hmac_0.2
  • x-42c-jwt-validation-rsa_0.2
  • x-42c-jwt-validation_0.3
  • x-42c-jwt-validation-ec_0.3
  • x-42c-jwt-validation-hmac_0.3
  • x-42c-jwt-validation-rsa_0.3

The numbers at the end of the extension denote the version of the protection: for example, x-42c-jwt-validation_0.1 applies the version 0.1 of the protection, x-42c-jwt-validation_0.2 the version 0.2, and so forth.

You apply protections to your API as strategies by using the x-42c security extensions, either locally to specific paths, operations, responses, or HTTP status codes, or alternatively to all incoming requests or outgoing responses. For more details, see Protections and security extensions.

Description

JSON Web Tokens (JWT) tokens are the primary format of tokens used for API authentication. In most cases, the tokens used are signed but not encrypted. Attackers can try to break into your system by intercepting and reusing, modifying, or even creating a token of their own and relying on the backend improperly validating the token. This protection externalizes JWT validation checks and adds an additional layer of protection against JWT attacks.

You can apply this protection to your OpenAPI definition in two ways:

  • Use the extension x-42c-jwt-validation and specify the algorithms API Firewall can use to validate the JWT regardless of which algorithm the token is signed with.
  • Use one of the following extensions to automatically validate the JWT against a specific algorithm family (all algorithms in the family are allowed):
    • x-42c-jwt-validation-ec: The JWT is validated against the Elliptic Curve algorithm family (ES256, ES384, and ES512).
    • x-42c-jwt-validation-hmac: The JWT is validated against the Keyed-hash Message Authentication Code algorithm family (HS256, HS384, and HS512).
    • x-42c-jwt-validation-rsa: The JWT is validated against the RSA algorithm family (RS256, RS384, RS512, PS256, PS384, and PS512).

This way, you can choose the level of control and definition that you want to use.

Direction

This protection applies only to incoming requests, not outgoing responses. The JWT must be passed in a HTTP header and in the format of JWS Compact Serialization. You can specify the name of validated header with the parameter header.name.

JWT header and claims validation process

API Firewall performs the JWT header and claims validation as follows:

  1. Check if the header defined in the parameter header.name is included in the request.
  2. Check if the JWT format corresponds to the pattern of JWS Compact Serialization. The regular expression used is ^([0-9a-zA-Z\-=_]{20,})\.([0-9a-zA-Z\-_=]{3,})\.([0-9a-zA-Z\-_=]*)$.
  3. Check that the algorithm (field alg) in the key structure definition (JWK) matches the field alg in the JOSE header of the JWT.
  4. Check that the key type can be used to validate the JWT token. The value of the field kty must correspond to the alg fields in both JWK and JOSE header.
  5. Check that the field alg is present in the JOSE header, its value matches authorized algorithms, and the signing algorithm is not NONE.
  6. Check the claims of the payload. If no claims are present in the payload, this step is skipped.
    • The claim nbf must be before the current time.
    • The claim exp must be after the current time.
    • The claim iat corresponds to the token lifetime. The iat value plus the value of the lifetime parameter defined for the protection must not exceed the value of the claim exp.
    • The claim jti must not be present in the API Firewall cache. This claim protects against replay attack. The claim jti is stored in the API Firewall cache until the jti.timeout of the protection expires.

      API Firewall ignores the jti claim if you use the _0.2 extensions to apply the newer version of the JWT validation protection. However, the value of the claim is still validated against the schema for the payload before it is passed on to downstream services, such as the authorization server.

  7. Check the message integrity with a cryptographic signature validation.

If any of the checks fail, the protection blocks the request.

JWK configuration

Because API Firewall runs in a container, like a Kubernetes pod, you can configure the JWK as a secret and pass it to API Firewall as an environment variable.

The JWK must contain at least the following fields:

  • kty: The key type. The value must be EC, RSA, or oct.
  • alg: The algorithm of the key.

Other fields are possible and strongly depend on the used key type. For more details, see RFC 7517.

The following is an example of the key configuration in Kubernetes (angle brackets indicate placeholders):

  1. Create the JWK environment file <my-jwk.env>:
    <JWK-ENV-VAR-NAME>={"kty": "oct", "alg": "HS256", "k": "b3dhc3Bicm9rZW53ZWJhcHBz"}
    
  2. Run the following to create the Kubernetes secret:
    kubectl create secret generic <my-jwk-secret-name> --from-env-file=/path/to/<my-jwk.env> --namespace=<my-k8s-namespace>
  3. Add the environment variable for the JWK to the deployment file of your API Firewall deployment, under the section /spec/template/spec/container/<container name>/env:
    env:
      - name: <JWK-ENV-VAR-NAME>
        valueFrom:
           secretKeyRef:
              name: <my-jwk-secret-name>
              key: <JWK-ENV-VAR-NAME>

When you redeploy the updated API Firewall deployment, the environment variable is passed to API Firewall and this protection can access it through the parameter jwk.envvar.

You can pass the public key required to validate the signature inside an environment variable, or retrieve it dynamically using the parameter jwks.uri if applying the protection with _0.2 extensions. See Parameters.

Parameters

You can configure the following parameters for the different versions of the protection:

Parameter name Description Version
header.name Required. The name of the HTTP header that contains the JWT. All
authorized.algorithms Required for x-42c-jwt-validation. An array of the algorithms API Firewall must use to validate the JWT.

You cannot mix algorithms from different algorithm families (for example, ES256 and RS256) in your list due to the nature of JWK.

All
jwk.envvar The environment variable that contains the JSON Web Key (JWK) token that API Firewall can access. The environment variable is set as a secret (for example, a Kubernetes secret) and declared in the API Firewall deployment properties (see JWK configuration). The default value is JWK. This parameter is optional. All
forward.jwt If set to true (default), the JWT is forwarded to the backend service, otherwise it is removed from the message. This parameter is optional. All
lifetime Token lifetime (in seconds). You can use this parameter to specify the maximum lifetime of the JWT. For this parameter to have effect, the claim iat must be present in the payload. The default value is 5. This parameter is optional. All
drift Drift time (in seconds) to allow a small leeway in case there is clock skew between the client and API Firewall. This parameter is used when checking claims dealing with time, such as like nbf and exp. The default value is 10. This parameter is optional. All
jti.timeout Timeout value (in seconds) to protect the API backend from replay attacks. For this parameter to have effect, the claim jti must be present in the payload. The jti value is removed from the cache after the timeout expires. The default value is 86400 (one day). This parameter is optional.

Because the API Firewall instance stores all counters in its memory, if the instance is restarted, all values in the cache are lost.

jti claim is ignored in _0.2
allow.basic.value If set to true, the value of the authorization header is enforced to start with Basic or Digest token, other tokens are rejected. This can be useful if your API can accept both Basic or Bearer token depending on client, and it allows JWT validation to proceed if the authentication is passed. The default value is false. This parameter is optional. _0.2 only
jwk.cache.timeout The value (in seconds) for how long the JWK retrieved from the JWKS URI is cached. The allowed timeout range is 6028800 (from 1 minute to 8 hours). The default value is 3600. This parameter is optional. _0.2 only
jwks.uri The URI of JWKset (for example, https://login.microsoftonline.com/common/discovery/v2.0/keys). This parameter is optional: if JWKS URI is not provided, the policy looks for an environment variable (defaults to JWK) that contains the JWK used to validate the signature. _0.2 only
jwks.proxy The host:port of the forward proxy that API Firewall must connect through using the HTTP CONNECT method to reach the JWKS endpoint. This parameter is required if traffic to the JWKS endpoint should go through a forward proxy. _0.3 only

API Firewall ignores the jti claim if you use the _0.2 extensions to apply the newer version of the JWT validation protection. However, the value of the claim is still validated against the schema for the payload before it is passed on to downstream services, such as the authorization server.

Examples

x-42c-jwt-validation

Versions:

  • x-42c-jwt-validation_0.1
  • x-42c-jwt-validation_0.2
  • x-42c-jwt-validation_0.3

If you apply the protection using the protection name jwt-validation_<version>, you can specify an array of algorithms in the protection parameter authorized.algorithms. API Firewall uses the specified algorithms (and only them) to validate JWT headers and claim regardless of what algorithms they use.

/api/user/info: 
    get: 
        x-42c-local-strategy:
            x-42c-strategy:
                protections:
                    - x-42c-jwt-validation_0.1: 
                        header.name: x-access-token
                        jwk.envvar: JWK_PUBLIC_RSA_KEY
                        authorized.algorithms: [RS256, RS384]
                    # ...

x-42c-jwt-validation-ec

Versions:

  • x-42c-jwt-validation-ec_0.1
  • x-42c-jwt-validation-ec_0.2
  • x-42c-jwt-validation-ec_0.3

If you apply the protection using the protection name x-42c-jwt-validation-ec_<version>, API Firewall automatically uses only the algorithms ES256, ES384, or ES512 of the Elliptic Curve family to validate the JWT headers and claims.

The protection also checks that the curve if the field crv of the JWK matches the curve of the algorithm set in the field alg:

  • Curve P-256 for ES256
  • Curve P-384 for ES384
  • Curve P-512 for ES512

For more details, see RFC 7517 and RFC 7518.

/api/user/info: 
    get: 
        x-42c-local-strategy:
            x-42c-strategy:
                protections:
                    - x-42c-jwt-validation-ec_0.1: 
                        header.name: x-access-token
                        jwk.envvar: JWK_PUBLIC_EC_KEY
                    # ... 

x-42c-jwt-validation-hmac

Versions:

  • x-42c-jwt-validation-hmac_0.1
  • x-42c-jwt-validation-hmac_0.2
  • x-42c-jwt-validation-hmac_0.3

If you apply the protection using the protection name x-42c-jwt-validation-hmac_<version>, API Firewall automatically uses only the algorithms HS256, HS384, or HS512 of the HMAC algorithm family to validate the JWT headers and claims.

/api/user/info: 
    get: 
        x-42c-local-strategy:
            x-42c-strategy:
                protections:
                    - x-42c-jwt-validation-hmac_0.1: 
                        header.name: x-access-token
                    # ...

x-42c-jwt-validation-rsa

Versions:

  • x-42c-jwt-validation-rsa_0.1
  • x-42c-jwt-validation-rsa_0.2
  • x-42c-jwt-validation-rsa_0.3

If you apply the protection using the protection name x-42c-jwt-validation-rsa_<version>, API Firewall automatically uses only the algorithms of the RSA algorithm family to validate the JWT headers and claims.

/api/user/info: 
    get: 
        x-42c-local-strategy:
            x-42c-strategy:
                protections:
                    - x-42c-jwt-validation-rsa_0.1:
                        header.name: x-access-token
                        jwk.envvar: JWK_PUBLIC_RSA_KEY
                    # ...