Contact salesSign inSign up
AuthsignalAuthsignal
Product
Passwordless / multi-factor authentication (MFA)
Drop-in authentication
Risk-based authentication
Passkeys
Biometric authentication
WhatsApp OTP
Authenticator apps (TOTP)
Push authentication
SMS OTP
Email OTP
Magic links
See all authenticators
See less authenticators
Palm biometrics
Contactless payments & identity verification
Flexible integration modes
Pre-built UI
Low code
UI components
Customizable
Custom UI
Flexible
Digital credentials API Beta
Authenticate customers instantly using digital credentials
Session management
Keep users signed in across web and mobile after authentication
Fraud Controls
Rules and policies engine
Step-up authentication
No-code rule creation
Risk alerts
User observability
Audit trails
Dynamic linking
Why Authsignal?
Complete authentication infrastructure from enrollment to step-up auth, modular by design
Solutions
By USE CASE
View All
Account takeovers (ATO)
Go passwordless
Call center
SMS cost optimization
Existing apps
QR code payments
Step-up MFA
Palm biometrics payments
By INDUSTRY
View All
Financial services
Marketplace
e-Commerce
FinTech
Crypto
Healthcare
By Integration (identity provider)
Amazon Cognito
Azure AD B2C
Duende IdentityServer
Keycloak
Auth0
NextAuth.js
Custom identity provider
By ROLe
Engineers
Product
Passwordless / Multi-factor Authentication (MFA)
Flexible Integration Modes
Pre-built UI · Low code
UI Components · Customizable
Custom UI · Flexible
Digital credentials API Beta
Authenticate customers instantly using digital credentials
Session management
Issue JWT access and refresh tokens
Why Authsignal?
Plug in Authsignal to elevate your IDP — effortless integration with any architecture.
Drop-in Authentication
Risk-based authentication
Passkeys
Biometric authentication
WhatsApp OTP
SMS OTP
Email OTP
Magic links
Authenticator apps (TOTP)
Push notifications
Palm Biometrics
Contactless payments & identity verification
Fraud Controls
Rules and Policies Engine
Step-up Authentication
No Code Rule Creation
Risk Alerts
User Observability
Audit Trails
Use Cases
Financial services
Account takeovers (ATO)
Marketplace
Go passwordless
e-Commerce
Solutions
By Use Case
Account takeovers (ATO)
Go passwordless
Call center
SMS cost optimization
Existing apps
QR code payments
Step-up MFA
Palm Biometric Payments
View all Use Cases
By Industry
Financial services
Marketplace
e-Commerce
FinTech
Crypto
Healthcare
View all Industries
By Integration (identity provider)
Amazon Cognito
Azure AD B2C
Duende IdentityServer
Keycloak
Auth0
NextAuth.js
Custom identity provider
By Role
Engineers
PricingAboutDocsBlog
Schedule a call
Try Authsignal
AUS Flag

Authsignal secures millions of passkey transactions out of our hosted Sydney region.

AUS Flag

Authsignal secures millions of passkey transactions out of our hosted Sydney region.

Join us today!
Right icon
Blog
/
Current article
e-Commerce
Passkeys
Passwordless authentication
Implementation
Guides

How to implement passkeys for a seamless E-commerce checkout experience.

Steven Clouston
⬤
May 14, 2025
Share
How to Implement Passkeys for a Seamless E-Commerce Checkout Experience.

Implementing passkeys at checkout on your eCommerce store enables you to deliver a seamless and secure experience for your customers. Passkeys enable a new standard of authentication not seen before in the eCommerce marketplace. Brands like Shopify are now starting to set a new standard in this space with their streamlined checkout processes, combining simplicity with strong authentication methods employing passkeys.

Below, we dive into how to integrate passkeys at checkout for your customers.

In this guide, we’ll walk through how to use Authsignal’s email OTP authenticator and passkeys to create a seamless user experience for your e-commerce platform. We'll focus on the technical aspects of implementing these features, giving you a clear, actionable path to building a secure passwordless authentication flow.

‍

‍

Step-by-Step Guide to Implementing Authsignal’s Email OTP and Passkeys

‍

For brevity, this implementation guide focuses on the specific requirements for integrating Authsignal. Some more general steps, such as frontend setup and common implementation details, have been simplified to keep the focus on the core Authsignal integration.

This guide uses Authsignal's Web and Node SDKs. Authsignal provides SDKs for a number of languages, so you can adapt this guide to suit your needs:

