ForgeRock SDKs

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:

  1. Create a script to generate a metadata callback.

  2. Update your journey/tree to execute the script.

  3. 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:

Example of the decision node script
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)

Include the scripted decision node in the page 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:

Stage property in AM 7

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
}
Copyright © 2010-2022 ForgeRock, all rights reserved.