PingAM 7.5.1

Scope validation

Use this plugin to configure the OAuth2 provider to validate the set of requested scopes against the allowed scopes and, optionally, to modify the list of valid scopes.

The plugin comprises four functions or methods that let you customize the validation of scopes at the following endpoints:

Function / Method Endpoint

validateAuthorizationScope

/authorize

validateAccessTokenScope

/authorize and /access_token

validateRefreshTokenScope

/refresh

validateBackChannelAuthorizationScope

/bc_authorize

Default script

To view the default script, including the available script properties, refer to oauth2-validate-scope.js.

To view or modify the default script in the AM admin UI, go to Realms > Realm Name > Scripts and select OAuth2 Validate Scope Script.

Java interface

org.forgerock.oauth2.core.plugins.ScopeValidator

Java sample
Show Sample Code
/*
 * Copyright 2021-2022 ForgeRock AS. All Rights Reserved
 *
 * Use of this code requires a commercial software license with ForgeRock AS.
 * or with one of its affiliates. All use shall be exclusively subject
 * to such license between the licensee and ForgeRock AS.
 */

package org.forgerock.openam.examples;

import java.util.HashSet;
import java.util.Set;

import org.forgerock.oauth2.core.ClientRegistration;
import org.forgerock.oauth2.core.OAuth2Request;
import org.forgerock.oauth2.core.exceptions.ServerException;
import org.forgerock.oauth2.core.plugins.ScopeValidator;

/**
 * Custom implementation of the Scope Validator
 * plugin interface {@link org.forgerock.oauth2.core.plugins.ScopeValidator}
 *
 * <li>
 * The {@code validateAuthorizationScope} method
 * adds default scopes, or any allowed scopes provided.
 * </li>
 *
 * <li>
 * The {@code validateAccessTokenScope} method
 * adds default scopes, or any allowed scopes provided.
 * </li>
 *
 * <li>
 * The {@code validateRefreshTokenScope} method
 * adds the scopes from the access token,
 * or any requested scopes provided that are also in the access token scopes.
 * </li>
 *
 *  * <li>
 *  * The {@code validateBackChannelAuthorizationScope} method
 *  * adds default scopes, or any allowed scopes provided.
 *  * </li>
 *
 */
public class CustomScopeValidator implements ScopeValidator {

    @Override
    public Set<String> validateAuthorizationScope(ClientRegistration clientRegistration, Set<String> scope,
            OAuth2Request oAuth2Request) throws ServerException {

        if (scope == null || scope.isEmpty()) {
            return clientRegistration.getDefaultScopes();
        }

        Set<String> scopes = new HashSet<String>(clientRegistration.getAllowedScopes());
        scopes.retainAll(scope);
        return scopes;
    }

    @Override
    public Set<String> validateAccessTokenScope(ClientRegistration clientRegistration,
            Set<String> scope, OAuth2Request request) throws ServerException {

        if (scope == null || scope.isEmpty()) {
            return clientRegistration.getDefaultScopes();
        }

        Set<String> scopes = new HashSet<String>(clientRegistration.getAllowedScopes());
        scopes.retainAll(scope);
        return scopes;
    }

    @Override
    public Set<String> validateRefreshTokenScope(ClientRegistration clientRegistration,
            Set<String> requestedScope, Set<String> tokenScope, OAuth2Request request) {

        if (requestedScope == null || requestedScope.isEmpty()) {
            return tokenScope;
        }

        Set<String> scopes = new HashSet<String>(tokenScope);
        scopes.retainAll(requestedScope);
        return scopes;
    }

    @Override
    public Set<String> validateBackChannelAuthorizationScope(ClientRegistration clientRegistration,
            Set<String> requestedScopes, OAuth2Request request) throws ServerException {

        if (requestedScopes == null || requestedScopes.isEmpty()) {
            return clientRegistration.getDefaultScopes();
        }

        Set<String> scopes = new HashSet<>(clientRegistration.getAllowedScopes());
        scopes.retainAll(requestedScopes);
        return scopes;
    }
}

