---
title: Authenticate clients with JWT profiles
description: Clients can send a signed JWT to the authorization server as credentials instead of the client ID and/or secret, as per (RFC 7523) JWT Profile for OAuth 2.0 Client Authentication and Authorization Grants. The authorization server must be able to validate the JWT to authenticate the client.
component: pingam
version: 7.2
page_id: pingam:oauth2-guide:client-auth-jwt
canonical_url: https://docs.pingidentity.com/pingam/8.1/am-oauth2/client-auth-jwt.html
llms_txt: https://docs.pingidentity.com/pingam/llms.txt
docs_for_agents: https://developer.pingidentity.com/build-with-ai/docs-for-agents.md
superseded_by: https://docs.pingidentity.com/pingam/8.1/am-oauth2/client-auth-jwt.html
---

# Authenticate clients with JWT profiles

Clients can send a signed JWT to the authorization server as credentials instead of the client ID and/or secret, as per [(RFC 7523) JWT Profile for OAuth 2.0 Client Authentication and Authorization Grants](https://www.rfc-editor.org/info/rfc7523). The authorization server must be able to validate the JWT to authenticate the client.

The following diagram demonstrates the JWT Bearer client authentication flow:

![JWT Bearer Client Authentication](https://kroki.io/plantuml/svg/eNplUs1u2zAMvuspCPfQBmjiLtgpKAIEBQZsWLEiSbvLgEKWaVurLHkS3TR9-lHS0jWpThLJ74ciy3MBfG7csPe67QjmV58-T-dX8znAF-dbXDv1BKvNDFbGwDqWBFhjQP-MtUjY-4DgGqBOB1CuRvD4Z9QeA0h-9z16paWB4BraSY9gtELLmJ2m7lgj0TmfM84mWs16smm00ZIwZBsjo0Mn-VYh4IsyY9DPaPYQxuo3Kko85Pipuje5CmmHaNnnmwUEaesTCwm7ddCiRc-S3ETgftAqhFrL1sseGu_63C_7wksYvFMYQoJqyvbvjLR0f_v9EjqiYVGWQwyMvZkFN3qFTVSdWaTyQD_rqDfivBRyJGfHvkIPxXW1PDubFEJU7gWKG6PREihpY-dfQxjRF0l2kJ600gNrHMoKkAHy9WPJP2wsyVeB_BUsIo7KVre_7Gqkznn9Kkk7C5s4-QyMidf8FiILTZeZbcE7wl0Fgm8_t0Lk4HSZixYxCBdBtxbryX_oO74F3P3YbPNPqpR-lIGXLlmIQzsNPtJ-QCHeUZzwPUij6zjPZOio7uCK13pwcVUueDi8V7If4nSTCf5xqeKQea-e0E7EX52YGVM=?id=figure-oauth2-jwt-bearer-authn)Figure 1. JWT Bearer Client Authentication

1. The client requests a JWT from the issuer.

   |   |                                                                                                                                                                                                                            |
   | - | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
   |   | Clients usually generate their own JWTs before starting the OAuth 2.0/OpenID Connect flow, but they can delegate the task to a specific service in your environment if required. AM cannot generate JWTs for this purpose. |

2. The issuer returns a signed JWT to the client.

   The JWT must contain, at least, the following claims in the payload:

   * **iss**. Specifies the unique identifier of the JWT *issuer*. This could also be the client, or a third party.

   * **sub**. Specifies the principal who is the *subject* of the JWT. Must be set to the client ID.

   * **aud**. Specifies the authorization server that is the intended *audience* of the JWT. Must be set to the authorization server's token endpoint. For example, `https://openam.example.com:8443/openam/oauth2/realms/root/realms/alpha/access_token`.

     |   |                                                                                                                                                                                                                                       |
     | - | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
     |   | To specify additional audiences permitted when verifying the JWT, set the [Additional Audience Values](../reference/global-services-configuration.html#oauth-provider-additional-audience-values) property of the OAuth 2.0 provider. |

   * **exp**. Specifies the *expiration time*.

     Providing a JWT with an expiry time greater than 30 minutes causes AM to return a `JWT expiration time is unreasonable` error message.

   * **jti**. Specifies a random, *unique identifier for the JWT*.

     This claim is *required* if the client requests the `openid` scope and optional otherwise.

   For more information about the JWT, read the [RFC 7523](https://www.rfc-editor.org/rfc/rfc7523.html#section-3) standard.

   The JWT issuer must digitally sign the JWT or have a Message Authentication Code (MAC) applied by the issuer. When the issuer is also the client, the client can sign the JWT by using a private key.

   AM ignores keys specified in JWT headers, such as \`jku\` and \`jwe\`. Regardless of who issues the JWT, you must configure the public key or HMAC secret in the client profile so AM can validate it:

   > **Collapse: Configuring certificates represented as PEM files**
   >
   > 1. In the AM admin UI, go to Realms > *Realm Name* > Applications > OAuth 2.0 > *Client Name* > Signing and Encryption.
   >
   > 2. In the Client JWT Bearer Public Key field, enter the public certificate. For example:
   >
   >    ```none
   >    -----BEGIN CERTIFICATE-----
   >    MIIDETCCAfmgAwIBAgIEU8SXLjAN...
   >    -----END CERTIFICATE-----
   >    ```
   >
   >    You can only enter one certificate.
   >
   > 3. In the Public key selector drop-down list, select `X509`.

   > **Collapse: Configuring Public Keys in JWK Format**
   >
   > You can either enter the JWK Set in the client profile, or store the JWK Set in a URI that exposes it to AM:
   >
   > * To store the JWK Set in the client profile:
   >
   >   1. In the AM admin UI, go to Realms > *Realm Name* > Applications > OAuth 2.0 > *Client Name* > Signing and Encryption.
   >
   >   2. In the Json Web Key field, enter the JWK Set. For example:
   >
   >      ```json
   >      {
   >        "keys": [
   >          {
   >            "alg": "RSA-OAEP-256",
   >            "kty": "RSA",
   >            "use": "sig",
   >            "kid": "RemA6Gw0...LzsJ5zG3E=",
   >            "n": "AL4kjz74rDo3VQ3Wx...nhch4qJRGt2QnCF7M0",
   >            "e": "AQAB"
   >          }
   >        ]
   >      }
   >      ```
   >
   >      Enter a JWK Set with multiple JWKs if you plan to rotate certificates.
   >
   >   3. In the Public key selector drop-down list, select `JWKs`.
   >
   > * To store the JWK Set in a URI:
   >
   >   1. In the AM admin UI, go to Realms > *Realm Name* > Applications > OAuth 2.0 > *Client Name* > Signing and Encryption.
   >
   >   2. In the \[.label]# Json Web Key URI# field, configure the URI that exposes the JWK Set.
   >
   >      Ensure that the following related properties have sensible values for your environment:
   >
   >      * JWKs URI content cache timeout in ms
   >
   >      * JWKs URI content cache miss cache time
   >
   >   Store a JWK Set with multiple JWKs if you plan to rotate certificates.
   >
   >   1. In the Public key selector drop-down list, select `JWKs_URI`.

   > **Collapse: Configuring HMAC secrets**
   >
   > 1. In the AM admin UI, go to Realms > *Realm Name* > Applications > OAuth 2.0 > *Client Name* > Core.
   >
   > 2. In the Client secret field, enter the HMAC secret. For more information about the length of the secret, see the [Symmetric Key Entropy](https://openid.net/specs/openid-connect-core-1_0.html#SymmetricKeyEntropy) section of the OpenID Connect specification.
   >
   >    You can only enter one HMAC secret.

   |   |                                                                                                                                                                                               |
   | - | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
   |   | OpenID Connect clients must also specify the authentication method they are using in their client profiles. See [OpenID Connect client authentication](../oidc1-guide/oidc-client-auth.html). |

3. The client includes the JWT and a client assertion type in the call to the OAuth 2.0 endpoint in the following parameters:

   * `client_assertion_type=urn%3Aietf%3Aparams%3Aoauth%3Aclient-assertion-type%3Ajwt-bearer`

   * `client_assertion=my_JWT`

   For example:

   ```bash
   $ curl \
   --request POST \
   --data "client_assertion_type=urn%3Aietf%3Aparams%3Aoauth%3Aclient-assertion-type%3Ajwt-bearer" \
   --data "client_assertion=eyAiYWxnIjogIlJTMjU2IiB9.eyAic3ViIjogImp3…​" \
   …​
   ```

4. The authorization server validates the JWT with the public key stored in the client profile.

5. The authorization server issues a response to the client. This response may include, for example, an access token.

A sample Java-based client to test the JWT token bearer flow is provided.

For information on downloading and building AM sample source code, see [How do I access and build the sample code provided for PingAM?](https://support.pingidentity.com/s/article/How-do-I-access-and-build-the-sample-code-provided-for-PingAM) in the *Knowledge Base*.
