Identity Cloud

Scripted decision node API

A Scripted Decision node calls server-side JavaScript to set the outcome for the node programmatically and determine the path the authentication journey takes. The script can perform actions before setting the outcome.

Create or edit a journey decision node script directly from within in the journey editor.

When configuring the Scripted Decision node, add the two outcomes true and false in Outcomes. Each outcome appears as a node endpoint that you connect to other nodes in the journey.

The outcome strings aren’t limited to true and false. Specify a value for each possible outcome and as many outcomes as required by the journey.

Use the action object to set the outcome.

Script bindings

In addition to the common bindings, a decision node script has access to the following specific bindings, predefined objects that Identity Cloud injects into the script execution context.

Identity Cloud has introduced a next-generation scripting engine that offers several benefits, including enhanced script bindings.

For decision node scripts, the availability and usage of bindings depend on the script engine version of the script: legacy or next-generation. Both versions are described in this section.

The next-generation script engine is only available to the Scripted decision node API.

For information about migrating to the enhanced scripting engine, refer to Migrating to next-generation scripts.

Binding Description Further information

action (1)

Set the script outcome and perform script-related actions.

auditEntryDetail

Add information to the Identity Cloud audit logs.

callbacksBuilder(1) callbacks

Request additional data from the user using a callback.

existingSession

If the user has previously authenticated and has a session, use this binding to access the properties of that session.

httpClient

Make outbound HTTP calls.

idRepository

Access the data stored in the user’s profile.

jwtAssertion(1)

Generate JWT assertions in scripts.

jwtValidator(1)

Validate JWT assertions in scripts.

logger

Write a message to the Identity Cloud debug log.

realm

Return the name of the realm to which the user is authenticating as a string.

For example, authenticating to the alpha realm returns a string value of /alpha.

requestHeaders

Access the HTTP headers provided in the login request.

requestParameters

Access the HTTP request parameters provided in the login request.

resumedFromSuspend

Boolean to indicate whether evaluation has resumed after suspension.

For example, the value returns True after sending an email and receiving the response.

secrets

Access the secrets configured for Identity Cloud in the environment.

nodeState

Access data set by previous nodes in the journey, or store data to be used by subsequent nodes.

openidm(1)

Access scripted functions in IDM to manage resources.

scriptName

Return the name of the running script.

systemEnv

Lets you get the value of an environment secret or variable (ESV).

(1) Not available in Legacy scripts.

Set script outcome

Use the action object to define the outcome or to perform an operation with the following supported methods:

Action:

  • public static ActionBuilder goTo(String outcome)

Action.ActionBuilder:

Method Information

public ActionBuilder putSessionProperty(String key, String value)

public ActionBuilder removeSessionProperty(String key)

Remove an existing session property.

public ActionBuilder withDescription(String description)

Set a description for the action.

public ActionBuilder withErrorMessage(String errorMessage)

Set an error message to display to the end user when the journey reaches the Failure node.

public ActionBuilder withLockoutMessage(String errorMessage)

Set an error message to display to the end user when the account is locked or inactive.

public ActionBuilder withStage(String stage)

Set a stage for the action.

For more information, refer to ActionBuilder.

Use action instead of the outcome variable to define the exit path from the node. The action object takes precedence and overrides the value set for the outcome variable, and can be used for other operations, such as adding and removing session properties, and setting error messages.

  • Next-generation

  • Legacy

// Evaluation continues along the "false" outcome
action.goTo("false").withErrorMessage(error);

 // No effect
outcome = "true";

Import the Action class to access the goTo method. Optionally, chain with ActionBuilder functions.

For details, refer to Action.

var fr = JavaImporter(org.forgerock.openam.auth.node.api.Action);

// Evaluation continues along the "false" outcome
action = fr.Action.goTo("false").withErrorMessage(error).build();

 // No effect
outcome = "true";

A script can also use the action object to set session properties and callbacks.

Access request header

A script can access the headers in the login request with the methods of the requestHeaders object.

The script has access to a copy of the headers. Changing their values does not affect the request.

String[] requestHeaders.get(String headerName)

Returns an array of the values in the named request header, or null, if the property is not set.

Header names are case-sensitive.

  • Next-generation

  • Legacy

if (requestHeaders.get("user-agent").get(0).indexOf("Chrome") !== -1) {
    action.goTo("true");
} else {
    action.goTo("false");
}
var fr = JavaImporter(org.forgerock.openam.auth.node.api.Action);

if (requestHeaders.get("user-agent").get(0).indexOf("Chrome") !== -1) {
    action = fr.Action.goTo("true").build();
} else {
    action = fr.Action.goTo("false").build();
}

Access request parameters

A script can access the query parameters in the login request with the methods of the requestParameters object.

The script has access to a copy of the parameters. Changing their values doesn’t affect the request.

String[] requestParameters.get(String parameterName)

Return an array of the values in the named request parameter, or null, if the parameter is not available.

  • Next-generation

  • Legacy

var service;
var authIndexType = requestParameters.get("authIndexType");

if (authIndexType && String(authIndexType.get(0)) === "service") {
    service = requestParameters.get("authIndexValue").get(0);
}

if (service) {
    nodeState.putShared("service", service);
}
action.goTo("true");
var fr = JavaImporter(org.forgerock.openam.auth.node.api.Action);

var service;
var authIndexType = requestParameters.get("authIndexType");

if (authIndexType && String(authIndexType.get(0)) === "service") {
    service = requestParameters.get("authIndexValue").get(0);
}

if (service) {
    nodeState.putShared("service", service);
}
action = fr.Action.goTo("true").build();

In JavaScript, the data type (typeof) of requestParameters values is object.

Convert the values to strings before using strict equality comparisons.

Access shared state data

A script can access the shared state of the journey with the methods of the nodeState object.

The sharedState and transientState bindings are deprecated, and are removed in the next-generation scripting engine.

You can still access the different states with the nodeState object, which replaces the sharedState and transientState bindings.

For example, use nodeState.putShared() instead of sharedState.put(), and nodeState.putTransient() instead of transientState.put(). Use nodeState.get() to retrieve shared and transient state properties.

There are three types of state:

Shared

Non-sensitive state.

Transient

Sensitive state.

Transient state data is never sent back to the user’s browser in a callback so doesn’t need to be encrypted. The transient state is for sensitive data and for data not required after the next callback.

Secure

Encrypted sensitive state.

Secure state data is sent back to the user’s browser encrypted as part of the shared state object.

Transient state data is promoted to secure state data when:

  • A callback to the user is about to occur.

  • A downstream node is detected in the journey, requesting data in the transient state as script input.

Unless the downstream node explicitly requests the secure state data by name, the authentication journey removes it from the node state after processing the next callback.

For example, a node in a registration journey stores a user’s password in transient state. The node sends a callback to the user before an inner tree node, downstream in the journey, consumes that password. As part of the callback, the journey assesses what to add to the secure state. It does this by checking the state inputs that downstream nodes in the journey require. Nodes that only request * are ignored, as this would result in putting everything that’s in transient state into secure state, and retaining sensitive information longer than necessary.

If a downstream node requires the password, it must therefore explicitly request it as state input, even if it lists the * wildcard as input.

<returnvalue> nodeState.get(String propertyName)

Returns the value of the named property.

The value may come from the transient, secure, or shared states, in that order. If the same property is available in several states, the method returns the value of the property in the transient state first.

If the property isn’t set, the method returns null.

  • Next-generation

  • Legacy

Returns the value as an Object. The JavaScript return type is coerced, so you no longer need to call functions such as asString() or asMap().

var currentAuthLevel = nodeState.get("authLevel");
var thePassword = nodeState.get("password");

action.goTo("true");

Returns the value as a JsonValue. Use functions such as asString() or asMap() to convert to the expected type.

var fr = JavaImporter(org.forgerock.openam.auth.node.api.Action);

var currentAuthLevel = nodeState.get("authLevel");
var thePassword = nodeState.get("password").asString();

action = fr.Action.goTo("true").build();
<returnvalue> nodeState.getObject(String propertyName)

Returns the value of the named property.

If the value is a map, this method combines and returns the values stored in transient, secure, and shared state.

If the property isn’t set, the method returns null.

The getObject method returns an immutable object. If you want to update the object, use nodeState.get(String propertyName) instead. The get method doesn’t combine values but returns the first value found in transient, secure, or shared state (in that order). You can then modify the returned object.

For example:

var attributes = nodeState.get("objectAttributes");
if (attributes) {
  attributes.put("mail", "test@example.com");
  nodeState.putShared("objectAttributes", attributes);
}

