Mobile PIN Authentication

Authenticates the user using the device's unlock PIN code

About client-facing steps

A journey is a sequence of steps that are executed when it's invoked by a client application (known as the "client"). Some steps require involvement from the client, such as to collect user input. Other steps, like validating a token, are executed in the backend by the Mosaic journey engine alone.

When invoked, the journey begins executing the steps while the client waits for further instructions. When a journey reaches a client-facing step, the journey asks the client for the required input and then waits for the client to respond. The client presents their own UI if user interaction is required, and returns input to the journey. The journey then proceeds in a similar manner until it's completed.

Description

This client-facing step is used to authenticate the user using the device's unlock PIN code. The PIN must first be registered using the Register Mobile PIN step.

Once triggered, this step instructs the client to authenticate the user by prompting for the device's unlock PIN. The client uses the Authentication SDK to perform the authentication and sign a challenge provided by the journey. The client then submits the authentication result to the journey using the Orchestration SDK.

If successful, the journey sets the user context to the authenticated user and continues to the next step. User tokens generated upon authentication can be accessed in subsequent steps using @policy.userContext(). If the step fails or is cancelled, the journey either aborts or continues to a failure or cancel branch if configured.

To support mobile PIN authentication, you'll need to:

  • Implement PIN registration as described in Register Mobile PIN
  • Implement the Authentication SDK call required for authentication (see Example )
  • Implement the Orchestration SDK call that submits the authentication result (see Android reference or iOS reference )
  • Configure the Mobile PIN Authentication journey step
Note
For Android, the Authentication SDK requires `compileSdk` 34 (or greater) and `minSdk` 23.

Configuration

Field Description
User identifier source Specifies the source of the user identifier. The username can either be provided by the client upon authentication (default) or provided by the journey (after resolving the configured source expression).
External user identifier User identifier, specified as an expression. Must be configured only if the journey is configured as the username source.
Error Output Variable Name of the variable that stores any errors returned by action
Failure Behavior Determines the behavior in case of failure, which either aborts the journey or proceeds to a failure branch of the control flow (default).
Custom Branches Additional journey branches supported for this step. The client can select a branch by returning the branch ID. For each branch, you can define a schema for the information that the client is expected to return (used by the code generator and for autocompleting journey expressions) and a display name to label it in the editor.
Branch Output Variable Name of the variable used to store the data returned by the client, which can be used in subsequent journey steps.
Cancel Behavior Determines the behavior of client cancellation, which either aborts the journey (default) or proceeds to a cancel branch of the control flow

Example

When executed, this step sends a callback to the client with the IDO service response object. It includes a challenge to be signed using the registered PIN credentials. The client prompts the user to enter their device PIN, performs the signing operation using the Authentication SDK, and submits the signed result back to the journey.

SwiftKotlin
Copy
Copied
// Authentication challenge provided by the journey
let challenge = serverResponse?.data["pin_challenge"] as? String ?? ""

// Authenticates the user with their device PIN using the Authentication SDK
TSAuthentication.shared.authenticatePinCode(username: "[USER_ID]", challenge: challenge) { result in
    switch result {
    case .success(let response):
        let data: [String: Any] = [
            "publicKeyId": response.publicKeyId,
            "signedChallenge": response.signature,
            "userIdentifier": "[USER_ID]"
        ]
        // Submits the authentication result to the journey
        TSIdo.submitClientResponse(clientResponseOptionId: .clientInput, data: data)
    case .failure(let error):
        debugPrint("[DEBUG] Error: \(error)")
        TSIdo.submitClientResponse(clientResponseOptionId: .fail)
    }
}
Copy
Copied
TSAuthentication.authenticatePinCode(userId, pinCode, challenge, object: TSAuthCallback<TSPinCodeAuthenticationResult, TSPinCodeAuthenticationError> {
    override fun success(authenticationResult: TSPinCodeAuthenticationResult) {
        // Get public key identifier
        val publicKeyId = authenticationResult.keyId()
        // Get original challenge
        val challenge = authenticationResult.challenge()
        // Get signed challenge
        val signature = authenticationResult.signature()
    }

    override fun error(error: TSPinCodeAuthenticationError) {
        //handle error
    }
})