---
title: Create a private key JWT
description: The PRIVATE_KEY_JWT property is a supported value on the application's tokenEndpointAuthMethod property. This client authentication method uses an external private key to sign a JWT, which is passed in as a property to authenticate the token request.
component: pingone-api
page_id: pingone-api:auth:auth-config-options/create-a-private-key-jwt
canonical_url: https://developer.pingidentity.com/pingone-api/auth/auth-config-options/create-a-private-key-jwt.html
section_ids:
  generate-a-keypair: Generate a keypair
  generate-a-signed-jwt: Generate a signed JWT
  use-the-jwt-in-a-token-request: Use the JWT in a token request
---

# Create a private key JWT

The `PRIVATE_KEY_JWT` property is a supported value on the application's `tokenEndpointAuthMethod` property. This client authentication method uses an external private key to sign a JWT, which is passed in as a property to authenticate the token request.

|   |                                                                                                                                                                                                                                                                                                                                                                                                                        |
| - | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|   | When you use a private key to sign a JWT, you must set the `jwks` (or `jwksUrl`) property on the application. For more information, refer to [Applications OIDC settings data model](../../platform/applications/applications-1.html#applications-oidc-settings-data-model). For information on creating a JWKS string, refer to [Create a private\_key\_jwt JWKS string](create-a-private-key-jwt-property-jwt.html). |

For JWT-based client authentication, the token supports the following required and optional claims.

| Claim | Type      | Required | Description                                                                                                                                                                                                                                                                                                           |
| ----- | --------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `iss` | String    | Required | A string that specifies the issuer. This value must match the application ID (client ID) of the PingOne application.                                                                                                                                                                                                  |
| `sub` | String    | Required | A string that specifies the identifier for the authenticated user. This value must match the application ID (client ID) of the PingOne application.                                                                                                                                                                   |
| `aud` | URI       | Required | A string that lists the audience, the resources for which this token is intended. Valid options are: (1) the token endpoint (`/as/token`), (2) the issuer uri (`/as`), (3) the endpoint being called (for example, `/as/introspect`). The value must be the full URL, including the PingOne domain, or custom domain. |
| `exp` | Timestamp | Required | A timestamp, measured in the number of seconds since January 1, 1970, UTC, indicating when this token will expire, as defined in [JWT RFC7519](https://tools.ietf.org/html/rfc7519). This JWT must not be expired. Tokens that expire more than one hour from now are rejected.                                       |
| `nbf` | Timestamp | Optional | A "not before" timestamp. If present, the JWT must be valid. JWTs are rejected if `nbf` is in the future.                                                                                                                                                                                                             |

Other properties of the JWT are:

* The optional `iat` and `jti` claims from the JSON Web Token (JWT) spec are not validated. Refer to [RFC7523 JWT Format and Processing Requirements](https://datatracker.ietf.org/doc/html/rfc7523#section-3).

* The JWT can include other claims in addition to those listed above.

* The JWT must be signed. For `PRIVATE_KEY_JWT` signing, the platform supports the RS256, RS384, and RS512 symmetric keyed hashing algorithm.

* The JWT must be valid.

## Generate a keypair

1. Use a keypair generator to create a keypair with the following configuration options. This example uses the `RS256` signing algorithm (`RS384`, and `RS512` are also supported).

   * Key size: 2048

   * Key use: signature

   * Algorithm: RS256

   * Key-ID: SHA-256

   * Show X.509: No

2. Save the generated **Public and Private Keypair** and the **Public Key**.

   * **Example public and private keypair**

     ```json
     {
     "p": "x1mRR-Y1_i8ZPTLe2sPmuif4hhIfaxSph8m_iACDEHvAfTh0RMV7SrExscRSUXzcWX_FbSIKE5tDm4c1qzImnmWz06z6SSQYUjl0iU6V439sebR662deH5kOF92Vbtj5OLk-mNdj-fm6CdwnWEp3vb36T9kOiKHGReluwJpG1I8",
     "kty": "RSA",
     "q": "tY0osG4YzkzTX_NCxN3QBFinw_hvJLX6zVXZ-PGHTOD0iFsdwCzmqa3o6_4-GtHUSiuoboTscx2ItbU824IDp41p99HLvSm0lZixszqlcG1JZSaQVj5_5rOBttTcovvAL5te4jq5Mi966WC3yT-V_ZLxE3jFNt5vNzW8ykxsAJ8",
     "d": "T_2qcj4Tb-wuMCvI3uOvBZza21PjzkCy5iTClT3QZ30Wlwm8A35x1b3MVHz7JGox3I_KvMClwQdrDMU2aibQaGzs_EunMH5Y1VhlKDg4RvuQBoyB9lpDT1TdrmDe7kHDPDERrB84gPQkrAm-RgJ0W_zPyJMR013pZjOwPKlxKYbsW1G02Jbg2Vl1zatNWBm1MFYQYEOYyaNQkt32WktNdgixYg0Qdt3Q160mbfNz5c9USLVqvCsye0J2t9DZPK7WzadQCC4S7ehdmQkGd87IfD4XyKuZND_nE8Nz5nbgOLNfuIwR6QH7ksOHT9ur1JVKkzEkX8P40_7LXdarwraiBQ",
     "e": "AQAB",
     "use": "sig",
     "kid": "q3sWApYjHZQLmWMUdAIqZiVWSshDdau5eI4K_Bm65Us",
     "qi": "t06uC_ML8E01gKSeFPH7LNFxpumuIaYBc_Enr10dB-wqGpYfs6B5yqf5SjlXg1K89Z3QZFcU9AdJW0SYtr9T-A7b3csxeWUW98hOwfXentP8vcSv3dXJI753f64tAZqz5Mgd6jh0D8i1Fvg6d7Hqm_a5cfd-DO80QkW9c8u8rmk",
     "dp": "L95hFWvBQVUb8WcavltWNxNMCR2m77aZcuLOHCFLV5TvxuHcgXsOPQRJk4852RlrbA5TYP5Qfx7EYD9acs5rGZQAV27s9s01DeGAC0yUj3lUmfDtp0M-BcZh7PcnX-O4DJfm4RqvhiIiOyXjSL8w-5330l6jr8lw6-6-yn8BTR8",
     "alg": "RS256",
     "dq": "lFS9ftClEcCxHn7Y-ZGkyDhK8ZFD9YF9ZVCUY5GqksRk5hdTylSlLNL7L_0sbqsrQGJFHe8aZL8nmBZ4n3utUrL2dlSBmo69jVARN7ddvep8gdktKlmsFChrfZ6SmdMIZZ0Su9FwyDEEwjKUVifOezwYHWmZ78dypHASTFJ-F08",
     "n": "jWA_vDxg41NrYJdIiv3BcljMy7V15bMyOyK5aJov6FgUTE2Xm_B9SqJu55qmS3CxVhvYWSpRIZvhrgap19CE_VnrAc5pzwj2oSEmDRXXFSGmMjHAmfTXU66nDZVmhbtDIBkPU-h55RDZf6zIn3SPOrmWJYj0G5X2fMJfbUOpuROjH1aMqqGOxcT-dX-LA0dd94LrH4J-g1HFeGZqw-uyQO8l1g6fbQYVaNvnHtw9V7U7I684Ks-3sZcU-YhexNhiN53izIglhdVva9pjSTUk4BnmYtSlfyF6HzUYkvg3H1S0Y6LqzW8lOIw8SF-L6jQqkT2DPDwDbxzNoaNx8lIE0Q"
     }
     ```

   * **Example public key**

     ```json
     {
     "kty": "RSA",
     "e": "AQAB",
     "use": "sig",
     "kid": "q3sWApYjHZQLmWMUdAIqZiVWSshDdau5eI4K_Bm65Us",
     "alg": "RS256",
     "n": "jWA_vDxg41NrYJdIiv3BcljMy7V15bMyOyK5aJov6FgUTE2Xm_B9SqJu55qmS3CxVhvYWSpRIZvhrgap19CE_VnrAc5pzwj2oSEmDRXXFSGmMjHAmfTXU66nDZVmhbtDIBkPU-h55RDZf6zIn3SPOrmWJYj0G5X2fMJfbUOpuROjH1aMqqGOxcT-dX-LA0dd94LrH4J-g1HFeGZqw-uyQO8l1g6fbQYVaNvnHtw9V7U7I684Ks-3sZcU-YhexNhiN53izIglhdVva9pjSTUk4BnmYtSlfyF6HzUYkvg3H1S0Y6LqzW8lOIw8SF-L6jQqkT2DPDwDbxzNoaNx8lIE0Q"
     }
     ```

## Generate a signed JWT

1. Create a signed JWT with with a signing algorithm of `RS256`, `RS384`, or `RS512` and header and payload information shown below.

   * **Header**

     ```json
     {
      "alg": "RS256",
      "typ": "JWT"
     }
     ```

   * **Payload**

     ```json
     {
      "iss": "{{appID}}",
      "sub": "{{appID}}",
      "exp": 1691085204,
      "aud": "https://auth.pingone.com/{{envID}}/as/token"
     }
     ```

2. Record the token returned successfully.

|   |                                                                                                                     |
| - | ------------------------------------------------------------------------------------------------------------------- |
|   | The value for `exp` must be valid. It cannot be in the past, and it cannot be set more than one hour in the future. |

## Use the JWT in a token request

For applications that set the `tokenEndpointAuthMethod` to `PRIVATE_KEY_JWT`, the token request requires the following two properties:

* `client_assertion`

  A JWT that contains a signed assertion with the application's credentials. This is the JWT that you generated and signed with your private key.

* `client_assertion_type`

  A string that specifies the client assertion type. The value of this property must be set to `urn:ietf:params:oauth:client-assertion-type:jwt-bearer`.

For more information about the token request, refer to [Token](../openid-connect-oauth-2/token-intro.html).
