Scripting in OpenAM 13

Scripting Design

This section introduces Client side and Server side scripts in OpenAM 13. These can be glued together to create Scripted Authentication modules that serve to create powerful authentication workflows as shown later in the Examples section.

Client Side Script

Authentication modules can use Client Side scripts and Server Side scripts using either JavaScript or Groovy. Note that the use of a Client side script is optional. If there is a requirement to collect information from the user, or browser plugins, fonts, screen resolution of a device, or even geolocation then by all means use the Client side script to collect and return the data to the Server side script.

The collected data is returned in the clientScriptOutputData object. You can use the .split() method to pull the client side data and parse accordingly.

An example Client side script is shown below.

 

Server Side Script

The Server side script handles authentication and is the place to put authentication workflow business logic. The Server side script has access to clientScriptOutputData and OpenAM’s powerful Scripting API. This script must set the authentication state to either success of failed, for example:

An example of using Server side scripts is as follows:

 

Chaining Scripted Authentication in OpenAM

You would setup your scripted module similar to any other authentication module in OpenAM, such as:

In this particular example, I have required DataStore to be a requisite module, followed immediately by a Scripted module that requires the authenticated user’s userId. See the following code snippet:

 

This Server side script is written in Groovy. The script reads the username and password from Shared State – a protected and shared area in memory – and uses the credential to make REST-based Policy calls to another OpenAM server (which could be a central policy hub in your enterprise, for example).

Scripting API

HTTP Commons Framework

OpenAM 13 introduces the HTTP Commons Framework. The following packages are available to developers:

org.forgerock.http.protocol.* – Request, Cookie, Entity, Header, Headers, and Response objects

org.forgerock.util.promise.* – Promise objects that represent the result of an asynchronous task in OpenAM

groovy.json.JsonSlurper – a very useful JSON parser that can be used in the scripts.

The API documentation is at http://commons.forgerock.org/bom/apidocs/index.html
You can use the new HTTP Commons Framework to create a new Request, and invoke REST API calls from the Server Side Script. For example: httpClient.send(Request), returns a Promise. Promise.get(), returns a Response. You may then parse the Response using JsonSlurper. The Server side script can access the Authentication State via the authState, and sharedState objects, as mentioned earlier.

Note that you will need to add the JsonSlurper, or any other class you wish to use, to the whitelist. Otherwise you will get a Security Exception stating use of the class is prohibited. You can whitelist a class using instructions documented here:

https://backstage.forgerock.com/#!/docs/openam/12.0.0/dev-guide/chap-scripted-auth-module#scripted-auth-module-sandbox

Logging

The logger object provides error(), message() and warning() methods for logging requirements.

Entity Profile

You are able to access user, group or device profile data via the idRepository object that provides the getAttribute(), setAttribute() and addAttribute() methods.

Original Request

You can also access the original login request using the requestData object, that provides the getHeader(s) and getParameter(s) methods.

Examples

Included here are some examples of using the Scripting API.

SSOToken

You can acquire an ssoToken object over REST

Policy Evaluation

Given the following two policies:

AuthnPolicy:

and AuthnPolicyY:

 

You can evaluate policy for the resource “authn/self’ and “authn/view”.

A policy decision is returned:

Check the policy decision and permit authentication if requested actions are ALLOWED:

Finally, logout the service account used for policy invocation using another REST call: