---
schema_version: "1"
id: 61a3314fd25d22b9dc29d6c500cdebed5ec8fb76452c2bb7b25fb4fc0537c6ef
title: JWT Validation Policy
collection: mulesoft
version: current
locale: en-us
portal_url: https://docs.salesforce.com/mulesoft/current/en-us/gateway/1.13/policies-included-jwt-validation.md
canonical_url: https://docs.mulesoft.com/gateway/1.13/policies-included-jwt-validation
source_site: docs.mulesoft.com
content_type: documentation
content_hash: aa2c0011de658ca44718e748f78ea91b5dc1302be1728a87028966c61a90cbd3
description: MuleSoft Documentation Site
release: "1.13"
latest: false
---
---
product: Omni Gateway
version: 1.13
keywords: jwt validation, api gateway, flex gateway, gateway, policy
---

# JWT Validation Policy

> For the full documentation index, see: https://docs.mulesoft.com/llms.txt

<table><colgroup><col> <col></colgroup><tbody><tr><td><p><strong>Policy name</strong></p></td><td><div><div><p>JWT Validation</p></div></div></td></tr><tr><td><p><strong>Summary</strong></p></td><td><div><div><p>Validates a JWT</p></div></div></td></tr><tr><td><p><strong>Category</strong></p></td><td><div><div><p>Security</p></div></div></td></tr><tr><td><p><strong>First Omni Gateway version available</strong></p></td><td><div><div><p>v1.0.0</p></div></div></td></tr><tr><td><p><strong>Release Notes</strong></p></td><td><div><div><p><a href="https://docs.mulesoft.com/release-notes/gateway/policies/jwt-validation-release-notes">JWT Validation</a></p></div></div></td></tr><tr><td rowspan="4"><p><strong>Returned Status Codes</strong></p></td><td><div></div></td></tr><tr><td><div><div><p>400 - Token was not provided in the request.</p></div><table><colgroup><col> <col></colgroup><tbody><tr><td rowspan="3"><div><div><p>401</p></div></div></td><td><div><div><p>Signature was not validated, or is invalid.</p></div></div></td></tr><tr><td><div><div><p>Some of the required claims are not present or their validation failed.</p></div></div></td></tr><tr><td><div><div><p>Failed to parse the token.</p></div></div></td></tr></tbody></table></div></td></tr></tbody></table>

## Summary

JSON Web Token (JWT) is a URL-secure method of representing claims to be transferred between two
parties. The claims in a JWT are encoded as a JSON object that is used as the payload of a JSON Web
Signature (JWS), or as a JSON web encryption (JWE) structure in plain text. This enables the claims
to be digitally signed and integrity protected with a message authentication code (MAC). Because the
token is signed, you can trust the information and its source.

The JWT Validation policy validates the signature of the token and asserts the values of the claims
of all incoming requests by using a JWT with JWS format. The policy does not validate JWT that uses
JWE.

## Configuring Policy Parameters

### Omni Gateway Local Mode

When you apply the policy via declarative configuration files, Refer to the following policy
definition and table of parameters:

\- policyRef: name: jwt-validation-flex config:

