UserProfileFilter

Queries AM to retrieve the profile attributes of an user identified by their username.

Only profile attributes that are enabled in AM can be returned by the query. The roles field is not returned.

The data is made available to downstream IG filters and handlers, in the context "UserProfileContext".

Supported with AM 5 and later versions.

Usage

{
  "name": string,
  "type": "UserProfileFilter",
  "config": {
    "username": configuration expression<string>,
    "userProfileService": UserProfileService reference
  }
}

Properties

"username": configuration expression<string>, required

The username of an AM subject. This filter retrieves profile attributes for the subject.

"userProfileService": UserProfileService reference, required

The service to retrieve profile attributes from AM, for the subject identified by username.

"userProfileService": {
  "type": "UserProfileService",
  "config": {
    "amService": AmService reference,
    "cache": object,
    "profileAttributes": array of runtime expression<string>,
    "realm": configuration expression<string>
  }
}
"amService": AmService reference, required

The AmService heap object to use for the following properties:

  • agent, the credentials of the IG agent in AM. When the agent is authenticated, the token can be used for tasks such as getting the user's profile, making policy evaluations, and connecting to the AM notification endpoint.

  • url: URL of the AM server where the user is authenticated.

  • amHandler: Handler to use when communicating with AM to fetch the requested user's profile.

  • realm: Realm of the IG agent in AM.

  • version: The version of the AM server.

cache: object, optional

Caching of AM user profiles, based on Caffeine. For more information, see the GitHub entry, Caffeine .

When caching is enabled, IG can reuse cached profile attributes without repeatedly querying AM. When caching is disabled, IG must query AM for each request, to retrieve the required user profile attributes.

Default: No cache.

enabled: boolean, optional

Enable or disable caching of user profiles. When false, the cache is disabled but the cache configuration is maintained.

Default: true when cache is configured

executor: executor, optional

An executor service to schedule the execution of tasks, such as the eviction of entries in the cache.

Default: ForkJoinPool.commonPool()

"maximumSize": configuration expression<number>, optional

The maximum number of entries the cache can contain.

Default: Unlimited/unbound

maximumTimeToCache: duration, required

The maximum duration for which to cache user profiles.

The duration cannot be zero.

For information about supported formats for duration, see duration.

profileAttributes: array of runtime expression<string>, optional

List of one or more fields to return and store in UserProfileContext.

Field names are defined by the underlying repository in AM. When AM is installed with the default configuration, the repository is ForgeRock Directory Services.

The following convenience accessors are provided for commonly used fields:

  • cn: Retrieved through ${contexts.userProfile.commonName}

  • dn: Retrieved through ${contexts.userProfile.distinguishedName}

  • realm: Retrieved through ${contexts.userProfile.realm}

  • username: Retrieved through ${contexts.userProfile.username}

All other available fields can be retrieved through ${contexts.userProfile.rawInfo} and ${contexts.userProfile.asJsonValue()}.

When profileAttributes is configured, the specified fields and the following fields are returned: username, _id, and _rev.

Default: All available fields are returned.

"realm": configuration expression<string>, optional

The AM realm where the subject is authenticated.

Default: The realm declared for amService.

Examples

In the following examples, the UserProfileFilter retrieves user profile attributes and stores them in the context.

The userProfile property of AmService is configured to retrieve employeeNumber and mail. When the property is not configured, all available attributes in rawInfo or asJsonValue() are displayed.

Retrieving Profile Attributes for a User Authenticated With an SSO Token

