Home

Documentation

Documentation

Step 3: Refresh Token → ID-JAG

Exchange the Refresh Token from Step 2 for an ID-JAG (Identity Assertion Authorization Grant), targeting a specific Authorization Server and resource. This is the second §4.5 exchange (TE ②), and it produces the same kind of ID-JAG the OIDC path does, carrying the SAML identity in a sub_id claim.

Request parameters

ParameterRequiredValue
grant_typeYesurn:ietf:params:oauth:grant-type:token-exchange
subject_tokenYesThe Refresh Token from Step 2
subject_token_typeYesurn:ietf:params:oauth:token-type:refresh_token
requested_token_typeYesurn:ietf:params:oauth:token-type:id-jag
audienceYesThe Authorization Server URL. Becomes the ID-JAG's aud claim.
resourceYesThe Resource Server API URL. Becomes the resource claim.
scopeOptionalRequested scopes (e.g., todos.read)
client_idYesYour IdP client ID
client_secretYesYour IdP client secret
audience vs resource

audience identifies who will validate the ID-JAG (the Authorization Server); resource identifies what will be accessed (your API). Both are required, and both must match a resource connection on your SAML app, or the request is rejected with invalid_target.

Implementation

Response

JSON
FieldDescription
access_tokenThe ID-JAG token
issued_token_typeConfirms this is an ID-JAG
token_typeN_A (the ID-JAG is not a bearer token; it's an assertion for Step 4)
expires_inToken lifetime in seconds (5 minutes)
scopeGranted scopes
The Refresh Token is single-use for this exchange

IdenX revokes the Refresh Token the moment it issues the ID-JAG, so a stolen Refresh Token can't be exchanged twice. Need another ID-JAG? Run Step 1 and Step 2 again to get a fresh Refresh Token.

Decoded ID-JAG example

JSON

sub_id: the SAML identity

Where an OIDC ID-JAG has a plain sub, the SAML ID-JAG adds a structured sub_id with format: "saml-nameid" (§3.2.1). It carries the SAML NameID and every qualifier that was present:

FieldAlways presentMeaning
formatYesAlways saml-nameid
issuerYesThe SAML Issuer of the original assertion
nameidYesThe NameID value
nameid_formatNoThe NameID Format, when present
name_qualifierNoThe NameID NameQualifier, when present
sp_name_qualifierNoThe NameID SPNameQualifier, when present
sp_provided_idNoThe NameID SPProvidedID, when present

An email claim is also included when the NameID format is emailAddress. Downstream, the Resource Server resolves the user from sub_id, not sub.

client_id is the resource client

The client_id claim is the resource client ({client_id}-at-{resource_id}, e.g. client_abc123-at-todo0). It is the identity your app presents to the Authorization Server in Step 4, distinct from the IdP client used in Steps 2 and 3.

Error handling

ErrorCauseFix
invalid_grantRefresh Token is unknown, expired, or already usedRe-run Steps 1–2 to mint a fresh Refresh Token
invalid_targetaudience + resource don't match a resource connectionConfirm the connection exists on your SAML app and the values match exactly
invalid_scopeA requested scope isn't allowed for the connectionRemove the scope, or add it to the resource connection

Steps 4 and 5: shared with the OIDC path

From here the SAML and OIDC paths converge. The ID-JAG you just minted is redeemed exactly like an OIDC one:

  • Step 4, JWT Bearer Grant: present the ID-JAG to the Authorization Server (authenticating as the resource client) to receive a scoped access token.
  • Step 5, API Call: call the Resource Server with the access token as a standard Bearer credential.

The Resource Server reads sub_id to resolve the SAML user, provisioning them on first access.

These materials and any recommendations within are not legal, privacy, security, compliance, or business advice. These materials are intended for general informational purposes only and may not reflect the most current security, privacy, and legal developments nor all relevant issues. You are responsible for obtaining legal, security, privacy, compliance, or business advice from your own lawyer or other professional advisor and should not rely on the recommendations herein.

Presented byOkta Developer

Copyright © 2026 Okta. All rights reserved.