Demonstrate impersonation
This page demonstrates token exchange with impersonation.
Prepare the demonstration
Start by preparing the demonstration:
May act script
The script adds a may_act
claim to the subject token.
-
In the AM admin UI, select Realm > Realm Name > Scripts + New Script.
-
In the New Script window, name the script
May act
and set Script Type toOAuth2 May Act
. -
In the edit window, save the following JavaScript:
(function () { var frJava = JavaImporter( org.forgerock.json.JsonValue ); var mayAct = frJava.JsonValue.json(frJava.JsonValue.object()) mayAct.put('client_id', 'impersonationClient') token.setMayAct(mayAct) }());
This script generates a
may_act
claim to permit the impersonating actor client to exchange the subject token.
Subject client
The OAuth 2.0 client profile in this example overrides the AM OAuth 2.0 provider settings. This lets you test the script without affecting access tokens issued to other clients.
-
Create a confidential OAuth 2.0 client account to get an original token for the subject.
In the AM admin UI, select Realm > Realm Name > Applications > OAuth 2.0 > Clients > + Add Client, and create a new confidential client with the following settings:
- Client ID
-
myClient
- Client secret
-
forgerock
- Redirection URIs
-
https://www.example.com:443/callback
- Scopes
-
change_data
create_accounts
read_accounts
transfer
-
Switch to the Advanced tab, enable Implied consent, and save your work:
-
Override OAuth 2.0 provider settings for this client.
Switch to the OAuth2 Provider Overrides tab, update the following settings and save your work:
- Enable OAuth2 Provider Overrides
-
Enabled
- OAuth2 Access Token May Act Script
-
May act
- OIDC ID Token May Act Script
-
May act
Actor client
Create a confidential OAuth 2.0 client account for the service that acts on behalf of the user.
-
In the AM admin UI, select Realm > Realm Name > Applications > OAuth 2.0 > Clients > + Add Client.
-
Create a new confidential client with the following settings:
- Client ID
-
impersonationClient
- Client Secret
-
forgerock
- Grant Types
-
Client Credentials
Refresh Token
Token Exchange
- Scopes
-
transfer
Test the demonstration
After preparing the demonstration, test your work using HTTP calls to REST endpoints.
The demonstration uses the Authorization code grant flow followed by token exchange:
-
The resource owner authenticates to obtain an SSO token.
-
The subject client relies on Implied Consent being enabled. It assumes the resource owner grants the client access.
-
The subject client requests the authorization code and exchanges it for an access token. Your script sets the
may_act
claim in the access token. -
The actor client exchanges the subject token for an access token.
Follow these steps:
-
Authenticate as the resource owner:
curl \ --request POST \ --header 'Content-Type: application/json' \ --header 'X-OpenAM-Username: <resource-owner-username>' \ --header 'X-OpenAM-Password: <resource-owner-password>' \ --header 'Accept-API-Version: resource=2.0, protocol=1.0' \ 'https://openam.example.com:8443/openam/json/realms/root/realms/alpha/authenticate' {"tokenId":"<resource-owner-tokenId>","successUrl":"/openam/console","realm":"/alpha"}
-
Request the authorization code as the subject client:
curl \ --dump-header - \ --request POST \ --Cookie 'iPlanetDirectoryPro=<resource-owner-tokenId>' \ --data 'scope=change_data create_accounts read_accounts transfer' \ --data 'response_type=code' \ --data 'client_id=myClient' \ --data 'csrf=<resource-owner-tokenId>' \ --data 'redirect_uri=https://www.example.com:443/callback' \ --data 'state=abc123' \ --data 'decision=allow' \ 'https://openam.example.com:8443/openam/oauth2/realms/root/realms/alpha/authorize' … location: https://www.example.com:443/callback?code=<authorization-code>&iss=https%3A%2F%2F… …
-
Exchange the authorization code for an access token as the subject client:
curl \ --request POST \ --user 'myClient:forgerock' \ --data 'grant_type=authorization_code' \ --data 'code=<authorization-code>' \ --data 'redirect_uri=https://www.example.com:443/callback' \ 'https://openam.example.com:8443/openam/oauth2/realms/root/realms/alpha/access_token' { "access_token": "<access-token>", "refresh_token": "<refresh-token>", "scope": "change_data transfer create_accounts read_accounts", "token_type": "Bearer", "expires_in": 3599 }
Your script has set the
may_act
claim, which is not directly visible. To see themay_act
claim, you must introspect the access token. -
Request an exchanged token as the actor client:
curl \ --request POST \ --user 'impersonationClient:forgerock' \ --data 'grant_type=urn:ietf:params:oauth:grant-type:token-exchange' \ --data 'scope=transfer' \ --data 'subject_token=<access-token>' \ --data 'subject_token_type=urn:ietf:params:oauth:token-type:access_token' \ 'https://openam.example.com:8443/openam/oauth2/realms/root/realms/alpha/access_token' { "access_token": "<exchanged-token>", "refresh_token": "<new-refresh-token>", "issued_token_type": "urn:ietf:params:oauth:token-type:access_token", "scope": "transfer", "token_type": "Bearer", "expires_in": 3599 }
The
issued_token_type
shows this is an exchanged token.