Determine the authentication stage
The ForgeRock SDKs greatly simplify adding Intelligent Authentication to your applications. They offer ready-to-use UI that completely handles rendering of authentication steps.
You can also take full control and create a custom UI, in which case it’s helpful to know the current stage of the authentication journey/tree to determine which UI you should render.
For recent versions of Intelligent Authentication, skip to Identity Cloud and AM 7. |
This article explains how to determine the current stage of an authentication tree in AM 6.5.2 and later, using two different approaches:
Approach #1: Inspect callbacks
If you have relatively few, or well-known authentication trees, you can determine the stage by checking the callbacks present in the step.
For example, it is common for an authentication tree to start by capturing a username and password, within a page node. In this case, you can inspect the callbacks to see if they consist of both a NameCallback and a PasswordCallback, and if so, render the appropriate custom UI.
ForgeRock JavaScript SDK
function getStage(step) {
// Check if the step contains callbacks for capturing username and password
const usernameCallbacks = step.getCallbacksOfType('NameCallback');
const passwordCallbacks = step.getCallbacksOfType('PasswordCallback');
if (usernameCallbacks.length > 0 && passwordCallbacks.length > 0) {
return "UsernamePassword";
}
// Use the SDK to determine if this is a WebAuthn step
const webAuthnStepType = FRWebAuthn.getWebAuthnStepType(step);
if (webAuthnStepType === 'Authentication') {
return "DeviceAuthentication";
} else if (webAuthnStepType === 'Registration') {
return "DeviceRegistration";
}
// ... Add checks to determine other stages in your trees ...
return undefined;
}
ForgeRock iOS SDK
import Foundation
import FRAuth
extension Node {
// Parse set of Callbacks in Node object, and return stage value
func getStage() -> String? {
// Check if the Node contains callbacks for capturing username and password
if self.callbacks.contains(where: { $0 is NameCallback}) &&
self.callbacks.contains(where: { $0 is PasswordCallback})
{
return "UsernamePassword"
}
// Add checks to determine other stages in your trees
else if self.callbacks.contains(where: { $0 is ChoiceCallback }) {
return "ChoiceCallback"
}
return ""
}
}
Approach #2: Add metadata callbacks
Using metadata callbacks, you can inject a stage value into the tree’s response payload.
This approach involves the following steps:
-
Create a script to generate a metadata callback.
-
Update your journey/tree to execute the script.
-
Using the SDK, read the metadata callback.
Step 1: Create a script to generate a metadata callback
In AM, create a "Decision node script for authentication trees" (AUTHENTICATION_TREE_DECISION_NODE
) script.
Give it an appropriate name, such as "MetadataCallback: UsernamePassword".
In the script, add a metadata callback that creates an object with a stage
property.
Be sure to also set the outcome
value:
var fr = JavaImporter(
org.forgerock.json.JsonValue,
org.forgerock.openam.auth.node.api.Action,
com.sun.identity.authentication.spi.MetadataCallback
);
with (fr) {
var json = JsonValue.json({ stage: "UsernamePassword" });
action = Action.send(new MetadataCallback(json)).build();
}
outcome = "true";
The result will resemble the following:

As with all scripts, ensure you allow any imported classes. |
Step 2: Update your tree to execute the script
In the authentication tree in AM, add a "Scripted Decision Node" to your "Page Node", and configure it to reference the script created in the previous step.
In this example, the step payload will contain three callbacks:
-
MetadataCallback
(Scripted Decision node) -
NameCallback
(Username Collector node) -
PasswordCallback
(Password Collector node)

Step 3: Use the SDK to read the metadata callback
Ensure your application can find the metadata callback, read its stage property, and render the appropriate UI.
Note that the ForgeRock Android and iOS SDKs automatically parse the MetadataCallback
, if present,
and extract the stage
property into the Node
object.
The following example obtains the stage property from the MetadataCallback
callback,
using the ForgeRock JavaScript SDk:
function getStage(step) {
// Get all metadata callbacks in the step
const metadataCallbacks = step.getCallbacksOfType('MetadataCallback');
// Find the first callback that contains a "stage" value in its data
const stage = metadataCallbacks.find((callback) => {
const data = callback.getData();
return !!(data && data.stage);
});
// Return the stage value, which will be undefined if none exists
return stage;
}
Identity Cloud and AM 7
In Identity Cloud and AM 7 and later, specifying the stage is straightforward. When constructing a tree, place nodes inside a page node, and then specify its stage, which is a free-form text field:

The SDKs have native support for the stage value in AM 7.
For example, in the ForgeRock JavaScript SDK, use the SDK’s FRAuth
module to iterate through a tree,
and then call the getStage()
method on the returned FRStep
to decide what custom UI needs to be rendered:
// Get the current step in the tree
const currentStep = await FRAuth.next(previousStep);
// Use the stage value configured in the tree
switch (currentStep.getStage()) {
case "UsernamePassword":
// Render your custom username/password UI
break;
case "SomeOtherStage":
// etc
break;
}
In the ForgeRock iOS SDK, simply do the following:
switch node.stage {
case "UsernamePassword":
// Render your custom username/password UI
break
case "SecondFactor":
// Render your custom second factor UI
break
default:
break
}