Login with PIN
PIN authentication lets users authenticate using a PIN code defined on their device. This PIN unlocks a locally stored encrypted seed, from which a secure key pair is derived on demand. The private key is used to sign authentication challenges, while the PIN and private key never leave the device. This ensures a user-friendly yet secure experience based on strong cryptography. For more about the PIN authenticator's settings for behavior and lockout policies, see our Manage authenticators page.
Note
This guide explains how to implement authentication with PIN codes using Journeys and mobile Orchestration SDKs. To learn more about SDKs integration, see Orchestration quickstart (Android) and Orchestration quickstart (iOS).
How it works
Mobile PIN authentication is based on asymmetric cryptography. When the user registers a PIN, the Authentication SDK generates a random secret seed, which is encrypted using the PIN and securely stored on the device. The PIN itself is never stored, and the private key is never persisted — it only exists in memory when needed.
PIN registration
During registration, the Orchestration SDK receives a registerPinCode
step from Mosaic and exposes it to the app. The app prompts the user to enter a PIN and then calls the Authentication SDK, which encrypts the seed and derives a public/private key pair. The public key and its identifier are returned to the app, which submits them to Mosaic via the Orchestration SDK.
Mosaic then returns a PinCodeRegistrationCommit
instruction to finalize the process. The Orchestration SDK exposes this instruction to the app, which must call commitPinCodeRegistration()
using the Authentication SDK. This marks the key as ready for use in authentication.
PIN authentication
During authentication, the Orchestration SDK receives a authenticatePinCode
step from Mosaic and exposes it to the app. The app collects the user's PIN and invokes the Authentication SDK, which decrypts the seed, derives the key pair on demand, and signs a challenge received from Mosaic. The signed result is sent back through the Orchestration SDK to Mosaic, where it is verified using the public key.
Requirements
iOS
iOS
- iOS 13+
- Xcode 11+
Android
Android
- Android 5+ (API level 21+)
Before you start
Before you start, make sure you have a Mosaic application with an OIDC client. See create an application.
For a user to register a PIN, they must already exist in your app and verify their identity before registration. This authentication can be performed using any supported method (e.g., password, OTP, document verification), either within the same journey or in a prior one.
Step 1: Configure PIN authenticator
Mobile PIN authentication lets users log in to their app using a PIN code that they choose specifically for the app. The PIN format and complexity (e.g., 4 or 6 digits) are defined by your application and must be enforced in the frontend.
The PIN authentication settings (Admin Portal > B2C Identity or B2B Identity > Authentication methods ) allow you to configure the lockout policy in case of repeated failed attempts:
- Failed attempts : set the number of incorrect PIN entries allowed before triggering a lockout.
- Lockout duration : define how long the user must wait before they can try again.
Tip
Once you've configured the lockout policy, you may also implement logic to unlock the PIN authenticator in case it locks. Use the Unlock authenticators API to reset a locked PIN code.
For more about the PIN authenticator, see Customize login methods.
Step 2: Create journeys
In the Admin Portal, go to B2C Identity or B2B Identity based on your setup, and open the Journeys section. Create two separate journeys—one for PIN registration and one for PIN authentication. You can name them as you like, for example register-pin-journey
, login-with-pin-journey
.
PIN registration journey
After adding the following steps to your journey:
Configure them as follows:
Login form
Configure this step to display a form that collects a password. Basic configuration for our example includes:
- Authentication methods : Enable only Password .
-
Step ID
: Provide a unique identifier, e.g.,
loginForm
. This is used by the client to recognize the step. -
Branch output variable
: Set to
loginData
. This is the variable that stores the user input and passes it to the next step.
Authenticate with password
Configure this step to validate the user credentials collected in the previous step. Basic configuration for our example includes:
-
External user ID
: Set to
loginData.username
. This maps the value submitted via the login form. -
Password
: Set to
loginData.password
. This retrieves the password submitted by the user.
Register Mobile PIN
This step binds the PIN credential to the device. Basic configuration for our example includes:
-
User Auth State
: Leave set to
The user is authenticated
. -
Branch Output Variable
: Set to
pinRegistrationData
or similar. This stores the result returned by the client (e.g., public key info).
PIN authentication journey
After adding the following steps:
Configure them as follows:
Login form
Configure this step to display a form that collects a PIN code. Basic configuration for our example includes:
- Authentication methods : Enable only Mobile PIN .
-
Step ID
: Provide a unique identifier, e.g.,
loginForm
. -
Branch output variable
: Set to
loginData
. This variable will hold the PIN input sent by the client.
Note
You can extend this journey later by enabling additional authentication methods (e.g., password or OTP) to support fallback scenarios.
Authenticate with Mobile PIN
This step verifies the user using the registered PIN. Basic configuration for our example includes:
-
User identifier source
: Set to
Provided by the client
. -
Branch output variable
: Set to
pinAuthData
or similar. This variable will contain the signed result submitted by the client.
Step 3: Add mobile SDKs
To run this flow, your integration needs the Orchestration SDK (for iOS and Android) and Authentication SDK (for iOS and Android) to enable your application to use mobile biometrics and invoke journeys.
Important
Make sure to initialize mobile SDKs within the context of the same client ID.
For Android, see instructions here:
- Adding to project: Orchestration SDK and Authentication SDK
- Initializing: Orchestration SDK and Authentication SDK
For iOS, see instructions here:
- Loading: Orchestration SDK and Authentication SDK
- Initializing: Orchestration SDK and Authentication SDK
Step 4: Start the journey
You must start the appropriate journey from your mobile app depending on the context, using the journey IDs you defined earlier step 2.
Launch PIN registration journey
To let a user set up their PIN for the first time, launch the registration journey you created (e.g., after successful authentication):
// Start the journey to register a PIN
TSIdo.startJourney(journeyId: "register-pin-journey")
// Start the journey to register a PIN
TSIdo.startJourney(
"register-pin-journey", // Replace with your journey ID
TSIdoStartJourneyOptions(additionalParams, flowId),
idoCallback
)
Once the journey starts, the client receives a TSIdoServiceResponse
containing the input required for the step—such as the PIN challenge and user identifier. After submitting the result using submitClientResponse
, the journey may return a backend instruction (e.g., PinCodeRegistrationCommit
) that must be handled to complete the operation. Make sure your implementation is prepared to handle this instruction by committing the registration result using the SDK.
Launch PIN authentication journey
To authenticate the user using their PIN, launch the authentication journey:
// Start the journey to authenticate with PIN
TSIdo.startJourney(journeyId: "login-with-pin-journey")
// Start the journey to authenticate with PIN
TSIdo.startJourney(
"login-with-pin-journey", // Replace with your journey ID
TSIdoStartJourneyOptions(additionalParams, flowId),
idoCallback
)
Once the journey starts, the client receives a TSIdoServiceResponse
containing the input required for the step—such as the PIN challenge and user identifier. After generating the signed result using the Authentication SDK, submit it back using submitClientResponse
. No additional backend instruction is expected in this case.
Note
In Android, the idoCallback
object must implement the TSIdoCallback
interface to receive the journey result.