In this example the user is authenticated with AM through the SingleSignOnFilter, which stores the SSO token and its validation information in the SsoTokenContext. The UserProfileFilter retrieves the user's mail and employee number, as well as the username, _id, and _rev, from that context.

  1. In AM, add the following items, and then log out:

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

  3. Add the following route to IG:

    $HOME/.openig/config/routes/user-profile-sso.json
    %appdata%\OpenIG\config\routes\user-profile-sso.json
    {
      "name": "user-profile-sso",
      "condition": "${matches(request.uri.path, '^/user-profile-sso')}",
      "heap": [
        {
          "name": "SystemAndEnvSecretStore-1",
          "type": "SystemAndEnvSecretStore"
        },
        {
          "name": "AmService-1",
          "type": "AmService",
          "config": {
            "url": "http://openam.example.com:8088/openam",
            "realm": "/",
            "version": "7",
            "agent": {
              "username": "ig_agent",
              "passwordSecretId": "agent.secret.id"
            },
            "secretsProvider": "SystemAndEnvSecretStore-1",
            "amHandler": "ForgeRockClientHandler"
          }
        }
      ],
      "handler": {
        "type": "Chain",
        "config": {
          "filters": [
            {
              "name": "SingleSignOnFilter",
              "type": "SingleSignOnFilter",
              "config": {
                "amService": "AmService-1"
              }
            },
            {
              "name": "UserProfileFilter-1",
              "type": "UserProfileFilter",
              "config": {
                "username": "${contexts.ssoToken.info.uid}",
                "userProfileService": {
                  "type": "UserProfileService",
                  "config": {
                    "amService": "AmService-1",
                    "profileAttributes": [ "employeeNumber", "mail" ]
                  }
                }
              }
            }
          ],
          "handler": {
            "type": "StaticResponseHandler",
            "config": {
              "status": 200,
              "headers": {
                "Content-Type": ["text/html"]
              },
              "entity": "<html><body>username: ${contexts.userProfile.username}<br><br>rawInfo: <pre>${contexts.userProfile.rawInfo}</pre></body></html>"
            }
          }
        }
      }
    }
  4. Go to http://openig.example.com:8080/user-profile-sso.

  5. Log in to AM with username george and password C0stanza.

    The UserProfileFilter retrieves George's profile data and stores it in the UserProfileContext. The StaticResponseHandler displays the username and the profile data that is available in rawInfo.

    username: george
     
    rawInfo:
    {_id=george, _rev=273001616, employeeNumber=[123], mail=[george@example.com], username=george}


Retrieving a Username From sessionInfo Context

This example shows how the UserProfileFilter retrieves AM profile information for the user identified by the SessionInfoContext, at ${contexts.amSession.username}.

Consider using the UserProfileFilter with a SessionInfoFilter to protect APIs. The SessionInfoFilter validates an SSO token without redirecting the request to an authentication page.

  1. In AM, add the following items, and then log out:

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

  3. Add the following route to IG:

    $HOME/.openig/config/routes/user-profile-ses-info.json
    %appdata%\OpenIG\config\routes\user-profile-ses-info.json
    {
      "name": "user-profile-ses-info",
      "condition": "${matches(request.uri.path, '^/user-profile-ses-info')}",
      "heap": [
        {
          "name": "SystemAndEnvSecretStore-1",
          "type": "SystemAndEnvSecretStore"
        },
        {
          "name": "AmService-1",
          "type": "AmService",
          "config": {
            "url": "http://openam.example.com:8088/openam",
            "realm": "/",
            "version": "7",
            "agent": {
              "username": "ig_agent",
              "passwordSecretId": "agent.secret.id"
            },
            "secretsProvider": "SystemAndEnvSecretStore-1",
            "amHandler": "ForgeRockClientHandler"
          }
        }
      ],
      "handler": {
        "type": "Chain",
        "capture": "all",
        "config": {
          "filters": [
            {
              "name": "SessionInfoFilter-1",
              "type": "SessionInfoFilter",
              "config": {
                "amService": "AmService-1"
              }
            },
            {
              "name": "UserProfileFilter-1",
              "type": "UserProfileFilter",
              "config": {
                "username": "${contexts.amSession.username}",
                "userProfileService": {
                  "type": "UserProfileService",
                  "config": {
                    "amService": "AmService-1",
                    "profileAttributes": [ "employeeNumber", "mail" ]
                  }
                }
              }
            }
          ],
          "handler": {
            "type": "StaticResponseHandler",
            "config": {
              "status": 200,
              "headers": {
                "Content-Type": [ "application/json" ]
              },
              "entity": "{ \"username\": \"${contexts.userProfile.username}\", \"user_profile\":  ${contexts.userProfile.asJsonValue()} }"
            }
          }
        }
      }
    }
  4. In a terminal window, retrieve an SSO token:

    $ curl --request POST \
    --url http://openam.example.com:8088/openam/json/realms/root/authenticate \
    --header 'accept-api-version: resource=2.0' \
    --header 'content-type: application/json' \
    --header 'x-openam-username: george' \
    --header 'x-openam-password: C0stanza' \
    --data '{}'
       
    {"tokenId":"AQIC5wM2LY . . . Dg5AAJTMQAA*","successUrl":"/openam/console"}
  5. Access the route, providing the token ID retrieved in the previous step, where iPlanetDirectoryPro is the name of the AM session cookie:

    $ curl --cookie 'iPlanetDirectoryPro=token' http://openig.example.com:8080/user-profile-ses-info | jq .
    
    {
      "username": "george",
      "user_profile": {
        "_id": "george",
        "_rev": "273001616",
        "employeeNumber": [
          "123"
        ],
        "mail": [
          "george@example.com"
        ],
        "username": "george"
      }
    }

    To find the name of your AM session cookie, see "Find the Name of Your AM Session Cookie".

    The UserProfileFilter retrieves George's profile data and stores it in the UserProfileContext. The StaticResponseHandler displays the username and the profile data that is available in asJsonValue().


