Validating Access_Tokens Through the Introspection Endpoint
This section sets up IG as an OAuth 2.0 resource server, using the introspection endpoint.
For more information about configuring AM as an OAuth 2.0 authorization service, see AM's OAuth 2.0 Guide.
Before you start, prepare AM, IG, and the sample application as described in "Example Installation for This Guide".
Set up AM:
Select Applications > Agents > Identity Gateway, add an agent with the following values:
Agent ID:
ig_agent
Password:
password
Token Introspection:
Realm Only
Select Identities, and add a user with the following values:
ID/username:
george
First name:
george
Last name:
costanza
Password:
C0stanza
Email Address:
george@example.com
Employee number:
123
Create an OAuth 2.0 Authorization Server:
Select Services > Add a Service > OAuth2 Provider.
Add a service with the default values.
Create an OAuth 2.0 Client to request OAuth 2.0 access_tokens:
Select Applications > OAuth 2.0 > Clients, and add a client with the following values:
Client ID:
client-application
Client secret:
password
Scope(s):
mail
,employeenumber
(From AM 6.5) On the Advanced tab, select the following value:
Grant Types:
Resource Owner Password Credentials
Set up IG
Set an environment variable for the IG agent password, and then restart IG:
$
export AGENT_SECRET_ID='cGFzc3dvcmQ='
The password is retrieved by a SystemAndEnvSecretStore, and must be base64-encoded.
Add the following route to IG:
$HOME/.openig/config/routes/rs-introspect.json
%appdata%\OpenIG\config\routes\rs-introspect.json
{ "name": "rs-introspect", "baseURI": "http://app.example.com:8081", "condition": "${matches(request.uri.path, '^/rs-introspect$')}", "heap": [ { "name": "SystemAndEnvSecretStore-1", "type": "SystemAndEnvSecretStore" }, { "name": "AmService-1", "type": "AmService", "config": { "agent": { "username": "ig_agent", "passwordSecretId": "agent.secret.id" }, "secretsProvider": "SystemAndEnvSecretStore-1", "url": "http://openam.example.com:8088/openam/", "version": "7" } } ], "handler": { "type": "Chain", "config": { "filters": [ { "name": "OAuth2ResourceServerFilter-1", "type": "OAuth2ResourceServerFilter", "config": { "scopes": [ "mail", "employeenumber" ], "requireHttps": false, "realm": "OpenIG", "accessTokenResolver": { "name": "TokenIntrospectionAccessTokenResolver-1", "type": "TokenIntrospectionAccessTokenResolver", "config": { "amService": "AmService-1", "providerHandler": { "type": "Chain", "config": { "filters": [ { "type": "HttpBasicAuthenticationClientFilter", "config": { "username": "ig_agent", "passwordSecretId": "agent.secret.id", "secretsProvider": "SystemAndEnvSecretStore-1" } } ], "handler": "ForgeRockClientHandler" } } } } } } ], "handler": { "type": "StaticResponseHandler", "config": { "status": 200, "headers": { "Content-Type": [ "text/html" ] }, "entity": "<html><body><h2>Decoded access_token: ${contexts.oauth2.accessToken.info}</h2></body></html>" } } } } }
For information about how to set up the IG route in Studio, see "Resource Server Using the Introspection Endpoint in Structured Editor".
Notice the following features of the route:
The route matches requests to
/rs-introspect
.The
OAuth2ResourceServerFilter
expects an OAuth 2.0 access_token in the header of the incoming authorization request, with the scopesmail
andemployeenumber
.The
accessTokenResolver
uses the AM server declared in the heap. The introspection endpoint to validate the access_token is extrapolated from the URL of the AM server.For convenience in this test,
requireHttps
is false. In production environments, set it to true.After the filter validates the access_token, it creates a new context from the authorization server response. The context is named
oauth2
, and can be reached atcontexts.oauth2
orcontexts['oauth2']
.The context contains information about the access_token, which can be reached at
contexts.oauth2.accessToken.info
. Filters and handlers further down the chain can access the token info through the context.If there is no access_token in the request, or token validation does not complete successfully, the filter returns an HTTP error status to the user-agent, and IG does not continue processing the request. This is done as specified in the RFC, OAuth 2.0 Bearer Token Usage.
The HttpBasicAuthenticationClientFilter adds the credentials to the outgoing token introspection request.
The StaticResponseHandler returns the content of the access_token from the context
${contexts.oauth2.accessToken.info}
.
Test the setup:
In a terminal window, use a curl command similar to the following to retrieve an access_token:
$
mytoken=$(curl -s \ --user "client-application:password" \ --data "grant_type=password&username=george&password=C0stanza&scope=mail%20employeenumber" \ http://openam.example.com:8088/openam/oauth2/access_token | jq -r ".access_token")
Validate the access_token returned in the previous step:
$
curl -v http://openig.example.com:8080/rs-introspect --header "Authorization: Bearer ${mytoken}"
{ active = true, scope = employeenumber mail, client_id = client - application, user_id = george, token_type = Bearer, exp = 158...907, sub = george, iss = http://openam.example.com:8088/openam/oauth2, ... ... }