<table><colgroup><col> <col> <col> <col></colgroup><thead><tr><th>Parameter</th><th>Required or Optional</th><th>Default Value</th><th>Description</th></tr></thead><tbody><tr><td><div><div><p><code>signingMethod</code></p></div></div></td><td><div><div><p>Optional</p></div></div></td><td><div><div><p><code>rsa</code></p></div></div></td><td><div><div><p>String containing the key signing method. Supported values: <code>rsa</code>, <code>hmac</code>, <code>es</code>, <code>none</code></p></div></div></td></tr><tr><td><div><div><p><code>signingKeyLength</code></p></div></div></td><td><div><div><p>Optional</p></div></div></td><td><div><div><p>256</p></div></div></td><td><div><div><p>Number indicating key length. Supported values are 256, 384, 512. For ES method, Omni Gateway supports 256 and 384 key lengths.</p></div></div></td></tr><tr><td><div><div><p><code>textKey</code></p></div></div></td><td><div><div><p>Optional</p></div></div></td><td><div><div><p><code>your-(256|384|512)-bit-secret/your-public-pem-certificate</code></p></div></div></td><td><div></div></td></tr><tr><td><div><div><p><code>jwtOrigin</code></p></div></div></td><td><div><div><p>Optional</p></div></div></td><td><div><div><p><code>httpBearerAuthenticationHeader</code></p></div></div></td><td><div></div></td></tr><tr><td><div><div><p><code>jwtKeyOrigin</code></p></div></div></td><td><div><div><p>Optional</p></div></div></td><td><div><div><p><code>text</code></p></div></div></td><td><div></div></td></tr><tr><td><div><div><p><code>jwksUrl</code></p></div></div></td><td><div><div><p>Optional</p></div></div></td><td><div><div><p><code><a href="http://your-jwks-service.example:80/base/path">http://your-jwks-service.example:80/base/path</a></code></p></div></div></td><td><div><div><p>JWKS server URLs that contain the public keys for the signature validation. Configure multiple JWKS servers with a comma-separated list of the URLs.</p></div></div></td></tr><tr><td><div><div><p><code>jwksServiceTimeToLive</code></p></div></div></td><td><div><div><p>Optional</p></div></div></td><td><div><div><p>60</p></div></div></td><td><div><div><p>Amount of time, in minutes, during which the policy considers the JWKS valid.</p></div></div></td></tr><tr><td><div><div><p><code>jwksServiceConnectionTimeout</code></p></div></div></td><td><div><div><p>Optional</p></div></div></td><td><div><div><p>10000</p></div></div></td><td><div><div><p>Maximum time, in milliseconds, to wait for a response from each JWKS service when authenticating the access token validation endpoint.</p></div></div></td></tr><tr><td><div><div><p><code>validateAudClaim</code></p></div></div></td><td><div><div><p>Optional</p></div></div></td><td><div><div><p><code>false</code></p></div></div></td><td><div></div></td></tr><tr><td><div><div><p><code>mandatoryAudClaim</code></p></div></div></td><td><div><div><p>Optional</p></div></div></td><td><div><div><p><code>false</code></p></div></div></td><td><div></div></td></tr><tr><td><div><div><p><code>mandatoryNbfClaim</code></p></div></div></td><td><div><div><p>Optional</p></div></div></td><td><div><div><p><code>false</code></p></div></div></td><td><div></div></td></tr><tr><td><div><div><p><code>mandatoryExpClaim</code></p></div></div></td><td><div><div><p>Optional</p></div></div></td><td><div><div><p><code>false</code></p></div></div></td><td><div></div></td></tr><tr><td><div><div><p><code>supportedAudiences</code></p></div></div></td><td><div><div><p>Optional</p></div></div></td><td><div><div><p>Empty string</p></div></div></td><td><div></div></td></tr><tr><td><div><div><p><code>validateCustomClaim</code></p></div></div></td><td><div><div><p>Optional</p></div></div></td><td><div><div><p><code>false</code></p></div></div></td><td><div></div></td></tr><tr><td><div><div><p><code>mandatoryCustomClaims</code></p></div></div></td><td><div><div><p>Optional</p></div></div></td><td><div><div><p>Empty array</p></div></div></td><td><div></div></td></tr><tr><td><div><div><p><code>nonMandatoryCustomClaims</code></p></div></div></td><td><div><div><p>Optional</p></div></div></td><td><div><div><p>Empty array</p></div></div></td><td><div></div></td></tr><tr><td><div><div><p><code>jwtExpression</code></p></div></div></td><td><div><div><p>Optional</p></div></div></td><td><div><div><p><code>#[attributes.headers['jwt']]</code></p></div></div></td><td><div></div></td></tr><tr><td><div><div><p><code>skipClientIdValidation</code></p></div></div></td><td><div><div><p>Required</p></div></div></td><td><div><div><p><code>true</code></p></div></div></td><td><div><div><p>This parameter must be set to <code>true</code> in Local Mode.</p></div></div></td></tr><tr><td><div><div><p><code>clientIdExpression</code></p></div></div></td><td><div><div><p>Optional</p></div></div></td><td><div><div><p><code>#[vars.claimSet.client_id]</code></p></div></div></td><td><div></div></td></tr></tbody></table>

### Managed Omni Gateway and Omni Gateway Connected Mode

When you apply the policy from the UI, the following parameters are displayed:

