---
title: Use a trusted issuer JWT for token enrichment
description: Explains how token exchange using a JWT from a trusted issuer can add additional mapped claims to a token
component: pingone-api
page_id: pingone-api:auth:auth-config-options/token-enrichment
canonical_url: https://developer.pingidentity.com/pingone-api/auth/auth-config-options/token-enrichment.html
llms_txt: https://developer.pingidentity.com/pingone-api/llms.txt
docs_for_agents: https://developer.pingidentity.com/build-with-ai/docs-for-agents.md
revdate: 2026-11-01
section_ids:
  runtime-flow-processing-details: Runtime flow processing details
  configuration-for-token-enrichment: Configuration for token enrichment
---

# Use a trusted issuer JWT for token enrichment

Token exchange in PingOne enables admins to map attributes from a source's subject or actor JWTs to the PingOne generated token to improve interoperability with OIDC applications. PingOne accepts JWTs from first-party or third-party sources, where the third-party sources are identified in PingOne as trusted issuers. Claims from these JWTs can be mapped to the PingOne generated tokens using the following expression variables:

```json
context.requestData.subjectToken
context.requestData.subjectTokenType
context.requestData.subjectTokenHeader
context.requestData.actorToken
context.requestData.actorTokenType
context.requestData.actorTokenHeader
context.requestData.requestedTokenType

context.requestData.subjectToken.[claimName]
context.requestData.subjectTokenHeader.[attributeName]
context.requestData.actorToken.[claimName]
context.requestData.actorTokenHeader.[attributeName]
```

Through a token exchange action, mapped claims from a trusted issuer's JWT can be added to a PingOne-generated access token. The configuration and runtime actions required for token enrichment from a third-party trusted issuer include:

1. Define the issuers that PingOne can trust. To learn more, refer to [Trusted issuers](../../platform/trusted-issuers/index.html).

2. Assign trusted issuers to the applications that need to use third-party signed JWTs from the assigned trusted issuers as inputs in their token-exchange token requests. To learn more, refer to [Application trusted issuer assignments](../../platform/applications/application-trusted-issuer-assignments/index.html).

3. Define attribute mappings in the resource attributes service that are the intended audiences of the access tokens in response to the token-exchange token requests. To learn more, refer to [Create resource attribute](../../platform/resources/resource-attributes/create-resource-attribute.html).

4. At runtime, send the token-exchange requests in which the subject or the actor token (or both) are signed JWTs from the application's assigned trusted issuers. To learn more, refer to [Token (token_exchange)](../openid-connect-oauth-2/token/token-token_exchange.html).

## Runtime flow processing details

Here are the high-level steps for processing a token exchange flow:

1. The PingOne authorization server receives the token exchange request with a specified `subject_token` property (and optional `actor_token` property) configured.

2. The PingOne authorization server validates the tokens:

   * The authorization server performs initial validation (introspection) of several claims such as (but not limited to) token expiration, JWT signature, and token revocation.

   * After that, validation is done through the admin-defined attribute mapping expressions.

3. The PingOne authorization server issues a new token that matches one of the `requested_token_type` values configured in the token request (for example, `requested_token_type=urn:ietf:params:oauth:token-type:access_token`).

4. The resource server or application receiving the issued token can perform additional validation, for example in a delegation use case where the `act` claim is present.

## Configuration for token enrichment

Here is a sample use case in which the resulting token is enriched with information from an ID token issued by PingFederate, a trusted issuer. Before calling the authorization server in Task 1 below, you must complete the steps to (1) define the trusted issuer, (2) assign the trusted issuer to the application, and (3) define the custom resource mapping. In this case, you will map the `securityLevel` attribute from the trusted issuer's actor token to the new `Security` claim in the resulting access token. The mapping expression in the custom resource, `#root.context.requestData.actorToken.securityLevel`, identifies the claim to add. After completing the configuration steps, you can initiate the authorization flow as follows:

**Task 1.** The application uses the authorization code flow to obtain an access token from PingOne with the following claims:

