Scripting environment
AM implements a configurable scripting engine for each of the context types that are executed on the server. There are two versions of the scripting engine: next-generation and legacy.
- Next-generation
-
-
Supports scripts written in JavaScript
-
Lets you access external functionality through script bindings
-
Enables code reuse with library scripts
-
Available to some script types
-
- Legacy
-
-
Supports server-side scripts written in either JavaScript or Groovy, and client-side authentication scripts in JavaScript
-
Lets you access external functionality through allowlisted Java classes and a limited set of bindings
-
Available to all script types except for SAML 2.0 NameID mapper scripts
-
The scripting engines contain configuration for security settings and thread pool management.

Libraries
AM uses the following libraries:
-
Mozilla Rhino version 1.7.14 to run JavaScript.
Rhino has limited support for ES6 / ES2015 (JavaScript version 1.7). For more information, refer to Rhino ES2015 Support.
-
Groovy version 3.0.10 to support scripting in Groovy.
Access Java classes
The next-generation and legacy script engines let you include functionality offered by external Java classes in different ways.
- Next-generation scripts
-
To enhance security, the next-generation scripting engine doesn’t support a configurable allowlist for Java classes. Instead, use predefined bindings that access allowlisted Java classes.
To access external functionality, first check if next-generation bindings meet your requirements. If they don’t, consider implementing the functionality as a reusable library script.
For information about next-generation bindings and library scripts, refer to:
In cases where reimplementation isn’t possible, you can request the functionality be included as a secure script binding in a future release.
- Legacy scripts
-
Legacy scripts can only import Java classes on the allowlist. AM defines an allowlist per script type.
Allowlists and denylists contain class names that are allowed or denied execution respectively.
Classes called by the script are checked against the allowlist first and must match at least one pattern in the list. The denylist is applied after the allowlist and classes matching any pattern are disallowed.
To access Java classes in a script, import classes in the following way:
-
JavaScript
-
Groovy
var fr = JavaImporter( org.forgerock.openam.auth.node.api.Action, javax.security.auth.callback.NameCallback ); // Now use fr.Action, fr.NameCallback, and so on.
import org.forgerock.openam.auth.node.api.Action; import javax.security.auth.callback.NameCallback;
The legacy scripting engine lets you add classes to allowlists and denylists by specifying the class name or by using regular expressions.
You can also configure the scripting engine to make an additional call to the JVM security manager for each class that is accessed. The security manager throws an exception if a class isn’t allowed to execute.
Learn more about allowlisting and configuring script engine security in the following topics:
To reduce the need to allowlist Java classes, consider migrating your scripts to use the next-generation scripting engine, which includes enhanced built-in script bindings for accessing many common script operations and the ability to include third-party software with library scripts.
-
Security considerations
Consider the following points when configuring the security settings within each script engine:
- Use script bindings where possible
-
The predefined script bindings provide a stable API without the need to allowlist Java classes. Different bindings are available to different script types, or contexts.
For more information, refer to Script bindings.
- The scripting engine only validates directly accessible classes
-
The security settings only apply to classes that the script directly accesses. If the script calls
Foo.a()
and that method callsBar.b()
, the scripting engine will be unable to prevent it. You must consider the whole chain of accessible classes.Access includes actions such as:
-
Importing or loading a class.
-
Accessing any instance of that class. For example, passed as a parameter to the script.
-
Calling a static method on that class.
-
Calling a method on an instance of that class.
-
Accessing a method or field that returns an instance of that class.
-
- Potentially dangerous Java classes are denylisted by default
-
All Java reflection classes (
java.lang.Class
,java.lang.reflect.*
) are denylisted by default to avoid bypassing the security settings.The
java.security.AccessController
class is also denylisted by default to prevent access to thedoPrivileged()
methods.Don’t remove potentially dangerous Java classes from the denylist. - The allowlists and denylists match class or package names only
-
The allowlist and denylist patterns apply only to the exact class or package names involved. The script engine does not know anything about inheritance, so it is best to allowlist known, specific classes.
Thread pools
Each script is executed in an individual thread. Each scripting engine starts with an initial number of threads available for executing scripts. If no threads are available for execution, AM creates a new thread to execute the script, until the configured maximum number of threads is reached.
If the maximum number of threads is reached, pending script executions are queued in a number of buffer threads, until a thread becomes available for execution. If a created thread has completed script execution and has been idle for a configured time period, AM terminates the thread, shrinking the pool.
For more information on configuring script engine thread pools, refer to the Scripting service.