Generating a privileged token for the Agent while it acts on behalf of a user
Some agent actions are not simple user-delegated actions. They require elevated access, strict policy, and strong auditability. A privileged token lets IBM Verify represent an approved agent operation as a narrow, short-lived, policy-controlled grant instead of giving the agent broad standing access.
This tutorial demonstrates a subject and actor OAuth 2.0 Token exchange flow in IBM Verify:
- the subject is the signed-in user;
- the actor is the agent performing the operation;
- the Privileged Token Exchange Application is an OAuth/OIDC application configured to use the token-exchange grant;
authorization_detailsbinds the request to the exact privileged action;audienceidentifies the protected resource for which the exchanged token is requested.
privileged_client_id / privileged_client_secret and carries the required audience value.IBM Verify references:
Key learnings
- Understand subject and actor identity in a privileged agent operation.
- Configure separate applications for user authentication, agent authentication, and privileged token exchange.
- Use authorization details to constrain the requested privileged action.
- Exchange a user subject token and an agent actor token for a privileged token.
- Request the token for a specific target
audience. - Introspect and validate the issued privileged token.
Audience
- IAM administrators
- Security architects
- Application developers integrating agent flows with IBM Verify
Architecture
Privileged-token configuration overview:
The key components are:
- Subject Application — Authorization Code flow for the signed-in user.
- Actor application or Agent client — Client Credentials flow for the agent runtime; this client is associated with the agent identity during onboarding.
- Privileged Token Exchange Application — OAuth/OIDC application configured for the token-exchange grant. Its credentials are
privileged_client_idandprivileged_client_secret. - Authorization Details Type (ADT) — describes the exact privileged action being requested.
- Protected Resource or Privileged API — the target API identified by
audience; its client credentials are used for token introspection in this tutorial. - IBM Verify policy — validates subject, actor, requested operation, audience, and other configured conditions before issuing the exchanged token.
Prerequisites and resources
You need:
- An IBM Verify tenant with Agent Identity capability enabled.
- Permission to create or configure OAuth/OIDC applications, authorization-details types, access policies, and the protected resource used in this tutorial.
- Either an existing onboarded agent identity or permission to onboard an agent and associate its runtime client.
- Postman or Insomnia.
This guide uses the IBM Verify Admin console to create the three OAuth/OIDC application roles used by the runtime flow. An Admin API client is also configured so API-driven agent onboarding or administration can obtain an administrative access token. The Admin API Client is not the Privileged Token Exchange Application and is never used to authenticate the runtime token-exchange call.
Resources provided:
- Guide 8 Insomnia API collection
type: guide8_insomnia name: Guide 8 - Privileged Token for Agent Operations description: Guide 8 configuration helper for an Admin API token plus subject + actor OAuth 2.0 Token Exchange using an OAuth/OIDC Privileged Token Exchange Application. No standalone STS client is used. variables: tenant_url: '' admin_client_id: '' admin_client_secret: '' admin_token: '' subject_client_id: '' subject_client_secret: '' authorization_code: '' redirect_uri: http://localhost:4000/callback subject_token: '' actor_client_id: '' actor_client_secret: '' actor_token: '' privileged_client_id: '' privileged_client_secret: '' audience: '' privileged_authorization_details: '[{"type":"urn:ibm:params:oauth:request:agent_privileged_action","actions":["reset-password"],"resource":"verify-user-admin"}]' resource_client_id: '' resource_client_secret: '' privileged_token: '' folders: - name: Configuration - name: Runtime Flow requests: - name: Get Admin Token folder: Configuration method: POST url: '{{ tenant_url }}/oauth2/token' body: mimeType: application/x-www-form-urlencoded params: - name: grant_type value: client_credentials - name: client_id value: '{{ admin_client_id }}' - name: client_secret value: '{{ admin_client_secret }}' description: Obtain an administrative access token for agent onboarding/administration APIs. Copy access_token to admin_token. This token is not used by Runtime Flow. - name: Get Subject Token folder: Runtime Flow method: POST url: '{{ tenant_url }}/oauth2/token' body: mimeType: application/x-www-form-urlencoded params: - name: grant_type value: authorization_code - name: client_id value: '{{ subject_client_id }}' - name: client_secret value: '{{ subject_client_secret }}' - name: code value: '{{ authorization_code }}' - name: redirect_uri value: '{{ redirect_uri }}' - name: Get Actor Token folder: Runtime Flow method: POST url: '{{ tenant_url }}/oauth2/token' body: mimeType: application/x-www-form-urlencoded params: - name: grant_type value: client_credentials - name: client_id value: '{{ actor_client_id }}' - name: client_secret value: '{{ actor_client_secret }}' - name: Exchange Subject and Actor Tokens for Privileged Token folder: Runtime Flow method: POST authentication: type: basic username: '{{ privileged_client_id }}' password: '{{ privileged_client_secret }}' url: '{{ tenant_url }}/oauth2/token' body: mimeType: application/x-www-form-urlencoded params: - name: grant_type value: urn:ietf:params:oauth:grant-type:token-exchange - name: subject_token value: '{{ subject_token }}' - name: subject_token_type value: urn:ietf:params:oauth:token-type:access_token - name: actor_token value: '{{ actor_token }}' - name: actor_token_type value: urn:ietf:params:oauth:token-type:access_token - name: requested_token_type value: urn:ietf:params:oauth:token-type:access_token - name: audience value: '{{ audience }}' - name: authorization_details value: '{{ privileged_authorization_details }}' - name: Introspect Privileged Token folder: Runtime Flow method: POST authentication: type: basic username: '{{ resource_client_id }}' password: '{{ resource_client_secret }}' url: '{{ tenant_url }}/oauth2/introspect' body: mimeType: application/x-www-form-urlencoded params: - name: token value: '{{ privileged_token }}' - Guide 8 Postman API collection
{ "info": { "_postman_id": "1b3cf1c8-a9f2-4f56-bef0-guide8privileged", "name": "Guide 8 - Privileged Token for Agent Operations", "description": "Runnable Guide 8 collection with a Configuration helper for the Admin API token plus the subject + actor OAuth 2.0 Token Exchange runtime flow. Runtime exchange uses the OAuth/OIDC Privileged Token Exchange Application; no standalone STS client is used.", "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json" }, "item": [ { "name": "Configuration", "description": "Administrative setup helpers. Get Admin Token is for agent onboarding/administration only; it is not part of Runtime Flow.", "item": [ { "name": "Get Admin Token", "request": { "method": "POST", "header": [ { "key": "Content-Type", "value": "application/x-www-form-urlencoded" } ], "body": { "mode": "urlencoded", "urlencoded": [ { "key": "grant_type", "value": "client_credentials", "type": "text" }, { "key": "client_id", "value": "{{admin_client_id}}", "type": "text" }, { "key": "client_secret", "value": "{{admin_client_secret}}", "type": "text" } ] }, "url": { "raw": "{{tenant_url}}/oauth2/token", "host": [ "{{tenant_url}}" ], "path": [ "oauth2", "token" ] }, "description": "Obtain an administrative access token for agent onboarding/administration APIs. This token is not used by Runtime Flow token exchange." }, "response": [], "event": [ { "listen": "test", "script": { "type": "text/javascript", "exec": [ "if (pm.response.code >= 200 && pm.response.code < 300) {", " const json = pm.response.json();", " if (json.access_token) {", " pm.collectionVariables.set(\"admin_token\", json.access_token);", " }", "}" ] } } ] } ] }, { "name": "Runtime Flow", "item": [ { "name": "Get Subject Token", "request": { "method": "POST", "header": [ { "key": "Content-Type", "value": "application/x-www-form-urlencoded" } ], "body": { "mode": "urlencoded", "urlencoded": [ { "key": "grant_type", "value": "authorization_code", "type": "text" }, { "key": "client_id", "value": "{{subject_client_id}}", "type": "text" }, { "key": "client_secret", "value": "{{subject_client_secret}}", "type": "text" }, { "key": "code", "value": "{{authorization_code}}", "type": "text" }, { "key": "redirect_uri", "value": "{{redirect_uri}}", "type": "text" } ] }, "url": { "raw": "{{tenant_url}}/oauth2/token", "host": [ "{{tenant_url}}" ], "path": [ "oauth2", "token" ] } }, "response": [], "event": [ { "listen": "test", "script": { "type": "text/javascript", "exec": [ "if (pm.response.code >= 200 && pm.response.code < 300) {", " const json = pm.response.json();", " if (json.access_token) {", " pm.collectionVariables.set(\"subject_token\", json.access_token);", " }", "}" ] } } ] }, { "name": "Get Actor Token", "request": { "method": "POST", "header": [ { "key": "Content-Type", "value": "application/x-www-form-urlencoded" } ], "body": { "mode": "urlencoded", "urlencoded": [ { "key": "grant_type", "value": "client_credentials", "type": "text" }, { "key": "client_id", "value": "{{actor_client_id}}", "type": "text" }, { "key": "client_secret", "value": "{{actor_client_secret}}", "type": "text" } ] }, "url": { "raw": "{{tenant_url}}/oauth2/token", "host": [ "{{tenant_url}}" ], "path": [ "oauth2", "token" ] } }, "response": [], "event": [ { "listen": "test", "script": { "type": "text/javascript", "exec": [ "if (pm.response.code >= 200 && pm.response.code < 300) {", " const json = pm.response.json();", " if (json.access_token) {", " pm.collectionVariables.set(\"actor_token\", json.access_token);", " }", "}" ] } } ] }, { "name": "Exchange Subject and Actor Tokens for Privileged Token", "request": { "method": "POST", "header": [ { "key": "Content-Type", "value": "application/x-www-form-urlencoded" } ], "body": { "mode": "urlencoded", "urlencoded": [ { "key": "grant_type", "value": "urn:ietf:params:oauth:grant-type:token-exchange", "type": "text" }, { "key": "subject_token", "value": "{{subject_token}}", "type": "text" }, { "key": "subject_token_type", "value": "urn:ietf:params:oauth:token-type:access_token", "type": "text" }, { "key": "actor_token", "value": "{{actor_token}}", "type": "text" }, { "key": "actor_token_type", "value": "urn:ietf:params:oauth:token-type:access_token", "type": "text" }, { "key": "requested_token_type", "value": "urn:ietf:params:oauth:token-type:access_token", "type": "text" }, { "key": "audience", "value": "{{audience}}", "type": "text" }, { "key": "authorization_details", "value": "{{privileged_authorization_details}}", "type": "text" } ] }, "url": { "raw": "{{tenant_url}}/oauth2/token", "host": [ "{{tenant_url}}" ], "path": [ "oauth2", "token" ] }, "auth": { "type": "basic", "basic": [ { "key": "username", "value": "{{privileged_client_id}}", "type": "string" }, { "key": "password", "value": "{{privileged_client_secret}}", "type": "string" } ] } }, "response": [], "event": [ { "listen": "test", "script": { "type": "text/javascript", "exec": [ "if (pm.response.code >= 200 && pm.response.code < 300) {", " const json = pm.response.json();", " if (json.access_token) {", " pm.collectionVariables.set(\"privileged_token\", json.access_token);", " }", "}" ] } } ] }, { "name": "Introspect Privileged Token", "request": { "method": "POST", "header": [ { "key": "Content-Type", "value": "application/x-www-form-urlencoded" } ], "body": { "mode": "urlencoded", "urlencoded": [ { "key": "token", "value": "{{privileged_token}}", "type": "text" } ] }, "url": { "raw": "{{tenant_url}}/oauth2/introspect", "host": [ "{{tenant_url}}" ], "path": [ "oauth2", "introspect" ] }, "auth": { "type": "basic", "basic": [ { "key": "username", "value": "{{resource_client_id}}", "type": "string" }, { "key": "password", "value": "{{resource_client_secret}}", "type": "string" } ] } }, "response": [] } ] } ], "variable": [ { "key": "tenant_url", "value": "" }, { "key": "admin_client_id", "value": "" }, { "key": "admin_client_secret", "value": "" }, { "key": "admin_token", "value": "" }, { "key": "subject_client_id", "value": "" }, { "key": "subject_client_secret", "value": "" }, { "key": "authorization_code", "value": "" }, { "key": "redirect_uri", "value": "http://localhost:4000/callback" }, { "key": "subject_token", "value": "" }, { "key": "actor_client_id", "value": "" }, { "key": "actor_client_secret", "value": "" }, { "key": "actor_token", "value": "" }, { "key": "privileged_client_id", "value": "" }, { "key": "privileged_client_secret", "value": "" }, { "key": "audience", "value": "" }, { "key": "privileged_authorization_details", "value": "[{\"type\":\"urn:ibm:params:oauth:request:agent_privileged_action\",\"actions\":[\"reset-password\"],\"resource\":\"verify-user-admin\"}]" }, { "key": "resource_client_id", "value": "" }, { "key": "resource_client_secret", "value": "" }, { "key": "privileged_token", "value": "" } ] }
Prepare the API collection
Import either the Postman or Insomnia collection and set variables as you complete the following configuration sections.
| Variable | Set after | Purpose |
|---|---|---|
tenant_url |
Tenant available | Base tenant URL, for example https://tenant.example.com |
admin_client_id / admin_client_secret |
Create Admin API Client | Credentials used only to obtain an admin token for agent onboarding/administration APIs |
admin_token |
Get Admin Token | Administrative access token; intentionally not used by Runtime Flow requests |
subject_client_id / subject_client_secret |
Create Subject Application | OAuth client for the signed-in user |
redirect_uri |
Create Subject Application | Redirect URI registered for Authorization Code flow |
authorization_code |
User authentication | Short-lived code returned to the redirect URI after the user signs in |
actor_client_id / actor_client_secret |
Create Actor Application / Agent Client | Agent runtime credentials |
privileged_client_id / privileged_client_secret |
Create Privileged Token Exchange Application | Client credentials that authenticate the token-exchange request |
audience |
Configure Protected Resource | Target resource identifier requested during token exchange |
resource_client_id / resource_client_secret |
Configure Protected Resource | Credentials used to introspect the exchanged token |
privileged_authorization_details |
Included by default | JSON describing the privileged action |
Runtime token variables are:
subject_tokenactor_tokenprivileged_token
The Postman collection automatically saves admin_token, subject_token, actor_token, and privileged_token from successful responses. In Insomnia, copy each returned access_token into the corresponding environment variable before it is needed.
admin_token belongs only to configuration/onboarding. It is not sent in the subject + actor token-exchange flow. There are deliberately no sts_client_id, sts_client_secret, privileged_sts_client_id, privileged_sts_client_secret, or resource_audience variables in this collection. agent_id is an onboarding/administrative identifier, not a runtime token-exchange form parameter.Configuration
Step 0: Create the Admin API client
The Admin API client is the administrative credential used when agent onboarding or client registration is performed through IBM Verify APIs. It is separate from all three runtime OAuth/OIDC application roles.
- Open the IBM Verify Admin Console.
- Go to Security > API access and select Add API client.
Grant only the entitlements required by the administrative operations you perform:
readAgents— read agent records.writeAgents— create/update agent records.manageAgentStatus— manage agent lifecycle/status when your onboarding flow requires it.manageOidcDynamicClient— add this only when your onboarding automation uses Dynamic Client Registration or OIDC-client management APIs.
- Do not add
manageSTSClientsfor this tutorial. - Save the API client and copy its credentials into
admin_client_idandadmin_client_secret. - Run Configuration > Get Admin Token from the supplied collection.
- Confirm an access token is returned. Postman saves it as
admin_token; in Insomnia, copy the returnedaccess_tokenintoadmin_token.
curl -X POST "{{tenant_url}}/oauth2/token" \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "grant_type=client_credentials" \
-d "client_id={{admin_client_id}}" \
-d "client_secret={{admin_client_secret}}"
admin_token is not used to request the privileged runtime token.Step 1: Create the Subject application
The Subject Application represents the signed-in user. For this tutorial, create it through the Admin Console.
- In the Admin Console, go to Applications > Applications and add or configure an OpenID Connect application.
- Enable the Authorization Code grant.
- Register the redirect URI used by your demo/API client, for example
http://localhost:4000/callback. - Save the client credentials as
subject_client_idandsubject_client_secret. - Set
redirect_uriin the collection to the exact registered redirect URI.
Obtain authorization_code
Open a browser to the authorization endpoint:
{{tenant_url}}/oauth2/authorize?client_id={{subject_client_id}}&response_type=code&redirect_uri=http%3A%2F%2Flocalhost%3A4000%2Fcallback&scope=openid%20profile&state=<random-value>
- Open the URL in a browser.
- Authenticate the end user and complete any required consent or policy steps.
- Verify redirects the browser to your registered callback, for example
http://localhost:4000/callback?code=<AUTHORIZATION_CODE>&state=<random-value>. - Copy only the value of the
codequery parameter into the collection variableauthorization_code. - Run Runtime Flow > Get Subject Token before the authorization code expires; authorization codes are short-lived and single-use.
code_challenge and code_challenge_method=S256, and the token request must send the matching code_verifier.Step 2: Create the Actor application or Agent client
The Actor application or Agent client is the agent runtime credential.
- In the Admin Console, go to Applications > Applications and create/configure the OAuth/OIDC application used by the agent runtime.
- Enable the Client Credentials grant.
- Save the generated credentials as
actor_client_idandactor_client_secret. - Do not obtain the actor token yet if the agent-to-client association has not been completed.
Step 3: Onboard the agent and map the Actor application or Agent client
The agent record represents the agent as a first-class identity. The runtime actor token must be resolvable to that agent through the client-to-agent association established during onboarding.
- Existing onboarded agent: verify that the
actor_client_idis already associated with the correct agent identity. - New agent: first run Configuration > Get Admin Token, then use the Agent Onboarding guide/API flow to create the agent record and associate the Actor application or Agent client with it.
Create Admin API Client
↓
Get Admin Token
↓
Create Actor Application / Agent Client
↓
Onboard or update Agent and map actor_client_id
↓
Only then run Runtime Flow
agent_id for administration, audit, and troubleshooting. It is intentionally not sent as a form parameter in the token-exchange request.Step 4: Create the Authorization Details Type
Authorization details describe the privileged operation being requested and bind the request to the exact operation.
Create or configure the following tutorial ADT:
| Field | Value |
|---|---|
| Name | Agent Privileged Action |
| Type | urn:ibm:params:oauth:request:agent_privileged_action |
| Purpose | Privileged agent operation performed with both subject and actor context |
Use this payload in the token-exchange request:
[
{
"type": "urn:ibm:params:oauth:request:agent_privileged_action",
"actions": ["reset-password"],
"resource": "verify-user-admin"
}
]
Step 5: Create the Privileged Token Exchange Application
Create an OAuth/OIDC application configured for OAuth 2.0 Token Exchange. Do not create or use a standalone STS client for this tutorial.
- In the Admin Console, go to Applications > Applications and create/configure the OpenID Connect application used specifically for privileged token exchange.
- Enable or configure the OAuth 2.0 Token exchange grant.
- Configure token-exchange trust or policy so only approved subject and actor combinations can obtain the privileged token.
- Bind or evaluate the ADT type
urn:ibm:params:oauth:request:agent_privileged_actionas required by your policy design. - Configure the policy/claims needed for the target protected resource and requested audience.
- Keep the exchanged privileged token lifetime short.
- Save this application's credentials as
privileged_client_idandprivileged_client_secret.
Step 6: Configure the Protected resource or Privileged API
- Define the resource identifier that the exchanged token must target.
- Set that exact value in the collection variable
audience. - Configure the resource to validate the token's audience and required authorization details/claims.
- For this tutorial's introspection step, set
resource_client_idandresource_client_secret.
audience variable is the single source of truth. There is no separate resource_audience variable.Token-exchange request contract
| Parameter | Value |
|---|---|
| Client authentication | HTTP Basic using privileged_client_id / privileged_client_secret |
grant_type |
urn:ietf:params:oauth:grant-type:token-exchange |
subject_token |
End-user access token from the Subject Application |
subject_token_type |
urn:ietf:params:oauth:token-type:access_token |
actor_token |
Agent access token from the Actor Application |
actor_token_type |
urn:ietf:params:oauth:token-type:access_token |
requested_token_type |
urn:ietf:params:oauth:token-type:access_token |
audience |
Target protected-resource identifier |
authorization_details |
Privileged ADT payload |
Run the flow
Privileged-token runtime flow:
Run the requests in this exact order from the collection folder Runtime Flow.
Step 1: Get Subject token
Exchange the user's authorization code for the subject access token.
curl -X POST "{{tenant_url}}/oauth2/token" \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "grant_type=authorization_code" \
-d "client_id={{subject_client_id}}" \
-d "client_secret={{subject_client_secret}}" \
-d "code={{authorization_code}}" \
-d "redirect_uri={{redirect_uri}}"
Save the returned access_token as subject_token.
Step 2: Get Actor Token
The agent obtains its runtime token using Client Credentials.
curl -X POST "{{tenant_url}}/oauth2/token" \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "grant_type=client_credentials" \
-d "client_id={{actor_client_id}}" \
-d "client_secret={{actor_client_secret}}"
Save the returned access_token as actor_token.
Step 3: Exchange Subject and Actor tokens for Privileged token
The Privileged Token Exchange Application authenticates to IBM Verify with privileged_client_id / privileged_client_secret and submits the subject token, actor token, requested audience, and authorization details.
curl -X POST "{{tenant_url}}/oauth2/token" \
-H "Content-Type: application/x-www-form-urlencoded" \
-u "{{privileged_client_id}}:{{privileged_client_secret}}" \
-d "grant_type=urn:ietf:params:oauth:grant-type:token-exchange" \
-d "subject_token={{subject_token}}" \
-d "subject_token_type=urn:ietf:params:oauth:token-type:access_token" \
-d "actor_token={{actor_token}}" \
-d "actor_token_type=urn:ietf:params:oauth:token-type:access_token" \
-d "requested_token_type=urn:ietf:params:oauth:token-type:access_token" \
-d "audience={{audience}}" \
--data-urlencode 'authorization_details=[{"type":"urn:ibm:params:oauth:request:agent_privileged_action","actions":["reset-password"],"resource":"verify-user-admin"}]'
Save the returned access_token as privileged_token.
Step 4: Introspect Privileged token
The protected resource validates the exchanged token.
curl -X POST "{{tenant_url}}/oauth2/introspect" \
-H "Content-Type: application/x-www-form-urlencoded" \
-u "{{resource_client_id}}:{{resource_client_secret}}" \
-d "token={{privileged_token}}"
Validate the following:
- The token is active.
- The subject context identifies the intended user.
- The actor context identifies the expected agent/runtime actor.
- The audience matches the target privileged resource.
- The privileged action/authorization details match the operation being attempted.
- The token lifetime is short enough for the privileged operation.
Security recommendations
- Do not give the agent permanent broad administrative scopes when a narrow exchanged token can be used.
- Bind privileged requests to a specific action and resource using authorization details.
- Validate both subject and actor context before issuing the privileged token.
- Restrict token exchange to the intended
audienceand validate that audience at the resource. - Keep privileged token lifetime short and avoid unnecessary refresh capability.
- Log the subject, agent or actor, privileged token-exchange client, requested action, audience or resource, policy decision, and token-exchange event.
- Use approval or human-in-the-loop controls for operations whose risk warrants an explicit approval step.
Troubleshooting
| Symptom | Likely cause | Check |
|---|---|---|
invalid_client getting admin token |
Wrong Admin API Client credentials | admin_client_id, admin_client_secret, and whether the API client is enabled |
Admin API returns 403 |
Admin client lacks required entitlement | Add only the entitlement needed; do not add manageSTSClients for this guide |
invalid_client during exchange |
Wrong Privileged Token Exchange Application credentials | privileged_client_id, privileged_client_secret, client authentication method, and token-exchange grant configuration |
invalid_grant |
Subject or actor token not accepted | Token expiry, issuer/type, and token-exchange trust/policy |
invalid_actor_token |
Actor token invalid or actor mapping cannot be resolved | Reissue actor token and confirm actor client is associated with the onboarded agent |
invalid_authorization_details |
ADT type or payload rejected | ADT type URI, JSON structure, allowed actions/resources, and policy mapping |
access_denied |
Policy rejected the requested privileged operation | Subject criteria, actor criteria, ADT/action, audience, approval state, and policy decision logs |
| Audience missing or wrong | audience unset or not allowed |
Set the single audience variable and verify the target resource/policy configuration |
Introspection fails with invalid_client |
Resource introspection credentials are wrong/not permitted | resource_client_id, resource_client_secret, and introspection authorization |
| Resource API rejects token | Token does not satisfy resource validation | aud, actor/subject context, action/authorization details, expiry, and resource validation rules |
Summary
The Admin API Client is a configuration or onboarding credential only; it obtains admin_token for IBM Verify administrative APIs and does not participate in runtime token exchange.
The runtime design uses three distinct OAuth/OIDC application roles:
- Subject application — obtains the user's subject token.
- Actor application or Agent client — obtains the agent's actor token and is mapped to the agent identity during onboarding.
- Privileged Token Exchange Application — authenticates the token-exchange request using
privileged_client_id/privileged_client_secretand requests a token for the configuredaudience.
IBM Verify evaluates the subject, actor, requested privileged action, target audience, and policy before issuing a constrained privileged token. The resulting token is intended to authorize a specific privileged operation without giving the agent standing broad access.