<table><colgroup><col> <col> <col></colgroup><thead><tr><th>Element</th><th>Description</th><th>Example</th></tr></thead><tbody><tr><td><p>JWT Origin</p></td><td><p>Specifies from where in the request the JWT will be extracted: * HTTP Bearer Authentication Header * Custom Expression</p><p>If you set this field to <code>HTTP Bearer Authentication Header</code>, the JWT is expected as Bearer.<br>If you set this field to <code>Custom Expression</code>, provide a DataWeave expression that returns the token.</p></td><td></td></tr><tr><td><p>Token Expression</p></td><td><p>If you set the JWT Origin to <code>Custom Expression</code>, type the DataWeave expression returning the JWT here.</p></td><td><p><code>#[attributes.headers['jwt']]</code><br>This expression searches the JWT in the header named <code>jwt</code>.</p></td></tr><tr><td><p>JWT Signing Method</p></td><td><p>Specify the signing method expected in the incoming JWT. The policy rejects the token if the JWT has a different signing method.</p></td><td><p>RSA, HMAC, ES, None</p></td></tr><tr><td><p>JWT Signing Key Length</p></td><td><p>Specify the length of the key (in the case of the HMAC algorithm) or the algorithm (in the case of RSA) used for the signing method.<br>Ignore this field if you selected <strong>none</strong> as JWT Signing Method.</p></td><td><p>256, 384, 512. For ES method, Omni Gateway only supports 256 and 384 key lengths.</p></td></tr><tr><td><p>JWT Key Origin</p></td><td><p>Specifies where to obtain the key for the Signature validation.<br>You can provide the key in the policy by selecting the <strong>Text</strong> option or by obtaining it from a <strong>JWKS</strong>.<br>Ignore this field if you selected <strong>none</strong> as JWT Signing Method.</p></td><td></td></tr><tr><td><p>JWT Key</p></td><td><p>This field appears if you selected <strong>Text</strong> as JWT Key Origin.<br>Use this field to provide the key used to check the signature of the token.<br>Ignore this field if you selected <strong>none</strong> as JWT Signing Method.</p></td><td><p>Enter a 32, 48, or 64 character string shared secret for HMAC, a 32 character string shared secret for ES, or the PEM Public Key without the header and footer for RSA.</p></td></tr><tr><td><p>JWKS URL</p></td><td><p>This field appears if you selected the <strong>JWKS</strong> method as JWT Key Origin.<br>Ignore this field if you selected <strong>none</strong> as JWT Signing Method.</p></td><td><p>JWKS server URLs that contain the public keys for the signature validation. Configure multiple JWKS servers with a comma-separated list of the URLs.</p></td></tr><tr><td><p>JWKS Caching Time To Live</p></td><td><p>Amount of time, in minutes, that the JWKS is valid. When the JWKS expires, the policy retrieves the JWKS from each JWKS server again. The default value is 60 minutes.<br>Ignore this field if you selected <strong>none</strong> as JWT Signing Method.</p></td><td><p>This field input is the amount of time, in minutes, during which the policy considers the JWKS valid.</p></td></tr><tr><td><p>JWKS Service connection timeout (milliseconds)</p></td><td><p>Maximum time, in milliseconds, to wait for a response from each JWKS service when authenticating the access token validation endpoint.<br>The default value is 10 seconds.</p></td><td></td></tr><tr><td><p>Skip Client ID Validation</p></td><td><p>If you check this field, the policy does not verify that the client ID extracted from the JWT matches a valid client application of the API.</p></td><td></td></tr><tr><td><p>Client ID Expression</p></td><td><p>If Skip Client Id Validation is not set, the client ID needs to be extracted from the token.</p></td><td><p>By default, the value will be extracted using the expression <code>#[vars.claimSet.client_id]</code> as specified in the <a href="https://tools.ietf.org/html/draft-ietf-oauth-token-exchange-16#section-4.3" target="_blank" rel="noopener">Oauth 2.0 token exchange draft</a>.</p></td></tr><tr><td><p>Validate Audience Claim</p></td><td><p>Indicates that the policy should check for the validity of the audience claim. You can set this "Mandatory" if you select <strong>Audience Claim Mandatory</strong>.</p></td><td></td></tr><tr><td><p>Validate Expiration Claim</p></td><td><p>Indicates that the policy should check for the validity of the expiration claim. You can set this claim as "Mandatory" by selecting <strong>Expiration Claim Mandatory</strong>.</p></td><td></td></tr><tr><td><p>Validate Not Before Claim</p></td><td><p>Indicates that the policy should check for the validity of the Not Before claim. You can set this claim as "Mandatory" by selecting <strong>Not Before Claim Mandatory</strong></p></td><td></td></tr><tr><td><p>Validate Custom Claim</p></td><td><p>Enables the usage of custom validations in the policy. The JWT will be valid only if all DataWeave expressions are fulfilled.</p></td><td><p>The policy provides a <em>claimSet</em> variable that contains all the claims present in the incoming JWT. For example:</p><p><code>foo : #[vars.claimSet.foo == 'fooValue']</code></p><p>Note that all DataWeave expressions must return a boolean value or they will always fail.</p></td></tr></tbody></table>

## How This Policy Works

The policy validates claims and signatures differently, as explained in this section.

### Validating Signatures

The policy validates the signature of the JWT based on the values specified in the policy
configuration. If the algorithm specified in the policy configuration does not match with the token,
or if the signature of the token is invalid, all JWTs are rejected by the policy. If no algorithm is
specified, the policy matches every signed and unsigned token.

The algorithms that support signature verification are:

- **Symmetric algorithms** - HMAC using SHA-256, SHA-384, and SHA-512.

- **Asymmetric algorithms** - ES and RSA using SHA-256, SHA-384, and SHA-512.

- **None** - No signature validation.

