Add WebAuthn cross-device login (Older SDK)

You can build WebAuthn-based login flows that involve multiple devices using our Web SDK for WebAuthn. This lets you provide a secure passwordless experience across all channels and devices. For example, suppose a user wants to log in to your website from a desktop device that doesn't support WebAuthn or doesn't belong to them. So the desktop presents a QR code that the user scans using their mobile device to initiate an authentication process in their mobile browser instead.

Note

This guide describes integrating using the older WebAuthn SDK. The new Platform SDK offers all the same functionality and more. While the older SDK is still supported for existing integrations, new features will only be supported by the Platform SDK.

Sample flows

Here are samples of some flows that implement WebAuthn biometric login using our Web SDK for WebAuthn. These are simplified representations to help you get to know Transmit Security APIs in context. There are many different ways to implement this and this is just an example.

Cross-device registration

This flow represents a cross-device login scenario where the user wants to log in for one device, but authenticates using another. For example, the user can log in from a desktop device and use a mobile device to authenticate. In this case, the authenticating device isn't yet registered for this user so a WebAuthn registration is performed. Transmit APIs are shown in pink along with the relevant integration steps.

Note

This flow assumes that you've collected and verified the username before initiating registration. The username should be a representation of the user in your system, such as their email, phone number, or another verifiable username known to the user (like account ID).

The cross-device registration flow consists of the following parts:

  1. Initiate cross-device flow
  2. Register credentials
  3. Get user tokens

1. Initiate cross-device flow

After initializing the Web SDK, the client initiates a cross-device flow to create a session context and register relevant event handlers to respond to events occurring on the auth device. The access device delegates authentication to the auth device (e.g., by displaying a QR code that encodes the session ID). Once the auth device is invoked (e.g., by scanning the QR), the SDK is initialized. If the device isn't registered, the client validates that the device supports WebAuthn and then attaches the device to the session. The access device is notified that the device is attached (if this event handler was registered).

2. Register credentials

The auth device authorizes the current session to establish a secure context for registration. To improve the UX, the SDK prepares for registration by fetching the challenge from the Transmit Server and storing it locally. Once the user is ready to register their device, the SDK tells the browser to create credentials, which may require the user to verify (e.g., via TouchID). Once completed, an authorization code is returned to the client. The access device receives the authorization code (if the relevant event handler was registered).

3. Get user tokens

Your client backend exchanges the auth code for ID and access tokens. Once tokens are validated, the user's device is registered and they're logged in. This part is the same for single-device flows, as well as cross-device authentication.

Cross-device authentication

This flow represents a cross-device login scenario where the user wants to log in to one device, but authenticates using another. For example, the user can log in from a desktop device and use a mobile device to authenticate. In this case, the authenticating device was previously registered for this user so a WebAuthn authentication is performed. Transmit APIs are shown in pink along with the relevant integration steps.

Note

This flow assumes that you know the username before initiating authentication. The username should be a representation of the user in your system, such as their email, phone number, or another verifiable username known to the user (like account ID). It must be the same username that was used during registration.

The cross-device authentication flow consists of the following parts:

  1. Initiate cross-device flow
  2. Authenticate
  3. Get user tokens

1. Initiate cross-device flow

After initializing the SDK, the client initiates a cross-device flow to create a session context and register relevant event handlers to respond to events occurring on the auth device. The access device delegates authentication to the auth device (e.g., by displayed a QR code that encodes the session ID). Once the auth device is invoked (e.g., by scanning the QR), the SDK is initialized. If the device isn't registered, the client validates that the device supports WebAuthn and then attaches the device to the session. The access device is notified that the device is attached (if this event handler was registered).

2. Authenticate

Unlike registration, the flow does not require any backend call, only SDK operation. To improve the UX, the SDK prepares for authentication by fetching the challenge from the Transmit Server and storing it locally. Once the user is ready to authenticate, the SDK tells the browser to prompt for credentials, which will require the user to verify (e.g., via TouchID). Once completed, an authorization code is returned to the client. The access device receives the authorization code (if the relevant event handler was registered).

3. Get user tokens

Your client backend exchanges the auth code for ID and access tokens. Once tokens are validated, the user's device is authenticated and they're logged in. This part is the same for single-device flows, as well as cross-device registration.

Before you start

Set up basic WebAuthn registration and authentication using the WebAuthn Quick Start. It covers the basic setup needed for any flow, and you can test the basic flows before adding new integration scenarios like cross-device login.

Step 1: Set up access device

In a cross-device login flow, the access device is the device that initiates the flow and will eventually log in to your app (pending a successful WebAuthn authentication or registration using a secondary device - known as the auth device).

To set up cross-device login for the access device:

  1. Initialize the WebAuthn SDK
  2. Start the cross-device flow

1. Initialize the WebAuthn SDK

You can obtain the Web SDK for WebAuthn directly from your Transmit representation.

Configure the SDK on the page that initiates the cross-device flow, such as your login or registration page. To do this, call the init() SDK method, passing your client ID (from your application settings in the Admin Portal). For example:

Copy
Copied
await window.WebAuthnSdk.init('CLIENT_ID', {serverPath: "https://api.transmitsecurity.io/cis"});

2. Start the cross-device flow

