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:
-
Access token modification plugin Modify the key-value pairs contained within an OAuth 2.0 access token.
-
Authorize endpoint data provider plugin Return additional data from an authorization request.
-
Scope evaluator plugin Evaluate and return an OAuth2 access token’s scope information.
-
Scope validator plugin Customize the set of requested scopes for authorize, access token, refresh token and back channel authorize requests.
-
User info claims plugin Map scopes to claims and data for OpenID Connect ID tokens.
-
- 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';
}