action.goTo("true");
  • Next-generation

  • Legacy

Returns the value as an Object. The JavaScript return type is coerced.

var attributes = nodeState.getObject("objectAttributes");

action.goTo("true");

Returns the value as a JsonValue. Use functions such as asString() or asMap() to convert to the expected type.

var fr = JavaImporter(org.forgerock.openam.auth.node.api.Action);

var attributes = nodeState.getObject("objectAttributes").asMap();

action = fr.Action.goTo("true").build();
<returnvalue> nodeState.putShared(String propertyName, String propertyValue)

Sets the value of the named shared state property.

  • Next-generation

  • Legacy

Returns a modified instance of NodeStateScriptWrapper.

try {
  var thePassword = nodeState.get("password");
} catch (e) {
  nodeState.putShared("errorMessage", e.toString());
}

action.goTo("true");

Returns a modified instance of NodeState.

var fr = JavaImporter(org.forgerock.openam.auth.node.api.Action);

try {
  var thePassword = nodeState.get("password").asString();
} catch (e) {
  nodeState.putShared("errorMessage", e.toString());
}

action = fr.Action.goTo("true").build();
<returnvalue> nodeState.putTransient(String propertyName, String propertyValue)

Sets the value of the named transient state property.

  • Next-generation

  • Legacy

Returns a modified instance of NodeStateScriptWrapper.

nodeState.putTransient("sensitiveKey", "sensitiveValue");

action.goTo("true");

Returns a modified instance of NodeState.

var fr = JavaImporter(org.forgerock.openam.auth.node.api.Action);

nodeState.putTransient("sensitiveKey", "sensitiveValue");

action = fr.Action.goTo("true").build();

Access profile data

A script can access profile data through the methods of the idRepository object.

In these examples, an Identity Store Decision node with Username as Universal Identifier enabled precedes the Scripted Decision node that uses the script. As a result, when you call nodeState.get('username') the function returns the user’s _id, which is required to get the identity object.

Get attribute values

Returns the values of the named attribute for the named user.

  • Next-generation

  • Legacy

// Get UUID by enabling `Username as Universal Identifier`
// in a preceding Identity Store Decision node
var uuid = nodeState.get("username");
var attribute = "mail";

// Get identity object separately
var identity = idRepository.getIdentity(uuid);

// Returns all values as an array, for example: ["test@example.com", "user@example.com"]
identity.getAttributeValues(attribute);

// Returns the first value, for example:  test@example.com
identity.getAttributeValues(attribute)[0];

// If no attribute by this name is found, the result is an empty array: []
identity.getAttributeValues("non-existent-attribute");

action.goTo("true");
var fr = JavaImporter(org.forgerock.openam.auth.node.api.Action);

// Get UUID by enabling `Username as Universal Identifier`
// in a preceding Identity Store Decision node
var uuid = nodeState.get("username").asString();
var attribute = "mail";

// Returns all values, for example: [test@example.com, user@example.com]
idRepository.getAttribute(uuid, attribute).toString();

// Returns the first value, for example:  test@example.com
idRepository.getAttribute(uuid, attribute).iterator().next();

// Returns a value at the specified index, for example: user@example.com
idRepository.getAttribute(uuid, attribute).toArray()[1];

// If no attribute by this name is found, the result is an empty array: []
idRepository.getAttribute(uuid, "non-existent-attribute").toString();

action = fr.Action.goTo("true").build();
Set attribute values

Sets the named attribute as specified by the attribute value for the named user, and persists the result in the user’s profile.

  • Next-generation

  • Legacy

// Get UUID by enabling `Username as Universal Identifier`
// in a preceding Identity Store Decision node
var uuid = nodeState.get("username");

// Get identity separately
var identity = idRepository.getIdentity(uuid);

// Set the attribute directly on the identity object
identity.setAttribute("mail", ["test@example.com"]);

try {
  // Explicitly persist data
  // throws an exception if setAttribute failed
  identity.store();
  action.goTo("true");
} catch(e) {
  logger.error("Unable to persist attribute. " + e);
  action.goTo("false");
}

You must explicitly call store() to persist changes to attribute values.

var fr = JavaImporter(org.forgerock.openam.auth.node.api.Action);