‍

Step 1: Set Up Email OTP Authentication

‍

Email OTP (One-Time Password) is the first step in our passwordless authentication process. It provides a simple yet secure method for users to verify their identity during sign-up or login.

This initiates the authentication chain, with email OTP as the primary security layer. Once verified, users can add additional authenticators like passkeys. Email OTP also serves as a reliable backup when passkeys are unavailable, creating a robust, multi-layered authentication system.

Our process involves checking if a user is already verified. For verified users with an email authenticator, we'll prompt them to complete an email OTP challenge and pre-fill their information. New users will be asked to complete their details. After verification, we proceed with the checkout.

To begin, sign in to Authsignal's authenticators section and set up an email OTP authenticator.

‍

1. Backend: Create an endpoint that checks if the user has a verified account. If so, this will return a URL that the frontend can use to launch Authsignal’s pre-built UI. We will call this endpoint /lookup-user but you can call it what you like.

‍

//POST /lookup-user

//find the user in your database by looking up their email

const authsignalUser = await authsignal.getUser({ userId: user.id });

if (authsignalUser?.enrolledVerificationMethods?.includes(EMAIL_OTP)) {
  // The user has an email authenticator
  
  const response = await authsignal.track({
    email: req.body.email,
    userId: user.id,
    action: "sign-in",
    redirectUrl: `${baseUrl}/activity`,
    deviceId: req.body.deviceId,
    userAgent: req.headers["user-agent"],
    ipAddress: requestIp.getClientIp(req) ?? undefined,
  });

  res.status(201).json(response.url);
} else {
  // The user has not verified using email - you could throw an error here
  // and handle it on the frontend
}

‍

For more detailed information about getting the Authsignal user, refer to the documentation.

‍2. Backend: Create an endpoint called /sign-in that we’ll use to generate a session cookie on successful authentication. This endpoint needs to accept a token that we'll receive from Authsignal. The session token generated is independent of Authsignal and is created using a library of your choice (iron-session for example).

‍

//POST sign-in

const { isValid, userId } = await authsignal.validateChallenge({
  token: req.body.token,
});

if (!isValid || !userId) {
  res.status(401).send("User not found");
  return;
}

//find the user in your database using the userId

//if the user is found, generate a session token 
//(you could use something like iron-session for this)

//set a cookie on the frontend that contains the session token 

‍

3. Backend: Create an endpoint called /enroll. This endpoint will create a user in the database and track an action that we can later validate using the /sign-in endpoint.

‍

//POST enroll

//create a user in the database

const response = await authsignal.track({
  email: req.body.email,
  userId: user.id,
  action: "enroll",
  deviceId: req.body.deviceId,
  userAgent: req.headers["user-agent"],
  ipAddress: requestIp.getClientIp(req) ?? undefined,
});

res.status(201).json(response.url);
return;

‍

4. Backend: Create an endpoint called /checkout. This authenticated endpoint will handle product purchases. It uses the session token generated in the /sign-in endpoint—don't confuse this with an Authsignal token.

‍

 //POST checkout
 
 const token = req.cookies.token;
 
 //validate the session token and extract the user ID
 
 //run your checkout logic

‍

‍5. Frontend:  Call the /lookup-user endpoint we created earlier to check if the user has a verified account. This will lead to either scenario A or B, which we'll explore in detail below.

‍

‍

Scenario A: The user does not already have a verified account:

A.1 Frontend: Display a form to collect the user’s details.

‍

‍

A.2 Frontend: Upon form submission, call the /enroll endpoint to create the user in your database and track an enroll action. Use the URL returned from /enroll to launch Authsignal's pre-built UI. The user will only be considered verified after successfully authenticating via email OTP.

‍

const { token: authsignalToken } = await authsignal.launch(url, {
    mode: "popup",
});

‍

‍

Upon successful verification, Authsignal provides a token that we can use to verify the user on the server side and generate a session token.

Our sign-in endpoint will handle this step - we’ll pass it the authsignalToken returned from Authsignal in the code above. For simplicity in this demo, we'll also store the authsignalToken in local storage. This temporary authsignalToken enables the user to add an additional authenticator (passkey in this case) later if needed.

‍

//the sign-in endpoint will set the session cookie if successful 
await fetch(`${baseUrl}/sign-in`, {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
    },
    body: JSON.stringify({ token: authsignalToken }),
    credentials: "include",
  });


 localStorage.setItem("authsignal_token", authsignalToken);

