Access Resources By Using OAuth 2.0 Credentials

This example shows how a client service accesses an OAuth 2.0-protected resource by using its OAuth 2.0 client credentials.

ClientCredentialsOAuth2ClientFilter
  1. Set up the AM as an Authorization Server:

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

      • Agent ID : ig_agent

      • Password : password

      • Token Introspection : Realm Only

    2. Create an OAuth 2.0 Authorization Server:

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

      2. Add a service with the default values.

    3. Create an OAuth 2.0 client to request access_tokens, using client credentials for authentication:

      1. Select Applications > OAuth 2.0 > Clients, and add a client with the following values:

        • Client ID : client-service

        • Client secret : password

        • Scope(s) : client-scope

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

        • Grant Types : Client 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:

      • Linux

      • Windows

      $HOME/.openig/routes/oauth2-protected-resource.json
      appdata\OpenIG\config\routes\oauth2-protected-resource.json
      {
        "name": "oauth2-protected-resource",
        "condition": "${matches(request.uri.path, '^/oauth2-protected-resource')}",
        "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.1"
            }
          }
        ],
        "handler": {
          "type": "Chain",
          "config": {
            "filters": [
              {
                "name": "OAuth2ResourceServerFilter-1",
                "type": "OAuth2ResourceServerFilter",
                "config": {
                  "scopes": [ "client-scope" ],
                  "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>Access Granted</h2></body></html>"
              }
            }
          }
        }
      }

      Notice the following features of the route:

      • The route matches requests to /oauth2-protected-resource.

      • The OAuth2ResourceServerFilter expects an OAuth 2.0 access_token in the header of the incoming request, with the scope client-scope.

      • The filter uses a TokenIntrospectionAccessTokenResolver to resolve the access_token. The introspect endpoint is protected with HTTP Basic Authentication, and the providerHandler uses an HttpBasicAuthenticationClientFilter to provide the resource server credentials.

      • For convenience in this test, "requireHttps" is false. In production environments, set it to true.

      • After the filter successfully validates the access_token, it creates a new context from the authorization server response, containing information about the access_token.

      • The StaticResponseHandler returns a message that access is granted.

    3. Add the following route to IG:

      • Linux

      • Windows

      $HOME/.openig/routes/client-credentials.json
      appdata\OpenIG\config\routes\client-credentials.json
      {
        "name": "client-credentials",
        "baseURI": "http://openig.example.com:8080",
        "condition" : "${matches(request.uri.path, '^/client-credentials')}",
        "heap": [
          {
            "name": "oauth2EnabledClientHandler",
            "type": "Chain",
            "capture": "all",
            "config": {
              "filters": [
                {
                  "type": "ClientCredentialsOAuth2ClientFilter",
                  "config": {
                    "clientId": "client-service",
                    "clientSecretId": "client.secret.id",
                    "secretsProvider": {
                      "type": "Base64EncodedSecretStore",
                      "config": {
                        "secrets": {
                          "client.secret.id": "cGFzc3dvcmQ="
                        }
                      }
                    },
                    "tokenEndpoint": "http://openam.example.com:8088/openam/oauth2/access_token",
                    "scopes" : ["client-scope"]
                  }
                }
              ],
              "handler": "ForgeRockClientHandler"
            }
          }
        ],
        "handler": {
          "type": "ScriptableHandler",
          "config": {
            "type": "application/x-groovy",
            "clientHandler": "oauth2EnabledClientHandler",
            "source": [
              "request.uri.path = '/oauth2-protected-resource'",
              "return http.send(context, request);"
            ]
          }
        }
      }

      Note the following features of the route:

      • The route matches requests to /client-credentials.

      • The ScriptableHandler rewrites the request to target it to /oauth2-protected-resource, and then calls the HTTP client, that has been redefined to use the oauth2EnabledClientHandler.

      • The oauth2EnabledClientHandler calls the ClientCredentialsOAuth2ClientFilter to obtain an access_token from AM by using the client’s OAuth 2.0 credentials, and then injects it into the request as a Bearer Authorization header.

      • The route oauth2-protected-resource.json uses the AM introspection endpoint to resolve the access_token and display its contents.

  3. Test the setup by accessing the route on http://openig.example.com:8080/client-credentials. A message shows that access is granted.