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.

Validate Access_Tokens Through the Introspection Endpoint

Before you start, prepare AM, IG, and the sample application as described in "Example Installation for This Guide".

  1. Set up AM:

    1. Select Applications > Agents > Identity Gateway, add an agent with the following values:

      • Agent ID: ig_agent

      • Password: password

      • Token Introspection: Realm Only

    2. 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

    3. Create an OAuth 2.0 Authorization Server:

      1. Select  Services > Add a Service > OAuth2 Provider.

      2. Add a service with the default values.

    4. Create an OAuth 2.0 Client to request OAuth 2.0 access_tokens:

      1. 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

      2. (From AM 6.5) On the Advanced tab, select the following value:

        • Grant Types: Resource Owner Password Credentials

  2. Set up IG

    1. 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.

    2. 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 scopes mail and employeenumber.

        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 at contexts.oauth2 or contexts['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}.

  3. Test the setup:

    1. 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")

    2. 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, ...
       ...
      }
Read a different version of :