Enrollment
Add passkey authentication to your existing auth system. Users can enroll passkeys while already logged in, then use those passkeys for future logins.
How It Works
Enrollment lets you bridge your existing authentication system with PasskeyBase. The flow works in two parts:
- Server-side: Your backend creates an enrollment token via the Management API, linking your existing user ID.
- Client-side: The SDK opens a popup where the user creates a passkey. No redirect -- the user stays on your page.
Step 1: Create an Enrollment Token (Server)
From your backend, call the PasskeyBase Management API to create a one-time enrollment token. You must provide your user's existing ID as the external_id. This links the PasskeyBase identity to your user.
Security: Always create enrollment tokens on your server. Never expose your Management API key to the frontend.
// Server-side: Create an enrollment token
// POST https://myapp.auth.ing/api/v1/enrollment-tokens
const response = await fetch('https://myapp.auth.ing/api/v1/enrollment-tokens', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer YOUR_MANAGEMENT_API_KEY',
},
body: JSON.stringify({
external_id: 'user_123', // Your existing user ID
display_name: 'Jane Doe', // Optional display name
expires_in: 3600, // Token TTL in seconds (default: 1 hour)
}),
});
const { token } = await response.json();
// token: "enroll_tok_abc123..."
// Return this token to your frontendStep 2: Enroll Passkey (Frontend)
Pass the enrollment token to the SDK's enrollPasskey()method. It opens a popup window where the user creates a passkey.
// Frontend: Enroll a passkey for the logged-in user
import { PasskeyBase } from '@passkeybase/js';
const pb = new PasskeyBase({
clientId: 'pk_live_abc123',
domain: 'myapp.auth.ing',
});
// Get the enrollment token from your backend
const response = await fetch('/api/enrollment-token', {
method: 'POST',
headers: { 'Authorization': 'Bearer ' + sessionToken },
});
const { token } = await response.json();
// Open the enrollment popup
try {
await pb.enrollPasskey(token);
console.log('Passkey enrolled successfully!');
showSuccessMessage('You can now log in with your passkey.');
} catch (err) {
if (err.message === 'popup_closed') {
console.log('User closed the enrollment popup');
} else {
console.error('Enrollment failed:', err);
}
}Full Example: Express.js Backend
Here is a complete example of creating an enrollment endpoint in an Express.js app:
// Express.js example
const express = require('express');
const app = express();
app.post('/api/enrollment-token', requireAuth, async (req, res) => {
const user = req.user; // From your existing auth middleware
const response = await fetch(
'https://myapp.auth.ing/api/v1/enrollment-tokens',
{
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${process.env.PASSKEYBASE_API_KEY}`,
},
body: JSON.stringify({
external_id: user.id,
display_name: user.name,
}),
}
);
const data = await response.json();
res.json({ token: data.token });
});After Enrollment
Once a user has enrolled a passkey, they can authenticate using the standard OAuth flow (via loginWithRedirect()). The ID token will include the external_idyou provided during enrollment, so you can map the PasskeyBase identity back to your existing user.
Multiple Passkeys
Users can enroll multiple passkeys (e.g., one on their phone, one on their laptop). Each enrollment creates a separate credential linked to the same user.
Token Expiry
Enrollment tokens are single-use and expire after the configured TTL (default: 1 hour). Generate a new token each time a user initiates enrollment.
Popup Blocked?
Ensure enrollPasskey() is called in response to a user gesture (e.g., button click). Browsers block popups that are not triggered by user interaction.