For more information about the algorithms in a JWS structure, refer to the
[JWA RFC standard](https://tools.ietf.org/html/rfc7518#section-3.1).

### Validating Claims

Claim validations enable you to choose the conditions under which a token received in the policy is
rejected. The following registered claim validations are provided by default:

- **aud**: The Audience validation specifies that a token must be rejected if it does not contain at
  least one of the values defined.

- **exp**: The Expiration validation specifies that a token must be rejected if its date is past the
  validation date.

- **nbf**: The Not before validation specifies that the token must be rejected if the validation
  time is before the time the token has.

In addition to these _provided claims_, you can also specify other claims to use in your
validations. For all claims, _Registered_ or _Custom_, you must provide the following details:

- The name of the claim you want to validate.  
  For example **iss**, for the issuer of the token.

- The value used to test.  
  You can provide a simple literal value if you only need to verify it, or you can provide a
  DataWeave expression for more complex comparisons.

You can define each claim validation as mandatory or non-mandatory. If a claim is defined as
mandatory and is not present in the incoming JWT, the policy rejects this token. If a claim is
defined as non-mandatory and is not present in the incoming JWT, the policy does not reject the
token for that specific validation.  
For both cases, if a claim is present, the policy validates the token value. If the validation
fails, the JWT will be rejected.

### Propagating Claims

After the policy parses and validates the JWT, the claims are propagated to downstream policies and
flows through the **claims** property in the authentication object.

To access the claim values you can use the following Dataweave 2.0 expression by replacing
`<claimName>` with the name of the desired claim to access:

`#[authentication.properties.claims.<claimName>]`

The JWT is also propagated downstream, and you can access it by using the following Dataweave 2.0
expression:

`#[authentication.properties.jwt]`

#### Propagating Client ID

If Client ID validation is enabled, the Client ID is propagated as a claim and as a reserved
authentication property. Access the property by using the following DataWeave expression:

`#[authentication.clientId]`

### Retry Mechanism

If you selected JSON Web Key Set (JWKS) as JWT Key Origin, the policy uses a retry mechanism to
handle failed JWKS fetches. Every time the cached JWKS expires or is absent and a new request is
triggered, a request is sent to each JWKS service. If a request fails, a sequence of asynchronous
requests with an exponential backoff delay is sent to the failed JWKS service until a new JWKS is
obtained and cached again.

Until the recaching finishes, the expired JWKS is used to process the request, and a `503` error is
returned if no request is found. Using an expired JWKS enables you to apply cached values in
upcoming requests, even if the previous requests failed.

## Obtain a Policy Compatible PEM Public Key

If you have a preexisting RSA key in an unsupported format that you want to use, first covert the
key to a PEM public key. The JWT policy uses public RSA key in PEM format.

**Task Prerequisite**

Before you convert your existing key:

1.  Obtain the `public.pem` key.

2.  Before you paste the key to the policy configuration, remove the **\-----BEGIN PUBLIC KEY-----**
    header and the **\-----END PUBLIC KEY-----** footer.

The following table provides instructions for how to convert your existing key based on its current
format:

<table><colgroup><col> <col></colgroup><thead><tr><th>Starting Point</th><th>Procedure</th></tr></thead><tbody><tr><td><div><div><p>No previous certificate</p></div></div></td><td><div><div><ol><li><p>Generate the private RSA key <code>openssl genrsa -out key.pem 2048</code></p></li><li><p>Extract the public key from the generated private key <strong>key.pem</strong> <code>openssl rsa -in key.pem -outform PEM -pubout -out public.pem</code></p></li><li><p>The public key will be in the file public.pem</p></li></ol></div></div></td></tr><tr><td><div><div><p>PEM Certificate</p></div></div></td><td><div><div><ol><li><p>Extract the public key from the PEM certificate <code>openssl x509 -inform pem -in cert.pem -pubkey -noout &gt; public.pem</code></p></li><li><p>The public key will be in the file public.pem</p></li></ol></div></div></td></tr><tr><td><div><div><p>DER Certificate</p></div></div></td><td><div><div><ol><li><p>Extract the public key from the DER certificate <code>openssl x509 -inform der -in cert.crt -pubkey -noout &gt; public.pem</code></p></li><li><p>The public key will be in the file public.pem</p></li></ol></div></div></td></tr><tr><td><div><div><p>x5c field from JWKS</p></div></div></td><td><div><div><ol><li><p>Copy the first certificate from the chain and decode it <code>echo &lt;certificateString&gt; | base64 -D &gt; cert.crt</code> (replace <code>&lt;certificateString&gt;</code> with the copied value)</p></li><li><p>Extract the public key from the DER certificate <code>openssl x509 -inform der -in cert.crt -pubkey -noout &gt; public.pem</code></p></li><li><p>The public key will be in the file public.pem</p></li></ol></div></div></td></tr></tbody></table>