Example scope validator plugin

Complete the following steps to implement a scope validator script that modifies the list of valid scopes.

To configure AM to use a Java scope validator plugin, refer to Configure AM to use a Java OAuth 2.0 plugin.

Configure the scope validator script

This task describes how to modify the default script to add an extra scope value. To create a new script instead, refer to Manage scripts (UI), and reference the new script name when you configure the provider.

  1. In the AM admin UI, go to Realms > Realm Name > Scripts, and click OAuth2 Scope Validator Script.

  2. In the Script field:

    • Update the script by inserting the following line of code preceding return scopes; on line 69:

       scopes.add("customscope");
  3. Save your changes.

The default scope validator script is now amended to add customscope to the requested scopes.

Configure AM to use the custom scope validator script

Perform this task to set up the OAuth2 provider to use the scope validator script.

  1. Configure the provider and ensure the following properties are set:

    • Scope Validator Plugin Type to SCRIPTED.

    • Scope Validator Script to OAuth2 Scope Validator Script.

    If you created a new script rather than editing the default, you must reference the new script name here.

  2. Save your changes.

Create an OAuth2 client

Create an OAuth 2.0 client to use in the client credentials grant flow.

  1. In the AM console, go to Realms > Realm Name > Applications > OAuth 2.0 > Clients, and click Add Client.

  2. Enter the following values:

    • Client ID: myClient

    • Client secret: forgerock

    • Redirection URIs: https://www.example.com:443/callback

    • Scope(s): access

  3. In Advanced > Grant Types, add Client Credentials.

  4. Click Create.

  5. Save your changes.

AM is now configured for you to try the sample scope validator script.

Try the custom scope validator plugin script

To try your custom script, use the Client credentials grant flow.

  1. Send a POST request to the /oauth2/access_token endpoint, specifying the grant type as client_credentials, scope as access, and your client details.

    For example:

    $ curl \
    --request POST \
    --data "grant_type=client_credentials" \
    --data "client_id=myClient" \
    --data "client_secret=forgerock" \
    --data "scope=access" \
    "https://openam.example.com:8443/openam/oauth2/realms/root/realms/alpha/access_token"
    {
      "access_token": "M3M2Jb2SMjvgWhzNas2SVy2LALg",
      "scope": "access",
      "token_type": "Bearer",
      "expires_in": 3599
    }
  2. Call the oauth2/tokeninfo endpoint to inspect the custom scope values. Include the access token value obtained in the previous request.

    For example:

    $ curl \
    "https://openam.example.com:8443/openam/oauth2/realms/root/realms/alpha/tokeninfo\
    ?access_token=M3M2Jb2SMjvgWhzNas2SVy2LALg"
    {
      "access_token": "M3M2Jb2SMjvgWhzNas2SVy2LALg",
      "access": "",
      "grant_type": "client_credentials",
      "auditTrackingId": "f9a8395d-1bac-4cba-8b09-8cc336dc49e2-6810",
      "scope": ["access", "customscope"],
      "realm": "/alpha",
      "token_type": "Bearer",
      "expires_in": 3583,
      "authGrantId": "l3355H89FDSWsfdKJmvWssGk_oE",
      "customscope": "",
      "client_id": "myClient"
    }

    Verify that the response contains both the requested scope and the additional scope, customscope.

Scope validator scripting API

The following properties are available to scope validator scripts.

Binding Description

allowedScopes

The set of scope strings AM allows this client to request.

defaultScopes

The set of scope strings configured as defaults for this client.

httpClient

An HTTP client for making external HTTP requests.

The logger instance for the script.

Logger names use the format scripts.OAUTH2_VALIDATE_SCOPE.<script UUID>.(<script name>).

Refer to Debug logging.

requestedScopes

The set of scope strings in the client request.

scriptName

The display name of the script.