// Get UUID by enabling `Username as Universal Identifier`
// in a preceding Identity Store Decision node
var uuid = nodeState.get("username").asString();

// Set attribute using the idRepository object
idRepository.setAttribute(uuid, "mail", ["test@example.com"]);

try {
  // check setAttribute was successful
  var mail = idRepository.getAttribute(uuid, "mail").iterator().next();
  action = fr.Action.goTo("true").build();
} catch(e) {
  logger.error("Unable to persist attribute. " + e);
  action = fr.Action.goTo("false").build();
}
Add attribute values

Add an attribute value to the list of attribute values associated with the attribute name for a particular user.

  • Next-generation

  • Legacy

// Get UUID by enabling `Username as Universal Identifier`
// in a preceding Identity Store Decision node
var uuid = nodeState.get("username");

// Get identity separately
var identity = idRepository.getIdentity(uuid);

// Add a value as a string.
identity.addAttribute("mail", "user@example.com");

try {
  // Explicitly persist data
  // throws an exception if addAttribute failed
  identity.store();
  action.goTo("true");
} catch(e) {
  logger.error("Unable to persist attribute. " + e);
  action.goTo("false");
}

You must explicitly call store() to persist changes to attribute values.

var fr = JavaImporter(org.forgerock.openam.auth.node.api.Action);

// Get UUID by enabling `Username as Universal Identifier`
// in a preceding Identity Store Decision node
var uuid = nodeState.get("username").asString();
var attr = "mail";

// get number of existing attribute values
var mail = idRepository.getAttribute(uuid, attr).toArray();

// Add attribute using the idRepository object
idRepository.addAttribute(uuid, attr, ["test@example.com"]);

// check addAttribute was successful
var updatedmail = idRepository.getAttribute(uuid, attr).toArray();
if (updatedmail.length > mail.length) {
  action = fr.Action.goTo("true").build();
} else {
  logger.error("Unable to add attribute.");
  action = fr.Action.goTo("false").build();
}

Set session properties

A script can set session properties with the fields and methods of the Action interface.

The following example sets the outcome to true, and adds a custom session property:

  • Next-generation

  • Legacy

action.goTo("true").putSessionProperty("mySessionProperty", "myPropertyValue");
var fr = JavaImporter(org.forgerock.openam.auth.node.api.Action);

action = fr.Action.goTo("true").putSessionProperty("mySessionProperty", "myPropertyValue").build();

When adding a session property, make sure it is in the Identity Cloud allowlist. Identity Cloud does not allow the script to add it to sessions unless it is in the allowlist.

  1. In AM admin UI, under Realms > Realm Name > Services, make sure the Session Property Whitelist Service is configured.

    If not, configure the service with the default settings.

  2. Add the property name to the Allowlisted Session Property Names list unless it is already present.

For details, refer to Session Property Whitelist Service.

Add the script to a Scripted Decision node in your authentication journey. When a user authenticates successfully, Identity Cloud adds the property to their session, as shown in the following output for session introspection:

{
  "username": "014c54bd-6078-4639-8316-8ce0e7746fa4",
  "universalId": "id=014c54bd-6078-4639-8316-8ce0e7746fa4,ou=user,o=alpha,ou=services,ou=am-config",
  "realm": "/alpha",
  "latestAccessTime": "2022-10-31T11:03:25Z",
  "maxIdleExpirationTime": "2022-10-31T11:33:25Z",
  "maxSessionExpirationTime": "2022-10-31T13:03:24Z",
  "properties": {
    "AMCtxId": "de5abe95-db97-4354-9d32-aab660ea23a3-4252446",
    "mySessionProperty": "myPropertyValue"
  }
}

Existing session properties

The existingSession binding is only present when performing a session upgrade. Any properties added by nodes earlier in the journey only appear on the user’s new session when the journey completes; such properties aren’t available in the existingSession binding.

A script can access existing session properties during a session upgrade request with the existingSession.get method.

String existingSession.get(String propertyName)

Returns the string value of the named existing session property, or null, if the property is not set.

If the current request isn’t a session upgrade and doesn’t provide an existing session, the existingSession variable isn’t declared. Check for a declaration before attempting to access the variable.

  • Next-generation

  • Legacy

