---
schema_version: "1"
id: 2bea831743ac0846812ac01576efe911fee2036396e3b696fbbf480b1bc60018
title: Passwordless Login with Passkeys for Storefront Next
collection: developer
version: current
locale: en-us
portal_url: https://docs.salesforce.com/developer/current/en-us/commerce-cloud/sfnext/guides/sfnext-passkey-login.md
canonical_url: https://developer.salesforce.com/docs/commerce/pwa-kit-managed-runtime/guide/sfnext-passkey-login.html
source_site: developer.salesforce.com
content_type: documentation
content_hash: 142db7fba764765c0c6cb750a78a56934b3d3c4a88838662e2e9b5c1c4ef70ee
products:
  - Composable Storefront
  - Salesforce APIs
---
# Passwordless Login with Passkeys for Storefront Next

Storefront Next supports passwordless login with passkeys, letting shoppers sign in with a device biometric or security key instead of a password. Passkeys are built on the WebAuthn and FIDO2 standards and use public key cryptography: the shopper's device holds a private key that never leaves the authenticator, and Shopper Login and API Access Service (SLAS) stores only the corresponding public key.

When you enable passkeys, a signed-in shopper can:

- Register a passkey on a device with an authenticator.
- Manage (view and delete) their registered passkeys from their account.

