Passkeys & WebAuthn

The Web Authentication API (WebAuthn) is a specification that allows web applications on supported browsers to authenticate a user via authenticator types such as built-in device biometrics (e.g. facial recognition on mobile and fingerprint readers on desktop) or secure hardware keys (e.g. YubiKeys). While WebAuthn has many benefits, developers need to understand the API to implement it securely. Stytch's WebAuthn product simplifies the process by abstracting the implementation details of WebAuthn for developers to make it as quick as possible to implement securely.

Methods

The Stytch SDK can be used to create new WebAuthn registrations for users and authenticate existing WebAuthn registrations.

To call these methods, WebAuthn must be enabled in the SDK Configuration page of the Stytch dashboard.

Register

Wraps Stytch's register_start and register WebAuthn endpoints and the navigator.credentials web API. Call this method to prompt the user to enroll a new WebAuthn factor and save the factor in Stytch.

Call webauthn.register inside an event callback triggered by a user gesture.

You can listen for successful user updates anywhere in the codebase with the stytch.user.onChange() method or useStytchUser() hook if you are using React.

Note: If a user has enrolled another MFA method, this method will require MFA. See the Multi-factor authentication section for more details.


Method parameters


domainstring

authenticator_typestring

is_passkeyboolean

session_duration_minutesint
import React, { useCallback, useEffect, useState } from 'react';
import { useStytch } from '@stytch/stytch-react';

export const Login = () => {
  const stytchClient = useStytch();

  const trigger = useCallback(() => {
    stytchClient.webauthn.register();
  }, [stytchClient]);

  return <button onClick={trigger}>Create WebAuthn Registration</button>;
};

RESPONSE

200
{
    "status_code": 200,
    "request_id": "request-id-test-b05c992f-ebdc-489d-a754-c7e70ba13141",
    "user_id": "user-test-16d9ba61-97a1-4ba4-9720-b03761dc50c6",
    "webauthn_registration_id": "webauthn-registration-test-5c44cc6a-8af7-48d6-8da7-ea821342f5a6"
  }

Authenticate

Wraps Stytch's authenticate_start and authenticate WebAuthn endpoints and the navigator.credentials web API. Call this method to prompt the user to enroll a new WebAuthn factor and save the factor in Stytch.

Call webauthn.authenticate inside an event callback triggered by a user gesture.

You can listen for successful user updates anywhere in the codebase with the stytch.user.onChange() method or useStytchUser() hook if you are using React.


Method parameters


domainstring

is_passkeyboolean

session_duration_minutesint

signalobject

conditional_mediationboolean
import React, { useCallback, useEffect, useState } from 'react';
import { useStytch } from '@stytch/stytch-react';

export const Login = () => {
  const stytchClient = useStytch();

  const trigger = useCallback(() => {
    stytchClient.webauthn.authenticate({
      session_duration_minutes: 60,
    });
  }, [stytchClient]);

  return <button onClick={trigger}>Authenticate WebAuthn Registration</button>;
};

RESPONSE

200
{
    "status_code": 200,
    "request_id": "request-id-test-b05c992f-ebdc-489d-a754-c7e70ba13141",
    "session": null
    "session_jwt": "",
    "session_token": "",
    "user": {...},
    "user_id": "user-test-16d9ba61-97a1-4ba4-9720-b03761dc50c6",
    "webauthn_registration_id": "webauthn-registration-test-5c44cc6a-8af7-48d6-8da7-ea821342f5a6",
  }

Update

Allows a WebAuthn registration to be updated with a different name.


Method parameters


webauthn_registration_id*string

name*string
const STYTCH_PUBLIC_TOKEN = 'PUBLIC_TOKEN';
const stytch = Stytch(STYTCH_PUBLIC_TOKEN);

stytch.webauthn.update({
    webauthn_registration_id: 'webauthn-registration-test-5c44cc6a-8af7-48d6-8da7-ea821342f5a6',
    name: 'Google Passkey'
});

RESPONSE

200
{
    "status_code": 200,
    "request_id": "request-id-test-b05c992f-ebdc-489d-a754-c7e70ba13141",
    "user_id": "user-test-16d9ba61-97a1-4ba4-9720-b03761dc50c6",
    "webauthn_registration": {
      "webauthn_registration_id": "webauthn-registration-test-5c44cc6a-8af7-48d6-8da7-ea821342f5a6",
      "domain": "example.com",
      "user_agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.103 Safari/537.36",
      "authenticator_type": "platform",
      "verified": true,
      "name": "Google Passkey"
    }
  }

Browser supports Autofill

Determines if the browser supports autofill. If it does, we recommend using conditional_mediation when authenticating.

const STYTCH_PUBLIC_TOKEN = 'PUBLIC_TOKEN';
const stytch = Stytch(STYTCH_PUBLIC_TOKEN);

const browserSupportsAutofill = stytch.webauthn.browserSupportsAutofill();

UI components

The SDK also comes with a pre-built UI component for our Passkeys product.

To add passkeys to the login UI, add Products.passkeys to the products array in the configuration.

We require that you also add at least one other product to the products array as well.

To see all authentication and customization options, see the UI config section below.

import React from 'react';
import { Products } from '@stytch/vanilla-js';
import { StytchLogin } from '@stytch/react';

const config = {
  emailMagicLinksOptions: {
    loginExpirationMinutes: 30,
    loginRedirectURL: 'https://example.com/authenticate',
    signupExpirationMinutes: 30,
    signupRedirectURL: 'https://example.com/authenticate',
  },
  products: [Products.emailMagicLinks, Products.passkeys],
};

export const Login = () => {
  return <StytchLogin config={config} />;
};

There is a separate component for the Passkey registration flow.

The component takes all props the StytchLogin component supports.

To see all authentication and customization options, see the UI config section below.

import React from 'react';
import { Products } from '@stytch/vanilla-js';
import { StytchPasskeyRegistration } from '@stytch/react';

const config = {
  emailMagicLinksOptions: {
    loginExpirationMinutes: 30,
    loginRedirectURL: 'https://example.com/authenticate',
    signupExpirationMinutes: 30,
    signupRedirectURL: 'https://example.com/authenticate',
  },
  products: [Products.emailMagicLinks, Products.passkeys],
};

export const PasskeyRegistration = () => {
  return <StytchPasskeyRegistration config={config} />;
};