Retrieve a Token Exchange Chain API

On this page

Enterprise plan To use Token Exchange, you'll need an Enterprise plan.

Available since 1.70.0

An exchanged token can itself be exchanged again. This API returns the entry for the exchange that issued a token, followed by the entries for each earlier exchange in its chain. The entries come from the Token Exchange audit log. To search the audit log, use the Search the Token Exchange Audit Log API.

Request#

API Key Authentication
Retrieve the exchange chain for an issued token
GET/api/system/token-exchange-audit-log/chain?issuedTokenJti={issuedTokenJti}

Query Parameters#

issuedTokenJti
  • Type: String
  • Required

The jti claim of the issued token.

tenantId
  • Type: UUID
  • Optional

Restricts the chain to entries belonging to the given Tenant. This parameter is overridden if the request contains an X-FusionAuth-TenantId header, or if the API key is scoped to a specific Tenant. Without a Tenant, the chain includes entries from every Tenant.

Response#

Response Codes
CodeDescription
200The request was successful. The response will contain a JSON body.
400The request was invalid and/or malformed. The response will contain an Errors JSON Object with the specific errors. This status will also be returned if a paid FusionAuth license is required and is not present.
401You did not supply a valid Authorization header. The header was omitted or your API key was not valid. The response will be empty. See Authentication.
404No retained entry issued a token with the given jti, or the entry belongs to a different Tenant.
500There was an internal error. A stack trace is provided and logged in the FusionAuth log files. The response will be empty.
503The search index is not available or encountered an exception so the request cannot be completed. The response will contain a JSON body.

Response Body#

tokenExchangeAuditLogs
  • Type: Array

The entries in the chain, starting with the exchange that issued the requested token and ending with the first exchange.

The chain stops early when an earlier entry is no longer retained, or when a subject token wasn't itself issued through token exchange.

tokenExchangeAuditLogs[x].actChain
  • Type: String

The act claim of the issued token, serialized as a JSON string. Only present when FusionAuth issued a token.

tokenExchangeAuditLogs[x].delegationSemantics
  • Type: String

The kind of exchange. This value is always DELEGATION. Only present when FusionAuth issued a token.

tokenExchangeAuditLogs[x].eventId
  • Type: UUID

The unique Id of the entry.

tokenExchangeAuditLogs[x].exchangerClientId
  • Type: UUID

The Id of the exchanger Entity. Absent when client authentication failed for an unknown client.

tokenExchangeAuditLogs[x].grantedAudience
  • Type: String

The space-delimited audiences of the issued token.

tokenExchangeAuditLogs[x].grantedScope
  • Type: String

The space-delimited scopes of the issued token.

tokenExchangeAuditLogs[x].insertInstant
  • Type: Long

The instant when FusionAuth recorded the attempt.

tokenExchangeAuditLogs[x].intent
  • Type: String

The value of the intent request parameter.

tokenExchangeAuditLogs[x].issuedTokenJti
  • Type: String

The jti claim of the issued token.

tokenExchangeAuditLogs[x].outcome
  • Type: String

The outcome of the attempt. The possible values are:

  • CLIENT_AUTHENTICATION_FAILED: the exchanger's client credentials were invalid.
  • CLIENT_DISALLOWED: the exchanger Entity doesn't have actAsTokenExchangeClient enabled.
  • CLIENT_REQUEST_FAILURE: the request parameters were invalid.
  • DEPTH_EXCEEDED: the subject token's actor chain already reached the Tenant's maximum depth.
  • POLICY_DENIED: the policy engine denied the exchange.
  • POLICY_LAMBDA_ERROR: the Token Exchange Policy lambda failed or returned an invalid result.
  • POPULATE_LAMBDA_ERROR: the Token Exchange Populate lambda failed.
  • SUBJECT_TOKEN_INVALID: the subject token failed validation.
  • SUCCESS: FusionAuth issued a token.
  • TENANT_DISALLOWED: the Tenant doesn't have token exchange enabled.
  • WEBHOOK_FAILURE: a webhook failed to accept the token.exchange event, so FusionAuth didn't return the token.
tokenExchangeAuditLogs[x].policyDecision
  • Type: String

The decision of the policy engine. The possible values are ALLOW, DENY, and ERROR. Only present when the policy engine ran.