‍

Now that the user is authenticated, we can call the authenticated /checkout endpoint, and you can run your checkout logic.

‍

Admin portal setup

To ensure that the user can only enroll using an email OTP authenticator, navigate to Authsignal’s actions page to configure the enroll action you have tracked.

‍

‍

We'll configure the enroll action to accept only the email OTP authenticator, as shown below. This is crucial because we want email OTP to be the first authenticator added to the authentication chain. Starting with a passkey as the first authenticator would be problematic since passkeys require a fallback authentication mechanism—which email OTP provides. Learn more about Authsignal's authenticators here.

‍

‍

Scenario B: The user already has a verified account:

For users with verified accounts, we'll use Authsignal's email OTP to sign them in and generate a session token. This session token allows us to fetch the user's details and populate the checkout form.

B.1 Frontend: Launch Authsignal’s pre-built UI in popup mode using the URL returned from the /lookup-user endpoint.

‍

const { token: authsignalToken } = await authsignal.launch(url, {
  mode: "popup",
});

‍

‍

Upon successful verification, we will receive a token from Authsignal that can be used to verify the user on the server side and generate a session token.

Call the sign-in endpoint, passing the token received from the Authsignal launch command. For simplicity in this demo, we will also save the token to local storage, allowing us to temporarily use it for the user to add another authenticator later if needed.

‍

await fetch(`${baseUrl}/sign-in`, {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
  },
  body: JSON.stringify({ token: authsignalToken }),
  credentials: "include",
});

localStorage.setItem("authsignal_token", authsignalToken);

‍

