Multi-factor authentication

Use passkeys in addition to other forms of authentication to add an additional layer of security.

Get started by choosing your client and backend for personalized docs.
Select client
Select backend

Prerequisites

Complete the steps to create a Passage app and install the necessary SDKs.

Multi-factor registration

Register a second form of authentication for users. This can be done during registration or elsewhere in the app. You can make multi-factor authentication optional or required for users.

Passage recommends the industry standard of requiring users to set up at least two forms of authentication.

Get transaction ID

Get a transaction ID from the Passkey Flex Backend for each user. Learn more about transactions.

Create or retrieve the user in your database, then call Passkey Flex with the user's external identifiers. You must create a unique external ID to associate with the user in your database and the Passage database.

Backend
 
app.post('/passkey/register', async (req: Request, res: Response) => {
 
    // Create or retrieve the user in your database
    const user = await User.create({
        email: req.body.email,
        passageExternalId: "random-UIUD" // Save a unique passage identifier to each user.
    });
 
    const transactionID = await passage.createRegisterTransaction({
        externalId: user.passageExternalId, // Same passage identifier saved to your DB
        passkeyDisplayName: user.email,
    });
});

Learn more about the Node.js Flex SDK

Register passkey

Initialize a Passkey Flex instance using your app ID found in the Passage console.

Register the user using the transaction ID you retrieved in step 2.

Client
import { PassageFlex } from '@passageidentity/passage-flex-js';
 
const passage = new PassageFlex(appID);
 
function async onCreatePasskeyClick() {
    // Make a request to the server
 
    const transactionID = // Result of request to example '/passkey/register' endpoint
 
    // Register the new passkey to the user
    const nonce = await passage.passkey.register(transactionID);
}

Learn more about the JavaScript Flex SDK

Passkey Flex triggers the WebAuthn (opens in a new tab) flow and the passkey is created on the user's device.

Validate the user

The Passkey Flex JavaScript library returns a nonce to your frontend. You can use the nonce to verify that Passage has registered the user successfully. Learn more about nonces.

Once verified you can then safely generate a token compatible with your system.

Backend
app.post('/user/verify', async (req: Request, res: Response) => {
    const { nonce } = req.body;
    try {
        const externalId = await passage.verifyNonce(nonce);
 
        res.json({
            auth_token: 'auth_token_or_other_auth_solution',
        });
    } catch (err) {
        res.status(response.status).json({ error: 'Error' });
    }
}); 

Learn more about the Node.js Flex SDK

Multi-factor authentication

Authenticate a user with a second form of verification during login. This can be required for all users or an option for users who have multiple authentication methods.

Get transaction ID

Get a transaction ID from the Passage Backend for each user. Learn more about transactions.

Upon succesfully authenticating a user with the first form of authentication, call Passage with the user's external identifier.

Backend
import { PassageFlex } from '@passageidentity/passage-flex-node';
 
const passage = new PassageFlex({
    appId: process.env.PASSAGE_APP_ID,
    apiKey: process.env.PASSAGE_API_KEY,
});
 
app.post('/user/authenticate-with-passkey', async (req: Request, res: Response) => {
 
    const user = // User authenticated with first form of authentication
 
    // Use the user's identifier to retrieve a transaction ID.
    // Can be any external identifier.
    const transactionID = await passage.createAuthenticateTransaction({
        externalId: "UUID-string"
    });
 
    return transactionID;
});

Learn more about the Node.js Flex SDK

Authenticate user

The WebAuthn (opens in a new tab) flow needs to be triggered from the client to authenticate the passkey on the user's device.

Initialize a Passage instance using your app ID found in Passage Console. Authenticate the user using the transaction ID you retrieved in step 2.

Client
import { PassageFlex } from 'passage-flex-js';
 
const passage = new PassageFlex(appID);
 
async function onLoginClick() {
    const transactionId = // Result of request to example '/user/authenticate-with-passkey' endpoint with `identifier`
    const nonce = await passage.passkey.authenticate(transactionID);
 
    const authResult = // Result of request to example '/user/verify` endpoint with `nonce`
}

Learn more about the JavaScript Flex SDK

Verify nonce & return auth identifier

From your server, verify the nonce with the Passkey Flex backend SDK.

Backend
app.post('/user/verify', async (req: Request, res: Response) => {
    const { nonce } = req.body;
    try {
        const externalId = await passage.verifyNonce(nonce);
 
        res.json({
            auth_token: 'auth_token_or_other_auth_solution',
        });
    } catch (err) {
        res.status(response.status).json({ error: 'Error' });
    }
});

Learn more about the Node.js Flex SDK

Learn more