```json
{
  "client_id": "34265a22-7330-4e5f-9aee-a93f892d873e",
  "iss": "https://auth.pingone.com/c6bcf635-3289-4b4a-ae02-5d4332363521/as",
  "jti": "222a2445-b540-44eb-b96e-e538f5285d3e",
  "iat": 1792621957,
  "exp": 1792625557,
  "aud": [
    "https://www.example.com/?here=apiAddress"
  ],
  "scope": "openid a.read.email",
  "sub": "bc782d02-9abc-45d9-9124-e8ec62d07fe8",
  "sid": "d8875daf-3e18-4f6d-bc73-3ce40a06d35a",
  "auth_time": 1792604632,
  "acr": "Single_Factor",
  "email": "jsmith@pingidentity.com",
  "env": "c6bcf635-3289-4b4a-ae02-5d4332363521",
  "org": "d4229c38-0f5e-4bf7-9292-9d3b0df7294c"
}
```

**Task 2.** The application also obtains an ID token from the trusted issuer, PingFederate, with the following claims:

```json
{
  "sub": "jsmith",
  "aud": "ac_oic_client",
  "jti": "zHSThjqv7PAVk6QLLl7MYP",
  "iss": "https://ssoux1.js.ping-eng.com:9031",
  "iat": 1792621936,
  "exp": 1792625536,
  "sid": "Gv6upknTl9kEhMigRlbozknRlK8",
  "amr": [
    "oidcPolicy"
  ],
  "auth_time": 1792621932,
  "acr": "oidcPolicy",
  "securityLevel": "Class 3"
}
```

This ID token from PingFederate includes a custom claim named `securityLevel` with a value of `Class 3`. Using token exchange, you will add this claim to the access token.

**Task 3.** The application sends a token request using the token exchange grant type. In this sample, the application's `tokenEndpointAuthMethod` value is `CLIENT_SECRET_POST`, which does not require an `Authorization` header, and the `client_id` and `client_secret` properties are sent in the request body. The token request also includes the `subject_token`, `subject_token_type`, `actor_token`, and `actor_token_type` properties to identify the JWTs from the trusted issuer:

```curl
curl --location --globoff '{{authPath}}/{{envID}}/as/token' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--header 'Authorization: Basic e3thcHBJRH19Ont7YXBwU2VjcmV0fX0=' \
--data-urlencode 'client_id={{clientID}}' \
--data-urlencode 'client_secret={{clientSecret}}' \
--data-urlencode 'grant_type=urn:ietf:params:oauth:grant-type:token-exchange' \
--data-urlencode 'subject_token={{subToken}}' \
--data-urlencode 'subject_token_type=urn:ietf:params:oauth:token-type:access_token' \
--data-urlencode 'actor_token={{actToken}}' \
--data-urlencode 'actor_token_type=urn:ietf:params:oauth:token-type:id_token' \
--data-urlencode 'requested_token_type=urn:ietf:params:oauth:token-type:access_token' \
--data-urlencode 'scope={{scopeID}}'
```

PingOne returns a token response with the following claims:

```json
{
  "client_id": "34265a22-7330-4e5f-9aee-a93f892d873e",
  "iss": "https://auth.pingone.com/c6bcf635-3289-4b4a-ae02-5d4332363521/as",
  "jti": "af15d5cf-bb11-4934-9517-2742a8118163",
  "iat": 1792621982,
  "exp": 1792625582,
  "aud": [
    "https://www.example.com/?here=apiB"
  ],
  "scope": "write",
  "sub": "bc782d02-9abc-45d9-9124-e8ec62d07fe8",
  "sid": "d8875daf-3e18-4f6d-bc73-3ce40a06d35a",
  "auth_time": 1792604632,
  "acr": "Single_Factor",
  "bestie": "jsmith",
  "security": "Class 3",
  "env": "c6bcf635-3289-4b4a-ae02-5d4332363521",
  "org": "d4229c38-0f5e-4bf7-9292-9d3b0df7294c"
}
```

Based on the expression defined in the custom resource, the value from the `securityLevel` claim from the actor token is added as the `security` claim in the resulting access token.