B.2 Frontend: With the session token now in place (distinct from Authsignal's token), we can call an authenticated endpoint to retrieve the user's information and pre-populate the form. Here's an example:

‍

 const userDetails = await fetch(`${baseUrl}/user`, {
      method: "GET",
      headers: {
        "Content-Type": "application/json",
      },
      credentials: "include",
    }); 
    
  //populate the form with the user's details

‍

‍

B3. Frontend: When the user clicks 'Pay now', call the/checkout endpoint to execute the required checkout logic.

At this point, you may want to redirect the user to a dashboard where they can view their purchase details.

‍

‍

Step 2: Add a Passkey Authenticator

We'll now add functionality to allow users to create a passkey and use it for sign-in with passkey autofill. This enhances the user experience significantly and can help convert visitors into paying customers.

‍

‍

Navigate to Authsignal’s authenticators page and add passkey as an authentication option.

As we are developing locally on port 5173, these are the passkey settings we’ll use. You can learn more about developing with passkeys in a local environment here.

‍

‍

1. Passkey prompt and passkey creation

On the first page that the user lands on after authentication, we can use Authsignal's isAvailableOnDevice check to determine if the user has a passkey on the current device. If not, we will show a prompt so they can add a passkey.

‍

‍

To create a passkey, the Authsignal SDK needs an authenticated user token. For simplicity in this demo, we'll use the token from the successful login via the pre-built UI, which we saved in local storage earlier. Keep in mind that this token is only valid for 10 minutes. If needed, you can generate a new token from your backend. For more details on creating passkeys, check out the documentation.

‍

//Code to prompt the user to create a passkey on their device
async function promptToCreatePasskey() {
  
  //get the authsignal_token that we stored earlier
  const token = localStorage.getItem("authsignal_token");

  localStorage.removeItem("authsignal_token");

  // True if a passkey has already been created on this device using the Web SDK
  const isPasskeyAvailable = await authsignal.passkey.isAvailableOnDevice();

  if (token && !isPasskeyAvailable) {
    const result = await authsignal.passkey.signUp({ token });

    if (result) {
      alert("Passkey created!");
    }
  }
}

useEffect(() => {
  promptToCreatePasskey();
}, []);

‍

‍2. Sign-in with a passkey using autofill

We will now make some changes to our checkout form so that passkeys are detected and shown as an option if they are available.

‍

‍

To enable passkey autofill, add the attribute autoComplete="username webauthn" to the email input field, as shown below. For more information about passkey autofill, check out our detailed guide.

‍

<input
	autoComplete="username webauthn"
	...
/>

‍

We'll also need to add the following logic that runs on page load. Upon success, we receive a token from Authsignal that we'll validate on our backend. We can pass this token to our existing /sign-in endpoint that we created earlier. If the token is valid, the sign-in endpoint will generate a session cookie for us, which we can use to retrieve the user's details.

‍

useEffect(() => {
    const initPasskeyAutofill = async () => {
      try {
        const { token, userDisplayName: email } = await authsignal.passkey.signIn({
          action: "passkey-sign-in",
          autofill: true,
        }) || {};
  
        if (token && email) {
          await fetch(`${baseUrl}/sign-in`, {
            method: "POST",
            headers: {
              "Content-Type": "application/json",
            },
            body: JSON.stringify({ token }),
            credentials: "include",
          });
        }
      } catch (error) {
        console.error("Error during passkey autofill:", error);
      }
    };
  
    initPasskeyAutofill();
  }, []);

‍

‍

Now that the user is signed-in, we can access authenticated endpoints, retrieve the user’s details and populate the form, in the same way we did with email-OTP.

‍

‍

The authenticated /checkout endpoint can be called when the ‘Pay now’ button is clicked.

Conclusion

Implementing a secure and user-friendly checkout process like Shopify's is now within reach for e-commerce platforms of all sizes. By leveraging Authsignal's email OTP and passkey authentication, you can create a seamless, passwordless experience that enhances both security and convenience for your customers.

This guide has walked you through the key steps:

  • Setting up email OTP authentication
  • Implementing passkey creation and autofill functionality
  • Integrating these features into your checkout flow

By following these steps, you'll be able to offer a modern, friction-free checkout experience that can help increase conversions and customer satisfaction. Remember, the key is to balance security with usability, and the combination of email OTP and passkeys achieves just that.

Question icon
Have a question?
Talk to an expert
NewsletterDemo PasskeysView docs
e-Commerce
Passkeys
Passwordless authentication
Implementation
Guides

You might also like

How to add push authentication to your app with Authsignal and React Native
Push authentication
React native
Node.js
Multi-factor authentication
Guides

How to add push authentication to your app with Authsignal and React Native

March 27, 2026
BSP Circular 1213: Philippine banks must replace SMS OTPs by June 2026
BSP Circular 1213
Philippine banking
SMS OTP
Risk based authentication

BSP Circular 1213: Philippine banks must replace SMS OTPs by June 2026

March 18, 2026
How to add adaptive MFA and passkeys to any web app with Authsignal and Lambda@Edge
AWS
Authentication
Security

How to add adaptive MFA and passkeys to any web app with Authsignal and Lambda@Edge

March 10, 2026

Secure your customers’ accounts today with Authsignal

Passkey demoCreate free account

Authsignal delivers passwordless and multi-factor authentication as a service. Focused on powering mid-market and enterprise businesses to rapidly deploy optimized good customer flows that enable a flexible and risk-based approach to authentication.

AICPA SOCFido Certified
LinkedInTwitter
Passwordless / multi-factor authentication (MFA)
Pre-built UI (low code)UI components (customizable)Custom UI (flexible)
Why Authsignal?
Drop-in authentication
Risk-based authentication PasskeysBiometric authenticationWhatsApp OTPSMS OTPEmail OTPMagic linksAuthenticator apps (TOTP)Push authenticationPalm biometricsDigital Credential Verification API
Rules and policies engine
User observability
Industries
Financial services
Marketplace
e-Commerce
FinTech
Crypto
View all industries
Teams
Engineers
Use cases
Account takeovers (ATO)
Go passwordless
Call center
SMS cost optimization
Existing apps
View all use cases
Identity providers (IDPs)
Amazon Cognito
Auth0
Azure AD B2C
Custom identity provider
Duende IdentityServer
Keycloak
NextAuth.js
Integrations
ASP.NET
C#
Java
Node.js
Open ID Connect (OIDC)
PHP
Python
React
Ruby
Ruby on Rails
Compare
Twilio Verify vs AuthsignalAuth0 vs AuthsignalAWS Cognito vs Authsignal + AWS Cognito
Resources
BlogDeveloper docsFree Figma mobile passkeys templateFree Figma desktop passkeys templateFree Figma webapp passkeys template
Company
About usWhy AuthsignalCareersPress releasesPartnersContact us
What is
SMS OTP
Risk Based Authentication
IP Spoofing
Passwordless authentication
Multi-Factor Authentication (MFA)
United States
+1 214 974-4877
Ireland
+353 12 676529
Australia
+61 387 715 810
New Zealand
+64 275 491 983
© 2026 Authsignal - All Rights Reserved
Terms of servicePrivacy policySecuritySystem statusCookies