if (typeof existingSession !== 'undefined') {
    var existingAuthLevel = existingSession.get("AuthLevel")
} else {
    nodeState.putShared("errorMessage", "Variable existingSession not declared - not a session upgrade.")
}

action.goTo("true");
var fr = JavaImporter(org.forgerock.openam.auth.node.api.Action);

if (typeof existingSession !== 'undefined') {
    var existingAuthLevel = existingSession.get("AuthLevel")
} else {
    nodeState.putShared("errorMessage", "Variable existingSession not declared - not a session upgrade.")
}

action = fr.Action.goTo("true").build();

Generate and validate JWTs

Use the jwtAssertion and jwtValuation bindings to include JWT operations in your script.

The jwtAssertion binding lets you generate a signed and/or encrypted JWT, for example, for securely transporting JWT claims that can be verified later in the journey via an emailed magic link.

The jwtValuation binding lets you decrypt and validate JWTs; for example, to verify JWT claims from another system such as IG.

String jwtAssertion.generateJwt(Map<String, Object> jwtData)

Provide the following data for generating a JWT assertion:

Data field Description

jwtType

(Required)

The type of JWT to generate: SIGNED, SIGNED_THEN_ENCRYPTED, or ENCRYPTED_THEN_SIGNED.

jwsAlgorithm

(Required) HS256 or RS256 (jwtType must be SIGNED).

accountId

(Required) The account identifier for the JWT subject (sub) and issuer (iss) claims.

audience

(Required) The JWT audience (aud) claim value.

validityMinutes

The duration of the validity of the JWT in minutes.

signingKey

The base64-encoded JSON Web Key used to sign/verify the JWT.

JWTS are signed using the HS256 or RS256 algorithms.

encryptionKey

The JSON Web Encryption (JWE) public key used to encrypt/decrypt the JWT.

JWTs are encrypted using the A128CBC-HS256 algorithm.

  • Next-generation

  • Legacy

var hmacJwtData = {
  jwtType: "ENCRYPTED_THEN_SIGNED",
  jwsAlgorithm: "HS256",
  accountId: "accountId",
  audience: "https://am.localtest.me:8080/am/oauth2/access_token",
  validityMinutes: 10,
  signingKey: "cGFzc3dvcmQ=",
  encryptionKey: "Syz1K5XQCZtq7FkE+GNvgZPeFyvUXJdemIW7CQjM18U="
};
// returns a string representation of the JWT
var assertionJwt = jwtAssertion.generateJwt(hmacJwtData);

action.goTo("true");

Not available in Legacy bindings

Map<String, Object> validateJwtClaims(Map<String, Object> jwtData)

Provide the following data for validating a JWT:

Data field Description

jwtType

(Required) The type of JWT to validate: SIGNED, SIGNED_THEN_ENCRYPTED, or ENCRYPTED_THEN_SIGNED.

jwt

(Required) The JWT object to validate.

accountId

(Required) The account identifier for the JWT subject (sub) and issuer (iss) claims.

audience

(Required) The JWT audience (aud) claim value.

signingKey

The base64-encoded JSON Web Key used to sign/verify the JWT.

JWTS are signed using the HS256 or RS256 algorithms.

encryptionKey

The JSON Web Encryption (JWE) public key used to encrypt/decrypt the JWT.

JWTs are encrypted using the A128CBC-HS256 algorithm.

  • Next-generation

  • Legacy

var jwtData = {
  jwtType: "ENCRYPTED_THEN_SIGNED",
  jwt: assertionJwt,
  accountId: "accountId",
  audience: "https://am.localtest.me:8080/am/oauth2/access_token",
  signingKey: "cGFzc3dvcmQ=",
  encryptionKey: "Syz1K5XQCZtq7FkE+GNvgZPeFyvUXJdemIW7CQjM18U="
};
try {
  // returns a map of JWT claims or null if required claims are missing
  // throws NoSuchSecretException if verification key is missing
  var jwtClaims = jwtValidator.validateJwtClaims(jwtData);

  if (jwtClaims !== null) {
    logger.debug("Audience: " + jwtClaims.get("audience"));
    logger.debug("ExpirationTime: " + jwtClaims.get("expirationTime"));
    logger.debug("IssuedAtTime: " + jwtClaims.get("issuedAtTime"));
    logger.debug("Issuer: " + jwtClaims.get("issuer"));
    logger.debug("JWTId: " + jwtClaims.get("jwtId"));
    logger.debug("Subject: " + jwtClaims.get("subject"));
    action.goTo("true");
  } else {
    logger.error("Invalid JWT claims");
    action.goTo("false");
  }
} catch(e) {
  logger.error("Invalid JWT signing key");
  action.goTo("false");
}