tokenExchangeAuditLogs[x].policyDecisionDurationMs
  • Type: Integer

The time in milliseconds the policy engine took to decide. Only present when the policy engine ran.

tokenExchangeAuditLogs[x].policyEngine
  • Type: String

The policy engine that evaluated the exchange. The possible values are ENTITY and LAMBDA. Only present when the policy engine ran.

tokenExchangeAuditLogs[x].requestedAudience
  • Type: String

The space-delimited values of the audience and resource request parameters.

tokenExchangeAuditLogs[x].subjectTokenIss
  • Type: String

The iss claim of the subject token.

tokenExchangeAuditLogs[x].subjectTokenJti
  • Type: String

The jti claim of the subject token.

tokenExchangeAuditLogs[x].subjectTokenSub
  • Type: String

The sub claim of the subject token.

tokenExchangeAuditLogs[x].subjectTokenType
  • Type: String

The value of the subject_token_type request parameter.

tokenExchangeAuditLogs[x].subjectTokenValidationStatus
  • Type: String

How FusionAuth validated the subject token. The possible values are AUTHORITATIVE, BEST_EFFORT, and FAILED. Absent when the attempt failed before FusionAuth validated the subject token.

tokenExchangeAuditLogs[x].tenantId
  • Type: UUID

The Id of the Tenant that processed the exchange.

Example JSON Response
{
  "tokenExchangeAuditLogs": [
    {
      "actChain": "{\"sub\":\"email-service\",\"sub_profile\":\"fusionauth:API Service\",\"act\":{\"sub\":\"todo-service\",\"sub_profile\":\"fusionauth:API Service\"}}",
      "delegationSemantics": "DELEGATION",
      "eventId": "9c1d2e3f-4a5b-4c6d-8e7f-0a1b2c3d4e5f",
      "exchangerClientId": "7e6d5c4b-3a2f-4e1d-9c8b-7a6f5e4d3c2b",
      "grantedAudience": "template-service",
      "grantedScope": "openid offline_access",
      "insertInstant": 1792680005000,
      "issuedTokenJti": "d4c3b2a1-0f9e-4d8c-b7a6-5f4e3d2c1b0a",
      "outcome": "SUCCESS",
      "policyDecision": "ALLOW",
      "policyDecisionDurationMs": 3,
      "policyEngine": "ENTITY",
      "requestedAudience": "template-service",
      "subjectTokenIss": "https://piedpiper.fusionauth.io",
      "subjectTokenJti": "6b3a7d1e-4c8f-4b2a-9e55-0f1c2d3e4a5b",
      "subjectTokenSub": "c0a6ae6c-6d38-4bb5-a7c2-4d2b4e3a1f2d",
      "subjectTokenType": "urn:ietf:params:oauth:token-type:access_token",
      "subjectTokenValidationStatus": "AUTHORITATIVE",
      "tenantId": "30663132-6464-6665-3032-326466613934"
    },
    {
      "actChain": "{\"sub\":\"todo-service\",\"sub_profile\":\"fusionauth:API Service\"}",
      "delegationSemantics": "DELEGATION",
      "eventId": "e7d9b3f0-8c2a-4d1b-9e6f-1a2b3c4d5e6f",
      "exchangerClientId": "4b8f3b1a-6c2d-4f0e-9a7b-2d1c3e4f5a6b",
      "grantedAudience": "email-service",
      "grantedScope": "openid offline_access",
      "insertInstant": 1792680000000,
      "issuedTokenJti": "6b3a7d1e-4c8f-4b2a-9e55-0f1c2d3e4a5b",
      "outcome": "SUCCESS",
      "policyDecision": "ALLOW",
      "policyDecisionDurationMs": 4,
      "policyEngine": "ENTITY",
      "requestedAudience": "email-service",
      "subjectTokenIss": "https://piedpiper.fusionauth.io",
      "subjectTokenJti": "a1b2c3d4-e5f6-4890-abcd-ef1234567890",
      "subjectTokenSub": "c0a6ae6c-6d38-4bb5-a7c2-4d2b4e3a1f2d",
      "subjectTokenType": "urn:ietf:params:oauth:token-type:access_token",
      "subjectTokenValidationStatus": "AUTHORITATIVE",
      "tenantId": "30663132-6464-6665-3032-326466613934"
    }
  ]
}