PingOne Advanced Identity Cloud

Migrate decision node scripts to next-generation scripts

Different bindings are available to the decision node script depending on the scripting engine version; legacy or next-generation.

Complete the steps described in Migrate to next-generation scripts, using the examples listed in the following table as a guide when updating the bindings:

Binding Next-generation change

New.

Use static method goTo() to set the script outcome.

To send callbacks, instead of calling Action.send(), use the new callbacksBuilder functionality.

New.

Instead of creating a Callback object and invoking Action.send(), add callbacks using static methods on the callbacksBuilder object; for example nameCallback and passwordCallback. These callbacks are automatically sent when the script completes.

Uses native JavaScript objects, similar to the Fetch API.

Class changed from ScriptIdentityRepository to ScriptedIdentityRepository.

Use getIdentity() method in addition to methods to get or set attributes.

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

New.

Generate JWT assertions in scripts.

New.

Validate JWT assertions in scripts.

Logger is now based on org.slf4j.Logger, instead of com.sun.identity.shared.debug.Debug.

The sharedState and transientState bindings are no longer supported.

New.

Use this binding to access the openidm scripting functions supported in IDM.

New.

Access the request cookies directly using this binding.

action

Use the action binding to define the exit path from the node and set properties.

  • Legacy

  • Next-generation

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

 // Journey continues along the "false" path
action = fr.Action.goTo("false").build();   1
 // Journey continues along the "false" path
action.goTo("false");                       1

1 No need to import the Action class to access the goTo method. Instead, call the goTo method directly on the action binding.

callbacksBuilder

Use the callbacksBuilder object instead of importing Callback classes.

Learn more in Use callbacks.

  • Legacy

  • Next-generation

var fr = JavaImporter(                       1
  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(                   2
    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 {                                   3
    transientState.put("password", password);
    action = fr.Action.goTo("true").build(); 4
  }
}
if (callbacks.isEmpty()) {                   1
  // Request callbacks
  callbacksBuilder.nameCallback(
    "User Name", "User Name");
  callbacksBuilder.passwordCallback(
    "Password", false);
} else {
  // Callbacks returned with credentials
  var username =
    callbacks.getNameCallbacks().get(0);
  var password =
    callbacks.getPasswordCallbacks().get(0);

  nodeState.putShared("username", username);

  if (password === null || !password) {
    action.goTo("false");                    2
  } else {
    nodeState.putTransient("password",       3
        password);
    action.goTo("true");                     4
  }
}

1 Use the callbacksBuilder object instead of importing Callback classes.
2 No need to explicitly call send(). The script sends every callback added to the callbacksBuilder when it completes.
3 Use nodeState.putShared() instead of sharedState.put() and nodeState.putTransient() instead of transientState.put().
4 No need to set the outcome, because action.goTo() was invoked.

idRepository

Get an identity from the idRepository object to access attribute values.

Learn more in Access profile data.

  • Legacy

  • Next-generation

var uuid = "3f5ab61c-1587-44b3-b7d4-675e5159fcca";

var mail = idRepository.getAttribute(
    uuid, "mail");                           1 2

idRepository.setAttribute(username, "mail",
    ["new@example.com"]);                    3
var uuid = "3f5ab61c-1587-44b3-b7d4-675e5159fcca";

var identity =
    idRepository.getIdentity(uuid);          1

var mail =
    identity.getAttributeValues("mail");     2

 // Does NOT automatically persist data
identity.setAttribute("mail",
    ["new@example.com"]);                    3

// persists data (throws an exception if setAttribute failed)
try {
    identity.store();                        4
} catch(e) {
    logger.error("Unable to persist attribute. " + e);
}

1 The idRepository object is no longer used to get attribute values. Instead, use the getIdentity() method of the new org.forgerock.openam.scripting.api.identity.ScriptIdentityRepository interface to get the identity object.
2 Use the identity object, instead of idRepository, to get or set attribute values.
3 Adding or setting attributes on the identity object does not persist data.
4 You must explicitly persist changes by calling the store method.

For more information about the idRepository binding, refer to Access profile data.

nodeState

Use the nodeState binding to get and set the shared state of the journey.

Learn more in Access shared state data.

  • Legacy

  • Next-generation

 // var username = sharedState.get("username");
                                             1
var username =
    nodeState.get("username").asString();    2
var attributes =                             3
    nodeState.get("objectAttributes").asMap();
var username = nodeState.get("username");    2
var attributes =
    nodeState.getObject("objectAttributes"); 3

1 Deprecated sharedState and transientState bindings are no longer available. Use nodeState.get() instead. To store state values, use nodeState.putShared() or nodeState.putTransient() instead of sharedState.put() and transientState.put().
2 No need to call methods such as asString() or asMap().
3 New getObject() method to retrieve a map with values stored across different states. The map is immutable.

To get the UUID from nodeState, precede the journey decision node with a Identity Store Decision node and enable the Username as Universal Identifier property. As a result, when you call nodeState.get('username') the function returns the user’s _id.