Authenticate
Confirm a user's identity for login or other secure actions.
Prerequisites
Complete the steps to create a Passage app and install the necessary SDKs.
Ways to authenticate
Confirm a user's identity for login or other secure actions. There are three ways to authenticate users:
- With an external identifier such as an email address, username, or phone number.
- Without an external identifier. All passkeys associated with the domain on the user's device are provided for authentication.
- With passkey autofill (web only). Requires the user to have a discoverable credential and a web browser that supports passkey autofll.
Authenticate with an external identifier
Users input an external identifier such as an email address, username, or phone number. Passage then authenticates them with the passkey associated with their external identifier.
Get transaction ID
Get a transaction ID from the Passage Backend for each user. Learn more about transactions.
Retrieve the user in your database, then call Passage with the user's external identifiers.
If the user doesn't exist, you'll need to register them first.
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) => {
// Using the identifier the user inputs, find the user in your database.
const user = User.find({ email: req.body.email });
// 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.
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.
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
Authenticate without an external identifier
Users do not provide an external identifier. All passkeys associated with that app on the user's device are provided for authentication.
Authenticate user
Initialize a Passkey Flex instance using your app ID found in Passage Console.
Passkey Flex triggers the WebAuthn (opens in a new tab) flow. Users are shown all app passkeys registered to the device on their screen.
import { PassageFlex } from 'passage-flex-js';
const passage = new PassageFlex(appID);
async function onLoginClick() {
const nonce = await passage.passkey.authenticate();
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.
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
Authenticate with passkey autofill (web only)
Also known as conditional mediation.
This requires users to have a discoverable credential and a web browser that supports passkey autofill.
Users select an identifier input field and the browser displays available passkeys in an autofill dropdown.
The order of the tokens in the autofill HTML attribute must be username
followed by webauthn
. Call on page load.
Set passkey autofill on page load
Request to authenticate with passkey autofill on page load to initiate WebAuthn ceremony.
async function onPageLoad() {
const nonce = await passage.passkey.authenticate({ isConditionalMediation: true });
}
Add WebAuthn autofill attribute to identifier input
Provide an input
for the autofill values to populate and give it an autocomplete="username webauthn"
attribute. A button for standard authentication with identifier isn't necessary but is recommended as a fallback if passkey autofill isn't available.
<input autocomplete="username webauthn" id="authenticate-input" type="email" placeholder="you@example.com" />
<button id="authenticate-button" type="button" onclick="onAuthenticatePasskeyClick()">Log in</button>
Note: The autocomplete
attribute supports multiple tokens, for passkey autofill to work webauthn
must be the last token listed.
Authenticate user
Initialize a Passkey Flex instance using your app ID found in Passage Console. Passkey Flex triggers the WebAuthn (opens in a new tab) flow. Users are provided all app passkeys registered to the device.
async function onLoginClick() {
const nonce = await passage.passkey.authenticate();
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 a Passkey Flex backend SDK.
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