Retrieving a Username From the OAuth2Context

In this example the OAuth2ResourceServerFilter validates a request containing an OAuth 2.0 access token, using the introspection endpoint, and injects the token into the OAuth2Context context. The UserProfileFilter retrieves AM profile information for the user identified by this context.

  1. In AM, add the following items, and then log out:

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

  3. Add the following route to IG:

    $HOME/.openig/config/routes/user-profile-oauth.json
    %appdata%\OpenIG\config\routes\user-profile-oauth.json
    {
      "name": "user-profile-oauth",
      "baseURI": "http://app.example.com:8081",
      "condition": "${matches(request.uri.path, '^/user-profile-oauth')}",
      "heap": [
        {
          "name": "SystemAndEnvSecretStore-1",
          "type": "SystemAndEnvSecretStore"
        },
        {
          "name": "AmService-1",
          "type": "AmService",
          "config": {
            "url": "http://openam.example.com:8088/openam",
            "realm": "/",
            "version": "7",
            "agent": {
              "username": "ig_agent",
              "passwordSecretId": "agent.secret.id"
            },
            "secretsProvider": "SystemAndEnvSecretStore-1",
            "amHandler": "ForgeRockClientHandler"
          }
        }
      ],
      "handler": {
        "type": "Chain",
        "config": {
          "filters": [
            {
              "name": "OAuth2ResourceServerFilter-1",
              "type": "OAuth2ResourceServerFilter",
              "config": {
                "scopes": [
                  "mail",
                  "employeenumber"
                ],
                "requireHttps": false,
                "realm": "OpenIG",
                "accessTokenResolver": {
                  "name": "token-resolver-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"
                      }
                    }
                  }
                }
              }
            },
            {
              "name": "UserProfileFilter-1",
              "type": "UserProfileFilter",
              "config": {
                "username": "${contexts.oauth2.accessToken.info.sub}",
                "userProfileService": {
                  "type": "UserProfileService",
                  "config": {
                    "amService": "AmService-1",
                    "profileAttributes": [ "employeeNumber", "mail" ]
                  }
                }
              }
            }
          ],
          "handler": {
            "type": "StaticResponseHandler",
            "config": {
              "status": 200,
              "headers": {
                "Content-Type": [ "application/json" ]
              },
              "entity": "{ \"username\": \"${contexts.userProfile.username}\", \"user_profile\":  ${contexts.userProfile.asJsonValue()} }"
            }
          }
        }
      }
    }
  4. In a terminal window, retrieve an access token:

    $ curl \
    --user "client-application:password" \
    --data "grant_type=password&username=george&password=C0stanza&scope=mail%20employeenumber" \
    http://openam.example.com:8088/openam/oauth2/access_token
       
    {
      "access_token":"<access_token>",
      "scope":"employeenumber mail",
      "token_type":"Bearer",
      "expires_in":3599
    }
  5. Access the route, providing the access token retrieved in the previous step:

    $ curl --header 'Authorization: Bearer <access_token>' http://openig.example.com:8080/user-profile-oauth | jq .
        
    {
      "username": "george",
      "user_profile": {
        "_id": "george",
        "_rev": "-576067013",
        "employeeNumber": [
          "123"
        ],
        "mail": [
          "george@example.com"
        ],
        "username": "george"
      }
    }

    The UserProfileFilter retrieves George's profile data and stores it in the UserProfileContext. The StaticResponseHandler displays the username and the profile data that is available in asJsonValue().


Read a different version of :