Access Management 7.2.2

Scripting API

AM provides the following functionality and artifacts for scripting:

Scripted module API

(Authentication chains only)

Access authentication state data, user profile data, request data, and information gathered by client-side scripts.

Scripted decision node API

(Authentication trees only)

Access data in request headers, shared state, and user session data.

Policy Condition Script API

Access the authorization state data, the information pertaining a session, and the user’s profile data in authorization policies.

Customize OAuth 2.0 with plugins

Extend authorization server behavior with the OAuth 2.0 plugins:

Token exchange scripting API

Add the may_act claim when performing OAuth 2.0 token exchange.

Accessing HTTP Services

Configure the parameters for the HTTP client object in any server-side script.

Debug logging

Add debug logging to any server-side script.

Configuring AM for token exchange

Add may_act claims to OAuth 2.0/OpenID Connect exchanged tokens.

Reference substituted properties in scripts

The systemEnv binding, available to all AM script types, includes an instance of the ScriptPropertyResolver class. This interface exposes the following methods:

  • JavaScript

  • Groovy

String getProperty(String propertyName);
String getProperty(String propertyName, String defaultValue);

where:

  • propertyName is the configuration expression (without the ampersand braces)

  • defaultValue is the default value set for that property in the configuration expression

String getProperty(String propertyName);
String getProperty(String propertyName, String defaultValue);
T getProperty(String propertyName, String defaultValue, Class<T> returnType);

where:

  • propertyName is the configuration expression (without the ampersand braces)

  • defaultValue is the default value set for that property in the configuration expression

  • T is the data type into which the value should be transformed; one of the following types:

    • String

    • Integer

    • Double

    • List

    • Map

    • Boolean

To reference a substituted property in a script, the property name must include a specific prefix. This prefix decreases the risk that random property values are resolved in scripts. Because property value substitution is often used to change secrets, you must be intentional about which properties you want to be able to resolve in scripts. The default prefix, for all script types, is script. You can change this prefix in the script type configuration. Select Configure > Global Services > Scripting > Secondary Configurations > Script Type > Secondary Configurations > Engine Configuration > Property Name Prefix.

Example: Property value resolution in a scripted decision node

These examples assume that the property name prefix script has been set in the script engine configuration for this script type. The scripts are used in a scripted decision node to get the values of the user’s email, hostname, port, and so on. The scripts also show type transformation where the type is not a string.

  • JavaScript

  • Groovy

// Properties should get resolved (set in AM)
var email = systemEnv.getProperty('script.tree.decision.node.email');
var name = systemEnv.getProperty('script.tree.decision.node.hostname', 'defaultHostname');
var port = systemEnv.getProperty('script.tree.decision.node.port', '587', java.lang.Integer);
var double = systemEnv.getProperty('script.tree.decision.node.double, '2.0', java.lang.Double);
var hasPort = systemEnv.getProperty('script.tree.decision.node.hasPort', 'false', java.lang.Boolean);
var map = systemEnv.getProperty('script.tree.decision.node.map', '{"defaultKey":"defaultValue"}', java.util.Map);
var list = systemEnv.getProperty('script.tree.decision.node.list', 'defaultValue', java.util.List);

// Properties should get resolved to their defaults (not set in AM)
var defaultName = systemEnv.getProperty('script.tree.decision.node.hostname.unresolved', 'defaultHostname');
var defaultPort = systemEnv.getProperty('script.tree.decision.node.port.unresolved', '587', java.lang.Integer);
var defaultDouble = systemEnv.getProperty('script.tree.decision.node.double.unresolved', '2.0', java.lang.Double);
var defaultHasPort = systemEnv.getProperty('script.tree.decision.node.hasPort.unresolved', 'false', java.lang.Boolean);
var defaultMap = systemEnv.getProperty('script.tree.decision.node.map.unresolved', '{"defaultKey":"defaultValue"}', java.util.Map);
var defaultList = systemEnv.getProperty('script.tree.decision.node.list.unresolved', 'defaultFirstValue,defaultSecondValue', java.util.List);

// Assert all property values - set the appropriate outcome
if (email === 'test@example.com' && name === 'testHostname' && port === 25 && double === 1.0 && hasPort === true
    && map.get('testKey') == 'testValue' && list == '[testFirstValue, testSecondValue]'
    && defaultName === 'defaultHostname' && defaultPort === 587 && defaultDouble === 2.0 && defaultHasPort === false
    && defaultMap.get('defaultKey') == 'defaultValue' && defaultList == '[defaultFirstValue, defaultSecondValue]') {
outcome = 'true';
} else {
outcome = 'false';
}
// Properties should get resolved (set in AM)
String email = systemEnv.getProperty('script.tree.decision.node.email');
String name = systemEnv.getProperty('script.tree.decision.node.hostname', 'defaultHostname');
Integer port = systemEnv.getProperty('script.tree.decision.node.port', '587', java.lang.Integer);
Double testDouble = systemEnv.getProperty('script.tree.decision.node.double', '2.0', java.lang.Double);
Boolean hasPort = systemEnv.getProperty('script.tree.decision.node.hasPort', 'false', java.lang.Boolean);
Map map = systemEnv.getProperty('script.tree.decision.node.map', '{\"defaultKey\":\"defaultValue\"}', java.util.Map);
List list = systemEnv.getProperty('script.tree.decision.node.list', 'defaultValue', java.util.List);

// Properties should get resolved to their defaults (not set in AM)
String defaultName = systemEnv.getProperty('script.tree.decision.node.hostname.unresolved', 'defaultHostname');
Integer defaultPort = systemEnv.getProperty('script.tree.decision.node.port.unresolved', '587', java.lang.Integer);
Double defaultDouble = systemEnv.getProperty('script.tree.decision.node.double.unresolved', '2.0', java.lang.Double);
Boolean defaultHasPort = systemEnv.getProperty('script.tree.decision.node.hasPort.unresolved', 'false', java.lang.Boolean);
Map defaultMap = systemEnv.getProperty('script.tree.decision.node.map.unresolved', '{\"defaultKey\":\"defaultValue\"}', java.util.Map);
List defaultList = systemEnv.getProperty('script.tree.decision.node.list.unresolved', 'defaultFirstValue,defaultSecondValue', java.util.List);

// Assert all property values - set the appropriate outcome
if (email.equals('test@example.com') && name.equals('testHostname') && port == 25 && testDouble == 1.0d && hasPort == true
    && defaultName.equals('defaultHostname') && defaultPort == 587 && defaultDouble == 2.0d && defaultHasPort == false
    && map.get('testKey').equals('testValue')
    && list.get(0).equals('testFirstValue') && list.get(1).equals('testSecondValue')
    && defaultMap.get('defaultKey').equals('defaultValue')
    && defaultList.get(0).equals('defaultFirstValue') && defaultList.get(1).equals('defaultSecondValue')) {

    outcome = 'true';
} else {
    outcome = 'false';
}

Reference ESVs in scripts

Use the esv prefix to reference ESVs from scripts. This prefix lets you create generic scripts that can be customized in different environments. For example:

var host = systemEnv.getProperty(esv.my.host);
Copyright © 2010-2024 ForgeRock, all rights reserved.