OIDC client (using the token exchange mechanism)
An OIDC client (using the token exchange mechanism) enables applications to exchange an existing access token for a new one, without requiring the customer to re-authenticate. This client type is used in scenarios where a token needs to be modified, for example, to change scopes, audiences, or claims, or to support delegation and impersonation flows.
Capabilities
Clients using the token exchange mechanism support the following scenarios:
- Scope changes: Request a new token with a reduced or modified set of scopes.
- Audience changes: Obtain a token targeted at a different resource server.
- Claim mapping: Modify or enrich token claims during exchange.
- Delegation: Use the
actclaim to act on behalf of another customer or entity. - Impersonation: Use the
may_actclaim to impersonate another customer, with the appropriate authorization.
Sample use cases
- Scope reduction for downstream services: An application receives an access token with broad scopes from Strivacity during customer login. When calling a downstream microservice, it only needs read-only access. Token exchange allows you to narrow that scope to only the needed one when the token is exchanged for a new one. This improves security by minimizing over-scoped tokens shared across internal services.
- Token for audience change between APIs: A frontend app authenticates a customer and receives a token with an audience of
api.frontend.strivacity.com. To call a partner API (api.partner.com), it needs a token scoped for that audience. Token exchange enables secure multi-audience access while preventing token misuse across unintended APIs. - Delegated access with act-as claim: A customer support portal allows support agents to act on behalf of end users to troubleshoot issues. Token exchange supports secure delegation patterns with full auditability and separation of roles.
Configuration
You can configure this client in the Admin Console under Applications → select application → Clients → select client.
OIDC clients (using the token exchange mechanism) include the following configuration tabs:
- General
- OAuth2/OIDC
- Token exchange
After saving the client, the following tabs become available:
- Claim mapping
- Logs
General
Use the General tab to define basic client properties.
- Name: name displayed in the client list in the Admin Console.
- Description: optional description visible only in the Admin Console.
- Enabled: enables or disables the client. Disabled clients cannot be used for token exchange.
- Application domain: defines which domain is used for this client. By default, the instance domain is used.
OAuth2/OIDC
The OAuth2/OIDC tab contains the OpenID Connect configuration for the client. These settings define how the client authenticates with Strivacity and how tokens are issued.
For a complete description of OAuth2/OIDC configuration options, see OAuth2/OIDC properties setup.
Token exchange
The Token exchange tab defines how token exchange requests are validated and how new tokens are issued.
Allowed exchange
Determines which type of token exchange is permitted:
- Impersonation (
may_actclaim): The client fully impersonates another customer, making requests as that customer. - Delegation (
actclaim): The client acts on behalf of another customer while retaining its own identity in the token chain.
Use case example: Enable delegation for a support application, while restricting impersonation to internal tools.
Allowed authorization servers
Defines which authorization servers are trusted when validating incoming tokens.
Subject tokens
Configure the properties of accepted subject tokens (the tokens to be exchanged):
- Token type: determines what type of token is accepted.
- Currently supported:
urn:ietf:params:oauth:token-type:access_token
- Currently supported:
- Issuer: the authorization server that issued the token.
- JWKS URI: the endpoint used to validate the token signature.
Use Add subject token to allow multiple authorization servers.
Settings
Allowed audiences
Defines which aud (audience) values are allowed in the exchanged token. This is critical in audience change scenarios, where tokens are reissued for use with different downstream APIs or services.
Use Add audience to specify one or more allowed audiences.
Use case example: A frontend app can exchange a token for one with an audience of orders-api.strivacity.com, but not admin-api.strivacity.com.
Allowed resources
Specifies which resource identifiers (resource parameter) are valid targets for exchanged tokens. This setting acts as an additional constraint for resource-specific access and complements the audience setting. Useful when APIs support multiple logical resource partitions under the same audience.
Use Add resource to specify allowed resources.
Use case example: Allow tokens to be scoped only to orders and inventory resources, not billing.
Scopes
Controls how scopes are applied to the exchanged token:
- Pass through only: scopes from the original token are preserved.
- Allow the following scopes: restricts the exchanged token to a predefined set of scopes.
Use case example: A service exchanges a token but is only allowed to request read:users, even if the original token has broader scopes like write:users.
Subject token account ID mapping
Defines how the subject token is mapped to a customer account in Strivacity.
Use this field to specify which claim or identifier from the subject token should be used to resolve the customer account.
Claim mapping
The Claim mapping tab becomes available after the client is saved. Use this tab to define a JavaScript function that customizes the token issued during token exchange.
The function can:
- Add custom claims to the issued access token
- Override the requested scopes
- Reject token issuance with a custom error
The function receives the following arguments:
- request_body: request body of the token exchange request.
- requested_scopes: list of requested scopes. If scope passthrough is used and no scopes are requested, this contains the scopes from the subject token.
- account: subject customer account.
Return a ClaimMapping object to continue issuing the token. Throw DenyRequest to reject token issuance.
Code example:
module.exports = async function ({ request_body, requested_scopes, account }) {
return new ClaimMapping({ custom: "data" });
}; Use case example:
Use the sub claim from the input token to:
- Look up the customer’s department in your HR system.
- Add department and
manager_idclaims to the output token. - Rename
email_verifiedtois_email_verified.
Logs
The Logs tab provides access to token exchange activity for the client. Use this tab to monitor and troubleshoot token exchange requests.
Columns
The log table includes the following columns:
- Date: date and time of the token exchange event.
- Log level counts: number of log entries by level for the given time.
Filters
Use the available filters to narrow down log results:
- Date: filter logs by a specific time range.
- Account ID: filter logs for a specific customer account.
- Account event ID: filter logs by event identifier.
- Log level: filter logs by log severity or type.
Token exchange example calls and responses
Scope reduction for downstream services
An application receives a broadly scoped access token from the login flow. Before calling a downstream microservice, it exchanges the token for one with a reduced set of scopes, following the principle of least privilege.
Configuration:
- Allowed exchange: Delegation or impersonation.
- Scopes: Restrict to
read:orders.
Token exchange request
Original token with read:orders and read:profile scopes:
POST /oauth2/token
Content-Type: application/x-www-form-urlencoded
Authorization: Basic <client_credentials>
grant_type=urn:ietf:params:oauth:grant-type:token-exchange
&subject_token=eyJhbGciOi...originalToken...
&subject_token_type=urn:ietf:params:oauth:token-type:access_token
&scope=read:read:orders read:profile
Response
New token with only read:orders scope:
{
"access_token": "eyJhbGciOi...reducedScopeToken...",
"issued_token_type": "urn:ietf:params:oauth:token-type:access_token",
"token_type": "Bearer",
"expires_in": 3600,
"scope": "read:orders"
}Audience change
A frontend application receives a token scoped for its own API (api.frontend.com). Before calling a partner service (api.partner.com), it exchanges the token for one with a new aud value.
Configuration
- Allowed audiences: api.partner.com
Token exchange request
POST /oauth2/token
Content-Type: application/x-www-form-urlencoded
Authorization: Basic <client_credentials>
grant_type=urn:ietf:params:oauth:grant-type:token-exchange
&subject_token=eyJhbGciOi...originalToken...
&subject_token_type=urn:ietf:params:oauth:token-type:access_token
&audience=api.partner.com
Response
{
"access_token": "eyJhbGciOi...newAudienceToken...",
"issued_token_type": "urn:ietf:params:oauth:token-type:access_token",
"token_type": "Bearer",
"expires_in": 3600,
}Decoded JWT payload
{
"sub": "user_123",
"aud": "api.partner.com",
"scope": "",
"iss": "{issuer}",
"iat": 1724487400,
"exp": 1724491000
}Delegation (act-as)
A support dashboard application allows agents to act on behalf of customers to perform troubleshooting. The agent’s client uses token exchange to produce a delegated token with an `act' claim representing the customer.
Policy settings
- Allowed exchange type: Delegation.
- Allowed authorization servers: Must accept both subject and actor tokens from trusted issuers.
- Scope handling: May be restricted to limited scopes (e.g.,
support:read). - Claim mapping: Optional, policies can forward or transform claims from either token.
Token inputs
Subject token (Decoded JWT Payload)
Represents the end user (customer):
{
"sub": "user_123",
"email": "[email protected]",
"tenant_id": "acme",
"iss": "https://login.strivacity.com",
"iat": 1724487600,
"exp": 1724491200
}
Actor Token (Decoded JWT payload)
Represents the support agent:
{
"sub": "support_agent_456",
"email": "[email protected]",
"role": "support",
"iss": "https://login.strivacity.com",
"iat": 1724487650,
"exp": 1724491250
}Token exchange request
Request includes the JWT subject token and actor token to use in the resulting delegated token.
POST /oauth2/token
Content-Type: application/x-www-form-urlencoded
Authorization: Basic <client_credentials>
grant_type=urn:ietf:params:oauth:grant-type:token-exchange&
subject_token=eyJhbGciOi...subjectToken...&
subject_token_type=urn:ietf:params:oauth:token-type:access_token&
actor_token=eyJhbGciOi...actorToken...&
actor_token_type=urn:ietf:params:oauth:token-type:access_token
Response (token exchange output)
Response is a bearer token with an access token in the JWT payload:
{
"access_token": "eyJhbGciOi...delegatedAccessToken...",
"issued_token_type": "urn:ietf:params:oauth:token-type:access_token",
"token_type": "Bearer",
"expires_in": 3600
}Resulting access token (decoded JWT payload)
The resulting access token includes the support agent’s identifier as the root “sub” claim and the customer's identifier in the “sub” claim under the “act” claim.
{
"sub": "support_agent_456",
"scope": "support:read user:read",
"tenant_id": "acme",
"act": {
"sub": "user_123"
},
"iss": "https://login.strivacity.com",
"iat": 1724487700,
"exp": 1724491300
}Claim mapping
Claim mapping allows you to modify or enrich the token claims in the resulting token during exchange. The claim mapping code block allows for mapping data into the new token from:
- The original token
- From an identity store
- From a 3rd party data source
Response 200 from claim mapping
Claim mapping code
module.exports = async function ({ request_body, requested_scopes, account }) {
return new ClaimMapping({ custom: "data" });
}; Content of the token in response
"custom": "data" appears at top level
{
"aud": [
"hodor"
],
"client_id": "d3b7292ee8594f97a255d7c7c0221071",
"custom": "data",
"exp": 1753346210,
"ext": {
"given_name": "2188e297-780e-4ed4-b342-706378def084"
},
"given_name": "2188e297-780e-4ed4-b342-706378def084",
"iat": 1753342610,
"iss": "https://demo.strivacity.cloud/",
"jti": "74873dfa-5c20-4d43-b64e-3e0c9d0117b2",
"may_act": {
"sub": "d3b7292ee8594f97a255d7c7c0221071"
},
"nbf": 1753342610,
"scp": [
"joska"
],
"sub": "2188e297-780e-4ed4-b342-706378def084"
}Updated 7 days ago
