Scope evaluation
This extension point retrieves and evaluates the scope information for an OAuth2 access token.
The default scopes implementation in AM treats scopes as profile attributes for the resource owner. When a resource server or other entity uses the access token to get token information from AM, AM populates the scopes with profile attribute values. For example, if one of the scopes is mail, AM sets mail to the resource owner’s email address in the token information returned.
The plugin lets you extend or modify this behavior by writing your own scope evaluation plugin to populate the scopes with custom values.
- Sample script
-
OAuth2 Evaluate Scope Script (Legacy)
- Script bindings
- Java interface
-
org.forgerock.oauth2.core.plugins.ScopeEvaluatorSample Java code
/* * Copyright 2021-2025 Ping Identity Corporation. All Rights Reserved * * This code is to be used exclusively in connection with Ping Identity * Corporation software or services. Ping Identity Corporation only offers * such software or services to legal entities who have entered into a * binding license agreement with Ping Identity Corporation. */ package org.forgerock.openam.examples; import java.util.HashMap; import java.util.Map; import java.util.Set; import org.forgerock.oauth2.core.AccessToken; import org.forgerock.oauth2.core.plugins.ScopeEvaluator; /** * Custom implementation of the Scope Evaluator * plugin interface {@link org.forgerock.oauth2.core.plugins.ScopeEvaluator} * * <li> * The {@code evaluateScope} method populates scope values to return. * </li> * */ public class CustomScopeEvaluator implements ScopeEvaluator { @Override public Map<String, Object> evaluateScope(AccessToken token) { return mapScopes(token); } /** * Set read and write permissions according to scope. * * @param token The access token presented for validation. * @return The map of read and write permissions, * with permissions set to {@code true} or {@code false}, * as appropriate. */ private Map<String, Object> mapScopes(AccessToken token) { Set<String> scopes = token.getScope(); Map<String, Object> map = new HashMap<String, Object>(); final String[] permissions = {"read", "write"}; for (String scope : permissions) { if (scopes.contains(scope)) { map.put(scope, true); } else { map.put(scope, false); } } return map; } }
Example Java plugin
This example uses the Java sample provided by AM.
Complete the following steps to implement a custom scope evaluation Java plugin that
sets read and write values in the access token according to the scope information.
|
To configure AM to use a scripted scope evaluation plugin, refer to the steps in Configure AM to use a scripted OAuth 2.0 plugin. Find information about the available script bindings in the Scope evaluation scripting API. |
Create and deploy the sample scope evaluation Java plugin
-
Clone the sample code and build a JAR file by following the steps described in How do I access and build the sample code provided for PingAM? in the Knowledge Base.
Files included in the sample
pom.xml-
Apache Maven project file for the module.
This file specifies how to build the sample, and specifies its dependencies on AM components.
src/main/java/org/forgerock/openam/examples/CustomScopeEvaluator.java-
Sample class for the Scope Evaluation OAuth 2.0 plugin.
After you successfully build the project, you find the
openam-scope-sample-8.1.0.jarin theopenam-samples/openam-scope-sample/targetdirectory of the project. -
Copy the built JAR file to the
/WEB-INF/libfolder where you deployed AM. -
Restart AM or the container in which it runs.
Configure AM to use the custom scope evaluation plugin
Perform this task to set up an OAuth 2.0 provider that uses the sample scope evaluation Java implementation.
-
Log in to the AM admin UI as an administrator.
For example,
amAdmin. -
Configure the provider and ensure the following properties are set:
-
Scope Evaluation Plugin Type to
JAVA. -
Scope Evaluation Plugin Implementation Class to
org.forgerock.openam.examples.CustomScopeEvaluation.
By default, a new OAuth 2.0 provider uses the default Java implementation.
-
-
Save your changes.
Create an OAuth2 client
Create an OAuth 2.0 client to use in the client credentials grant flow.
-
In the AM admin UI, go to Realms > realm name > Applications > OAuth 2.0 > Clients, and click Add Client.
-
Enter the following values:
-
Client ID:
myClient -
Client secret:
mySecret -
Redirection URIs:
https://www.example.com:443/callback -
Scope(s):
readwrite
-
-
Click Create.
-
In Advanced > Grant Types, add
Client Credentials. -
Save your changes.
AM is now configured for you to try the sample scope evaluation script.
Try the custom scope evaluation Java plugin
To try the custom scope evaluation plugin, use the Client credentials grant flow.
-
Send a POST request to the /oauth2/access_token endpoint, specifying the grant type as
client_credentials, scope asread, and your client details.For example:
$ curl \ --request POST \ --data "grant_type=client_credentials" \ --data "client_id=myClient" \ --data "client_secret=mySecret" \ --data "scope=read" \ "https://am.example.com:8443/am/oauth2/realms/root/realms/alpha/access_token" { "access_token": "M3M2Jb2SMjvgWhzNas2SVy2LALg", "scope": "read", "token_type": "Bearer", "expires_in": 3599 } -
Call the oauth2/tokeninfo endpoint to inspect the custom scope values. Include the access token obtained in the previous request.
For example:
$ curl \ "https://am.example.com:8443/am/oauth2/realms/root/realms/alpha/tokeninfo\ ?access_token=M3M2Jb2SMjvgWhzNas2SVy2LALg" { "access_token": "M3M2Jb2SMjvgWhzNas2SVy2LALg", "read": true, "grant_type": "client_credentials", "auditTrackingId": "f9a8395d-1bac-4cba-8b09-8cc336dc49e2-6810", "scope": ["read"], "realm": "/alpha", "token_type": "Bearer", "expires_in": 3583, "authGrantId": "l3355H89FDSWsfdKJmvWssGk_oE", "write": false, "client_id": "myClient" }As this example indicates, the requested scope
readis authorized, but thewritescope has not been authorized.
Example scripted plugin
Follow these steps to customize how AM returns custom user session data with a script:
Create a custom script
The example script populates scopes with attributes from the resource owner’s user profile.
-
Create a new OAuth2 Evaluate Scope script.
-
Name your script
Demo scope evaluation script.You can create either a Legacy or a Next Generation script.
-
In the script window, add the following JavaScript:
-
Legacy
-
Next-generation
(function () { var map = new java.util.HashMap(); if (identity) { // convert Set of scopes to an Array var scopes = accessToken.getScope().toArray(); scopes.forEach(function (scope) { var attributes = identity.getAttribute(scope).toArray(); map.put(scope, attributes.join(",")); }); } else { logger.error('Identity is null'); } return map; }());(function () { var map = {}; if (identity) { // returns a List of scopes var scopes = accessToken.getScope(); for each (var scope in scopes) { var attributes = identity.getAttributeValues(scope); map[scope] = Array.from(attributes).join(","); }; } else { logger.error('Identity is null'); } return map; }());You can find information about the common bindings such as
loggerandscriptNamein Common bindings.You can find information about the bindings specific to scope evaluation scripts in the Scope evaluation scripting API.
-
-
Save your changes.
Create the resource owner
The script requires a resource owner with an email address in their user profile. Follow these steps to prepare a test user profile:
-
In the AM admin UI, select Realm > realm name > Identities > + Add Identity and fill the required fields.
Record the username and password, for example,
bjensenandCh4ng31t. -
Update the following setting in the new user profile and save your work:
- Email Address
-
bjensen@example.com
-
Save your changes.
Create an OAuth 2.0 client
Create and configure a client application to override the OAuth 2.0 provider settings in the authorization flow.
-
Create an OAuth 2.0 client with the following values:
- Client ID
-
myClient - Client secret
-
mySecret - Redirection URIs
-
https://www.example.com:443/callback - Scope(s)
-
mail
-
On the Advanced tab, enable Implied consent, and save your changes.
-
Switch to the OAuth2 Provider Overrides tab and update the following settings:
- Enable OAuth2 Provider Overrides
-
Enabled
- Scope Evaluation Plugin Type
-
SCRIPTED - Scope Evaluation Script
-
Demo scope evaluation script
-
Save your changes.
AM is now configured to use your custom scope evalution script.
Try the script
Test the example using the Authorization code grant flow:
-
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://am.example.com:8443/am/json/realms/root/realms/alpha/authenticate' { "tokenId": "<resource-owner-tokenId>", "successUrl": "/enduser/?realm=/alpha", "realm": "/alpha" } -
Request the authorization code as the client:
curl \ --dump-header - \ --request POST \ --header 'iPlanetDirectoryPro: <resource-owner-tokenId>' \ --data 'scope=mail' \ --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://am.example.com:8443/am/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 client:
curl \ --request POST \ --user 'myClient:mySecret' \ --data 'grant_type=authorization_code' \ --data 'code=<authorization-code>' \ --data 'redirect_uri=https://www.example.com:443/callback' \ 'https://am.example.com:8443/am/oauth2/realms/root/realms/alpha/access_token' { "access_token": "<access-token>", "refresh_token": "<refresh-token>", "scope": "mail", "token_type": "Bearer", "expires_in": 3599 } -
Get information about the access token as the client acting as a resource server:
curl \ --request GET \ --header 'iPlanetDirectoryPro: AQIC5wM…TU3OQ*' \ 'https://am.example.com:8443/am/oauth2/realms/root/realms/alpha/tokeninfo' { "access_token": "<access-token>", "mail": "bjensen@example.com", "grant_type": "authorization_code", "auth_level": 0, "auditTrackingId": "<audit-tracking-id>", "scope": ["mail"], "realm": "/alpha", "token_type": "Bearer", "expires_in": 3497, "authGrantId": "<auth-grant-id>", "client_id": "myClient" }The script added
"mail": "bjensen@example.com".