Initiate the flow on the access device before allowing the user to proceed to the auth device. This will:

  • Create a new session, which provides context for the flow. You'll need to provide the session ID to the auth device (e.g., by encoding it in a QR code to display on the desktop). The auth device will need it in order to attach to the session in Step 2 , and to authorize the session in Step 3 before starting a registration process.

  • Register event handlers that will be called by the SDK when the event occurs on the auth device. For example, the onDeviceAttach handler allows the desktop to display a spinner once the QR code is scanned by the mobile device (after it attaches to the session). Make sure to register the onCredentialRegister and onCredentialAuthenticate handlers, which receive the authorization code to exchange for user tokens in Step 5 .

To start the flow, call the startCrossDeviceFlow() SDK method, passing the event handlers you want to register:

Copy
Copied
// Triggered when the auth device calls attach()
async function onDeviceAttach() {
	//Show a spinner in the UI
	return true; // Return true to keep polling
}

// Triggered at the end of the registration process on the auth device
async function onCredentialRegister(authCode) {
	return await completeSession(authCode);
}

// Triggered at the end of the authentication process on the auth device
async function onCredentialAuthenticate(authCode) {
	return await completeSession(authCode);
}

// Triggered on failure
async function onFailure(error) {
	// Log the error and display a message to the user / navigate to an error page.
}

async function completeSession(code: string) {
	// Get user tokens using the received code as described below
	return false;
}

// Initiate the cross device flow and provide the handlers.
const controller = await window.WebAuthnSdk.startCrossDeviceFlow({
	onDeviceAttach,
	onCredentialRegister,
	onCredentialAuthenticate,
	onFailure,
});

// Construct the URL of your login page along with the authSessionId param (aid in this example).
// It is best to display the generated URL using a QR code.
const url = `<YOUR_APP_LOGIN_PAGE_URL>?aid=${controller.authSessionId}`;

Step 2: Set up auth device

In cross-device login flows, the auth device is the device used to authenticate (or register credentials) in order to allow the access device to log in to the app.

To set up cross-device login for the auth device:

  1. Initialize the WebAuthn SDK
  2. Check that the device supports WebAuthn
  3. Attach the auth device to the session

1. Initialize the WebAuthn SDK

Configure the SDK on the page that will continue the cross-device flow on the auth device, such as the page that the mobile browser will navigate to when the QR code is scanned by the mobile device. To do this, add code to the page that calls the init() SDK method, passing the same client ID used in Step 1. For example:

Copy
Copied
await window.WebAuthnSdk.init('CLIENT_ID', {serverPath: "https://api.transmitsecurity.io/cis"});

2. Check for WebAuthn support

Before attaching the auth device to the session, use the isPlatformAuthenticatorSupported() SDK call to check if the device supports WebAuthn.

Copy
Copied
const isBiometricsSupported = await window.WebAuthnSdk.isPlatformAuthenticatorSupported();

3. Attach the auth device to the session

To add the auth device to the cross-device flow initiated by the access device, the auth device needs to attach to the session. This corresponds to the session ID that you passed to the auth device when delegating authentication (e.g., by encoding it in the QR code). The device must be attached before initiating the registration or authentication processes described in the subsequent steps.

Attach the auth device to the session using the attachDevice() SDK call. Once attached, the onDeviceAttach handler will be called if it was registered in Step 1.2.

Copy
Copied
await window.WebAuthnSdk.attachDevice(authSessionId);

Step 3: Register credentials

Register WebAuthn credentials from the auth device as described in the WebAuthn Quick Start for a single device flow, with the following exceptions:

  • Checking for WebAuthn support should be done before attaching a device to a session in a cross-device flow
  • In a single device flow, the session is authorized when created in the backend. In a cross-device flow, sessions are created implicitly by the SDK when the cross-device flow is started to provide the required context and then authorized explicitly before WebAuthn registration.

From your backend, authorize the existing session for the user in order to provide the secure context required for WebAuthn registration. To do this, send the /auth-session/authorize request below from your client backend.

In the request below, you should replace the following:

  • AUTH_SESSION_ID is the ID of the session
  • USERNAME is a verified username, which should be a representation of the user in your system (such as their email, phone number, or another verifiable username known to the user like account ID).
  • TOKEN is either a client access token or a user access token depending on your login scenario . To quickly test a basic WebAuthn integration (without implementing any additional login methods or the full logic required for your use case), make sure public sign-up is enabled for your application and use a client access token .
Copy
Copied
const basePath = 'v1';
const resp = await fetch(
  `https://api.transmitsecurity.io/cis/${basePath}/auth-session/authorize`,
  {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      Authorization: 'Bearer TOKEN'  // Type of token depends on the use case, as explained above
    },
    body: JSON.stringify({
      username: 'USERNAME',
      auth_session_id: 'AUTH_SESSION_ID'
    })
  }
);

const data = await resp.json();
console.log(data);

Step 4: Authenticate user

Authenticate the user from the auth device as described in the Web quick start for a single-device flow.

Step 5: Get user tokens

Upon successful WebAuthn registration or authentication, an authorization code is returned to the auth device. If the onCredentialAuthenticate and onCredentialRegister handlers were registered in Step 1.2, the access device will receive the authorization code. Exchange this code for ID and access tokens in the backend, as described in the Web quick start for a single device flow.

Next steps

Once you've tested your WebAuthn integration, you can complete your implementation. See Implement login scenarios for additional logic, like how to verify user identities before registering credentials.