Orchestration SDKs

Navigating an authentication journey on Android

PingOne Advanced Identity Cloud PingAM Android


The start() method returns a Node instance, which represents where you are in the authentication journey.

There are four main types of Node instance a journey can return.

The four different types of node instances
Node type Description

ContinueNode

Indicates a step in the middle of the authentication journey.

Call node.next() to submit any collected data and advance to the next node.

ErrorNode

Represents a bad request, such as invalid credentials. For example a bad password or incorrect one-time passcode (OTP).

Access the error message using node.message.

FailureNode

Signifies an unexpected error during the authentication process, such as network connectivity issues.

Retrieve the underlying cause using node.cause.

SuccessNode

Indicates successful authentication.

Obtain the user session details using node.session.

Handle the different node types as follows:

Handling the different node types in a journey
var node = journey.start("sdkUsernamePasswordJourney")

// Determine the type of the current Node
when (node) {
    is ContinueNode -> {
        // Proceed to the next step in the authentication journey
        val nextNode = node.next()
    }
    is ErrorNode -> {
        // Handle server-side errors, such as invalid credentials
        val errorMessage = node.message
        node.input["name"] // Access the raw JSON response with the input attribute
        // Display error to the user
    }
    is FailureNode -> {
        // Handle unexpected errors, such as network issues, parsing response problems
        val errorCause = node.cause
        // Log the error and potentially display a generic message
    }
    is SuccessNode -> {
        // Authentication successful!
        // Retrieve the session
        val session = node.session
        node.input["name"] // Access the raw JSON response with the input attribute
        // Proceed with post-authentication actions
    }
}

Handling ContinueNode

The ContinueNode type often contains a list of callbacks that require input from the client.

You can access these using node.callbacks(), and provide the necessary information to each relevant callback:

Handling different callbacks
val node = journey.start() // Initiate the authentication flow

when (node) {
    is ContinueNode -> {
        node.callbacks.forEach { callback ->
            when (callback) {
                is NameCallback -> callback.name = "Your Username"
                is PasswordCallback -> callback.password = "Your Password"
                // Handle other callback types as they are introduced
            }
        }

        // Return the collected input and proceed to the next Node
        val nextNode = node.next()
    }
    is FailureNode -> {/* ... */}
    is ErrorNode -> {/* ... */}
    is SuccessNode -> {/* ... */}
}

Specific callback types provide their own properties for accessing labels and setting values:

Accessing callback prompts and setting input data
  • NameCallback

  • PasswordCallback

val prompt = (callback as? NameCallback)?.prompt // Access the prompt/label
(callback as? NameCallback)?.name = "Your Username" // Set the user’s input
val prompt = (callback as? PasswordCallback)?.prompt // Access the prompt/label
(callback as? PasswordCallback)?.password = "Your Password" // Set the user’s password

Learn about supported callbacks in Supported Nodes and Callbacks.

Handling FailureNode and ErrorNode

The Journey module distinguishes between the FailureNode and ErrorNode types for different categories of errors encountered during the authentication flow.

FailureNode

Indicates an unexpected issue that prevents the journey from continuing. This could stem from network problems or data parsing errors.

You can access the underlying Throwable that caused the error using node.cause() 1.

You should display a user-friendly generic error message and log the details for support investigation.

ErrorNode

Signifies an error response from the authentication server, typically an HTTP 4xx or 5xx status code.

These errors often relate to invalid user input or issues server-side.

You can retrieve the specific error message provided by the server using node.message() 2, and access the raw JSON response by using node.input 3.

Handling FailureNodes and ErrorNodes
val node = journey.start() // Initiate the authentication flow

when (node) {
    is ContinueNode -> {/* ... */}

    is FailureNode -> {
        // Retrieve the underlying error
        val errorCause = node.cause (1)

        // Log the errorCause for debugging
        // Display a generic error message to the user
    }

    is ErrorNode -> {
        // Retrieve the server-provided error message
        val errorMessage = node.message (2)
        // Access the raw JSON error response
        val rawResponse = node.input (3)

        // Display the specific error message to the user
    }

    is SuccessNode -> {/* ... */}
}

Handling SuccessNode

When the Journey module reaches the SuccessNode type it securely stores session tokens, and populates the user object.

Handling SuccessNode
val node = journey.start() // Initiate the authentication flow

when (node) {
    is ContinueNode -> {/* ... */}
    is FailureNode -> {/* ... */}
    is ErrorNode -> {/* ... */}

    is SuccessNode -> {
        // Checking the user object
        val user: User? = journey.user()
        // Retrieve the session token, if available
        val session: SSOToken? = user?.ssoToken()
    }
}