Not available in Legacy bindings

Use callbacks

A script can use callbacks to provide or prompt for additional information during the authentication process.

The following script checks for a password and stores the username to shared state for use by subsequent nodes in the authentication journey.

  • Next-generation

  • Legacy

Next-generation callback functionality is split between two bindings:

  • callbacksBuilder: Request callbacks. Callbacks are sent automatically when the script completes.

    callbacksBuilder request methods
    • public void textOutputCallback(int messageType, String message)

    • public void suspendedTextOutputCallback(int messageType, String message)

    • public void hiddenValueCallback(String id, String value)

    • public void choiceCallback(String prompt, String[] choices, int defaultChoice, boolean multipleSelectionsAllowed)

    • public void nameCallback(String prompt)

    • public void nameCallback(String prompt, String defaultName)

    • public void passwordCallback(String prompt, boolean echoOn)

    • public void textInputCallback(String prompt)

    • public void textInputCallback(String prompt, String defaultText)

    • public void scriptTextOutputCallback(String message)

    • public void redirectCallback(String redirectUrl, Map redirectData, String method)

    • public void redirectCallback(String redirectUrl, Map redirectData, String method, String statusParameter, String redirectBackUrlCookie)

    • public void metadataCallback(Object outputValue)

    • public void stringAttributeInputCallback(String name, String prompt, String value, Boolean required)

    • public void stringAttributeInputCallback(String name, String prompt, String value, Boolean required, List<String> failedPolicies)

    • public void stringAttributeInputCallback(String name, String prompt, String value, Boolean required, Object policies, Boolean validateOnly)

    • public void stringAttributeInputCallback(String name, String prompt, String value, Boolean required, Object policies, Boolean validateOnly, List<String> failedPolicies)

    • public void numberAttributeInputCallback(String name, String prompt, Double value, Boolean required)

    • public void numberAttributeInputCallback(String name, String prompt, Double value, Boolean required, List<String> failedPolicies)

    • public void numberAttributeInputCallback(String name, String prompt, Double value, Boolean required, Object policies, Boolean validateOnly)

    • public void numberAttributeInputCallback(String name, String prompt, Double value, Boolean required, Object policies, Boolean validateOnly, List<String> failedPolicies)

    • public void booleanAttributeInputCallback(String name, String prompt, Boolean value, Boolean required)

    • public void booleanAttributeInputCallback(String name, String prompt, Boolean value, Boolean required, List<String> failedPolicies)

    • public void booleanAttributeInputCallback(String name, String prompt, Boolean value, Boolean required, Object policies, Boolean validateOnly)

    • public void booleanAttributeInputCallback(String name, String prompt, Boolean value, Boolean required, Object policies, Boolean validateOnly, List<String> failedPolicies)

    • public void confirmationCallback(int messageType, int optionType, int defaultOption)

    • public void confirmationCallback(int messageType, String[] options, int defaultOption)

    • public void confirmationCallback(String prompt, int messageType, int optionType, int defaultOption)

    • public void confirmationCallback(String prompt, int messageType, String[] options, int defaultOption)

    • public void languageCallback(String language, String country)

    • public void idPCallback(String provider, String clientId, String redirectUri, List<String> scope, String nonce, String request, String requestUri, List<String> acrValues, boolean requestNativeAppForUserInfo)

    • public void idPCallback(String provider, String clientId, String redirectUri, List<String> scope, String nonce, String request, String requestUri, List<String> acrValues, boolean requestNativeAppForUserInfo, String token, String tokenType)

    • public void pollingWaitCallback(String waitTime, String message)

    • public void validatedPasswordCallback(String prompt, boolean echoOn, Object policies, Boolean validateOnly)

    • public void validatedPasswordCallback(String prompt, boolean echoOn, Object policies, Boolean validateOnly, List<String> failedPolicies)

    • public void validatedUsernameCallback(String prompt, Object policies, Boolean validateOnly)

    • public void validatedUsernameCallback(String prompt, Object policies, Boolean validateOnly, List<String> failedPolicies)

    • public void httpCallback(String authorizationHeader, String negotiationHeader, String errorCode)

    • public void httpCallback(String authRHeader, String negoName, String negoValue, int errorCode)

    • public void x509CertificateCallback(String prompt)

    • public void x509CertificateCallback(String prompt, X509Certificate certificate)

    • public void x509CertificateCallback(String prompt, X509Certificate certificate, boolean requestSignature)

    • public void consentMappingCallback(Object config, String message, Boolean isRequired)

    • public void consentMappingCallback(String name, String displayName, String icon, String accessLevel, List<String> titles, String message, Boolean isRequired)

    • public void deviceProfileCallback(Boolean metadata, Boolean location, String message)

    • public void kbaCreateCallback(String prompt, List<String> predefinedQuestions, boolean allowUserDefinedQuestions)

    • public void selectIdPCallback(Object providers)

    • public void termsAndConditionsCallback(String version, String terms, String createDate)

  • callbacks: Use isEmpty() to check if callbacks have returned to Identity Cloud. Use public get methods to retrieve input from interactive and backchannel callbacks.

    callbacks public get methods
    Method Return type Description

    getBooleanAttributeInputCallbacks()

    List<Boolean>

    The collected Boolean value

    getChoiceCallbacks()

    List<int[]>

    The selected choices as indexes

    getConfirmationCallbacks()

    List<Integer>

    The selected confirmation option

    getConsentMappingCallbacks()

    List<Boolean>

    The collected Boolean value

    getDeviceProfileCallbacks()

    List<String>

    The device information in escaped JSON format

    getHttpCallbacks()

    List<String>

    The authorization token

    getIdpCallbacks()

    List<Map<String, Object>>

    A map of IDP callback data. Values are:

    • nodeName (String)

    • provider (String)

    • clientId (String)

    • redirectUri (String)

    • scope (List<String>)

    • nonce (String)

    • request (String)

    • requestUri (String)

    • acrValues (List<String>)

    • token (String)

    • tokenType (String)

    • userInfo (String)

    • requestNativeAppForUserInfo (boolean)

    getKbaCreateCallbacks()

    List<Map<String, String>>

    A map of knowledge-based authentication (KBA) responses. Values are selectedQuestion and selectedAnswer.

    getLanguageCallbacks()

    List<String>

    The selected locale

    getNameCallbacks()

    List<String>

    The collected name value

    getNumberAttributeInputCallbacks()

    List<Double>

    The collected numeric value

    getPasswordCallbacks()

    List<String>

    The collected password value

    getSelectIdPCallbacks()

    List<Map<String, Object>>

    A map of selected IDP providers in JSON format

    getStringAttributeInputCallbacks()

    List<String>

    The collected String value

    getTermsAndConditionsCallbacks()

    List<Boolean>

    The Boolean acceptance value

    getTextInputCallbacks()

    List<String>

    The collected text as a String value (can be null)

    getValidatedPasswordCallbacks()

    List<Map<String, Object>>

    A map with the password returned as value (String) and validateOnly(whether to only validate input, or validate and continue journey)

    getValidatedUsernameCallbacks()

    List<Map<String, Object>>

    A map with the username returned as value (String) and validateOnly(whether to only validate input, or validate and continue journey)

    getX509CertificateCallbacks()

    List<Map<String, Object>>

    A map of X.509 certificate callback data. Values are:

    • certificate (X509Certificate)

    • signature (String)

    • reqSignature (Boolean)