Passkeys build on SLAS passwordless login. For the underlying API contract, request and response shapes, and server-side behavior, see [Passwordless Login with Passkeys](https://developer.salesforce.com/docs/commerce/commerce-api/guide/slas-passwordless-login-passkey.html) in the _B2C Commerce API Developer Guide_.

**note:** Hybrid storefronts that use Storefront Next don't currently support passkeys.

## Prerequisites

- A SLAS client configured for passkeys, with WebAuthn configuration (Relying Party ID and Allowed Origins) set through the SLAS Admin UI. See [Before You Begin](https://developer.salesforce.com/docs/commerce/commerce-api/guide/slas-passwordless-login-passkey.html#before-you-begin) in the _B2C Commerce API Developer Guide_.
- An OTP delivery method for authorizing registration. Registering a passkey requires the shopper to be signed in and to confirm a one-time passcode (OTP). The delivery method is controlled by `features.passkey.mode` (see [Configure Settings](#configure-settings)).

## Configure Settings

To control passkey settings, update the `features.passkey` object in `config.server.ts`.

```ts
// config.server.ts
const config = {
  // ...
  features: {
    passkey: {
      enabled: false,
      mode: "email", // 'email' | 'callback'
      callbackUri: "", // required only when mode is 'callback'
    },
  },
};
```

- `features.passkey.enabled`: Specifies whether passkey registration and login are enabled (`true`) or not. Type: boolean. Defaults to `false`.
- `features.passkey.mode`: The mode used to deliver the OTP that authorizes passkey registration. Type: `'email' | 'callback'`. Defaults to `'email'`.
  - `email`: SLAS emails the OTP to the shopper.
  - `callback`: SLAS POSTs the OTP to your `callbackUri` instead of emailing the shopper. Requires `callbackUri` to be set and registered for your SLAS client. Useful when you deliver the code through your own email or SMS provider.
- `features.passkey.callbackUri`: The callback URI sent to SLAS when authorizing registration. Type: string. Required when `mode` is `'callback'`. Must be an absolute URL pointing to an external service, for example `https://example.com/passkey-callback`.

**note:** The OTP length isn't set on the `features.passkey` object. Instead, it comes from the shared `auth.otpLength` setting, which must match your SLAS client. For Storefront Next, the default value is `6`. See [Passwordless Login for Storefront Next](https://developer.salesforce.com/docs/commerce/sfnext/guide/sfnext-passwordless-login.html#configure-settings).

To override configuration options, use Managed Runtime (MRT) environment variables with the `PUBLIC__` prefix.

```shell
PUBLIC__app__features__passkey__enabled=true
PUBLIC__app__features__passkey__mode=callback
PUBLIC__app__features__passkey__callbackUri=https://www.example.com/webauthn-login-callback
PUBLIC__app__auth__otpLength=8
```

The `rpId` and Allowed Origins aren't set in the storefront config. They live on the SLAS client (see [Prerequisites](#prerequisites)). SLAS returns these values to the browser during the WebAuthn ceremony.

## How Passkeys Work in Storefront Next

Storefront Next calls the browser WebAuthn API and relays the results to SLAS through server-side route actions. There are two flows: registration (a signed-in shopper enrolls a passkey) and authentication (a returning shopper signs in with a passkey).

### Register a Passkey

A shopper must be signed in (a registered user) to register a passkey. Registration is authorized with a one-time passcode.

1. The signed-in shopper chooses to add a passkey. The storefront authorizes registration, and SLAS delivers an OTP according to `features.passkey.mode`.
2. The shopper enters the OTP.

   ![Passkey OTP verification modal](https://developer.salesforce.com/docs/media/sfnext/sfnext-passkey-verify-otp.png '{"class": "image-md"}')

3. The storefront starts registration, passing the `pwdActionToken` and an optional passkey nickname (up to 128 characters). SLAS returns WebAuthn credential-creation options, including a random challenge.
4. The storefront passes the options to `navigator.credentials.create()`. The browser prompts the shopper's authenticator (biometric or PIN).
5. The authenticator generates a public/private key pair and returns a public key credential.
6. The storefront finishes registration, sending the credential and `pwdActionToken`. SLAS verifies the challenge, origin, and signature, then stores the public key.

**note:** The `pwdActionToken` ties the WebAuthn ceremony to a verified OTP. Start a fresh authorization if it expires. Don't reuse a token or challenge across attempts.

### Sign In with a Passkey

Authentication signs a returning shopper in without a password.

1. The shopper chooses to sign in with a passkey. The storefront starts authentication. It can omit the shopper identifier to request a discoverable-credential challenge (the browser or autofill lets the shopper choose which passkey to use), or pass a `userId` to scope the challenge to a specific login.
2. SLAS returns authentication options, including the challenge, the `allowCredentials` list, and the `rpId`.
3. The storefront passes the options to `navigator.credentials.get()`. The browser prompts the shopper's authenticator.
4. The authenticator returns an assertion, a digital signature proving the shopper controls the private key.
5. The storefront finishes authentication, sending the assertion and the current guest `usid` so the guest basket and wishlist are linked to the shopper. SLAS verifies the signature and returns a shopper access token in JSON Web Token (JWT) format.
6. The shopper is signed in. The storefront merges and recalculates the guest basket and merges any guest wishlist.

For full request and response schemas, see [Passwordless Login with Passkeys](https://developer.salesforce.com/docs/commerce/commerce-api/guide/slas-passwordless-login-passkey.html) in the _B2C Commerce API Developer Guide_.

### Manage Passkeys

When passkeys are enabled, the account area can show whether a shopper has a registered passkey and let them remove one. The storefront queries passkey status for the signed-in shopper and can delete a specific credential by its ID. Provide this UI so shoppers can revoke access from lost or retired devices.

![Manage passkeys in the account area](https://developer.salesforce.com/docs/media/sfnext/sfnext-passkey-manage.png '{"class": "image-md"}')

## Best Practices

- Keep `rpId` and Allowed Origins aligned with your deployment. When you add a domain, staging origin, or port, update the SLAS client's WebAuthn configuration before shoppers reach it.
- Match `auth.otpLength` to your SLAS client. The value sets the OTP modal's slot count and the "we sent an N-digit code" copy. SLAS issues 6- or 8-digit codes.
- Offer a fallback. Keep another sign-in method (email OTP or password) available for shoppers on unsupported browsers or new devices without a registered passkey.
- Use callback mode only when you own the delivery. Set `mode` to `'callback'` with a registered absolute callback URI when routing the OTP through your own email or SMS provider. Otherwise, keep the default email mode.

## Troubleshoot Passkeys

**Passkey registration or login fails silently in the browser**

_Potential cause:_ The storefront origin doesn't match the SLAS client's `rpId` or isn't listed in Allowed Origins. The browser blocks the WebAuthn ceremony before any request reaches SLAS.

_Suggested solution:_ In the SLAS Admin UI (or via the SLAS Admin API), confirm that `rpId` is the registrable domain of the storefront (for example, `example.com`) and that every origin the storefront runs on, including ports used in local or staging environments, is listed in Allowed Origins.

**Passkey routes return 404 Not Found**

_Potential cause:_ `features.passkey.enabled` is `false`. Every passkey route returns 404 when the feature is turned off.

_Suggested solution:_ Set `features.passkey.enabled` to `true` in `config.server.ts` (or via the `PUBLIC__app__features__passkey__enabled` environment variable) and redeploy.

**Registration OTP never arrives**

_Potential cause:_ In callback mode, `callbackUri` is missing, not an absolute URL, or not registered for the SLAS client, so SLAS has nowhere to POST the OTP.

_Suggested solution:_ Set `features.passkey.callbackUri` to an absolute URL (for example, `https://example.com/passkey-callback`) and register it for your SLAS client, or switch to email mode to have SLAS email the OTP directly.

**Registration fails after the shopper enters the OTP**

_Potential cause:_ The `pwdActionToken` expired or was reused, or the challenge or origin didn't validate on the SLAS side.

_Suggested solution:_ Restart the flow so the shopper receives a fresh OTP and a new `pwdActionToken`. Don't reuse a token or challenge. Confirm the browser-reported origin matches the SLAS client's Allowed Origins.

**Login starts but no passkey is offered**

_Potential cause:_ The shopper has no passkey registered for the account (or on the current device), so the `allowCredentials` list is empty.

_Suggested solution:_ Route the shopper to registration or an alternative sign-in method. A passkey must be registered on the account and available on the device before it can be used to sign in.

**Passkey login intermittently returns no options**

_Potential cause:_ SLAS is briefly throttling repeated authentication starts (HTTP 412). The storefront treats this as a silent no-op rather than an error.

_Suggested solution:_ This is expected rate-limiting. Have the shopper retry after a short wait. Avoid triggering authentication starts in a tight loop.

## See Also

- [Passwordless Login for Storefront Next](https://developer.salesforce.com/docs/commerce/pwa-kit-managed-runtime/guide/sfnext-passwordless-login.md)
- [Passwordless Login with Passkeys](https://developer.salesforce.com/docs/commerce/commerce-api/guide/slas-passwordless-login-passkey.html)
- [Passwordless Login](https://developer.salesforce.com/docs/commerce/commerce-api/guide/slas-passwordless-login-overview.html)
- [Shopper Login and API Access Service (SLAS) Overview](https://developer.salesforce.com/docs/commerce/commerce-api/guide/slas.html)
- [Shopper Login API Reference](https://developer.salesforce.com/docs/commerce/commerce-api/references/shopper-login)