if (callbacks.isEmpty()) {
  // Request callbacks
  callbacksBuilder.nameCallback("User Name", "User Name");
  callbacksBuilder.passwordCallback("Password", false);
} else {
  // Callbacks returned from browser, save username and password
  var username = callbacks.getNameCallbacks().get(0);
  var password = callbacks.getPasswordCallbacks().get(0);

  nodeState.putShared("username", username);

  if (password === null || !password) {
    action.goTo("false");
  } else {
    nodeState.putTransient("password", password);
    action.goTo("true";
  }
}
var fr = JavaImporter(
  org.forgerock.openam.auth.node.api.Action,
  javax.security.auth.callback.NameCallback,
  javax.security.auth.callback.PasswordCallback,
  java.lang.String
);

if (callbacks.isEmpty()) {
  // Request callbacks
  action = fr.Action.send(
    new fr.NameCallback("User Name"),
    new fr.PasswordCallback("Password", false)).build();
} else {
  // Callbacks returned with credentials
  var username = fr.String(callbacks.get(0).getName());
  var password = fr.String(callbacks.get(1).getPassword());

  sharedState.put("username", username);
  if (password === null || !password) {
    action = fr.Action.goTo("false").build();
  } else {
    transientState.put("password", password);
    action = fr.Action.goTo("true").build();
  }
}

For a list of supported callbacks, refer to Supported callbacks.

Access IDM scripting functions

The openidm binding lets you manage an IDM resource by calling scripting functions directly from a decision node script.

The following CRUDPAQ functions are supported:

  • create

  • read

  • update

  • delete

  • patch

  • action

  • query

For more information, refer to Scripting functions.

The openidm binding provides administrative access to IDM functions. Use it with caution to prevent the exposure of sensitive data.

The following example illustrates how to create a user, update their details, send an email, and finally delete the user:

  • Next-generation

  • Legacy

// create
var newUser = openidm.create("managed/alpha_user", null, {
  "userName": "testUser",
  "mail": "foo@bar.com",
  "givenName": "Foo",
  "sn": "Bar"});

var userID = newUser._id;

// read - returns entire json object
var user = openidm.read("managed/alpha_user/" + userID);

// update - replace object
user.description = 'New description';
var updatedUser = openidm.update("managed/alpha_user/" + userID, null, user);

// patch - selectively modify object
var patchedUser = openidm.patch("managed/alpha_user/" + userID, null, [{
        "operation":"replace",
        "field":"/mail",
        "value":"new@example.com"
}]);

// send email
var actionResponse = openidm.action("external/email", "send", {
    "from": "admin@example.com",
    "to": patchedUser.mail,
    "subject": "Example email",
    "body": "This is an example"
});

// delete
openidm.delete('managed/alpha_user/'+ userID, null);

action.goTo("true";

Not available in Legacy bindings

Add information to authentication audit log entries

A script can add information to audit log entries with the auditEntryDetail variable. Identity Cloud appends the value of the variable to the authentication audit logs, which corresponds to the am-authentication log source.

The auditEntryDetail variable can hold either a string or a JSON object:

  • To add a string to authentication audit log entries:

    auditEntryDetail = "Additional audit information"
  • To add a JSON object to authentication audit log entries:

    auditEntryDetail = {
        "transactionStatus": "Success"
    }

    ForgeRock recommends that you do not put spaces in the keys of your JSON objects as it prevents you from using a query filter to search your additional audit information. ForgeRock recommends that you don’t put spaces in the keys of JSON objects as it prevents you from using a query filter to search additional audit information. For example, the following JSON would not be searchable:

    auditEntryDetail = {
        "Transaction Status": "Success"
    }

Identity Cloud adds the value of auditEntryDetail to the payload > entries > info > nodeExtraLogging > auditInfo field of the audit log entry:

{
  "payload": {
    "_id": "de5abe95-db97-4354-9d32-aab660ea23a3-4392064",
    "component": "Authentication",
    "entries": [{
      "info": {
        "authLevel": "0",
        "displayName": "Scripted Decision",
        "nodeExtraLogging": {
          "auditInfo": {
            "transactionStatus": "Success"
          }
        },
        "nodeId": "d3a9a765-f5d7-41dd-b936-f862c8b672a2",
        "nodeOutcome": "true",
        "nodeType": "ScriptedDecisionNode",
        "treeName": "Test"
      }
    }],
    "eventName": "AM-NODE-LOGIN-COMPLETED",
    "level": "INFO",
    "principal": [
      "014c54bd-6078-4639-8316-8ce0e7746fa4"
    ],
    "realm": "/alpha",
    "source": "audit",
    "timestamp": "2022-10-31T13:06:38.195Z",
    "topic": "authentication",
    "trackingIds": [
      "de5abe95-db97-4354-9d32-aab660ea23a3-4391910"
    ],
    "transactionId": "bd52ff36-8b34-4819-8e50-68ca1961275b-request-4/0"
  },
  "timestamp": "2022-10-31T13:06:38.195401296Z",
  "type": "application/json",
  "source": "am-authentication"
}
Copyright © 2010-2024 ForgeRock, all rights reserved.