Skip to content

@W-21056536 Error handling Passkey Registration and Login#3672

Merged
hajinsuha1 merged 29 commits intofeature/webauthn-loginfrom
W-21056536-error-handling-passkey-registration-and-login
Feb 23, 2026
Merged

@W-21056536 Error handling Passkey Registration and Login#3672
hajinsuha1 merged 29 commits intofeature/webauthn-loginfrom
W-21056536-error-handling-passkey-registration-and-login

Conversation

@hajinsuha1
Copy link
Collaborator

@hajinsuha1 hajinsuha1 commented Feb 18, 2026

Description

Display user-friendly error messages for errors during passkey login and registration
Doc listing all error message mapping: https://salesforce.quip.com/97bPANYv5D2U

After a lot of thinking, I chose to use a more generic error handling approach of returning a "Something went wrong. Try again!" error for most cases because passkey login is triggered automatically rather than via a button.

Types of Changes

  • Bug fix (non-breaking change that fixes an issue)
  • New feature (non-breaking change that adds functionality)
  • Documentation update
  • Breaking change (could cause existing functionality to not work as expected)
  • Other changes (non-breaking changes that does not fit any of the above)

Breaking changes include:

  • Removing a public function or component or prop
  • Adding a required argument to a function
  • Changing the data type of a function parameter or return value
  • Adding a new peer dependency to package.json

Changes

  • display user-friendly error message for errors during
    • passkey login:
      • use-auth-modal.js
      • pages/login/index.jsx
    • passkey registration:
      • use-passkey-registration.jsx

How to Test-Drive This PR

Unit Tests

Since CI is broken for now becasue we are using commerce-sdk-isomorphic preview version
Ensure the modified unit tests pass:

npm run test passkey-registration-modal use-auth-modal pages/login/index.test.jsx use-passkey-login
Screenshot 2026-02-19 at 3 38 59 PM

Passkey Login Errors

Cancelling does not display error

  1. Navigate to https://wasatch-mrt-passwordless-poc.mrt-storefront-staging.com/login
  2. Cancel the passkey login by closing all passkey prompts
  3. Verify no error message is displayed and no error is logged
  4. Repeat for use-auth-modal
Screenshare.-.2026-02-19.2_48_29.PM.mp4
Screenshare.-.2026-02-19.2_23_07.PM.mp4

412 from timeout does not display error

  1. Attempt passkey login twice in 1 minute to trigger 412 error due to timeout
  2. Verify "We couldn't verify your passkey. Try again or use a different login method." error is displayed
  3. Repeat for use-auth-modal
Screenshare.-.2026-02-19.2_20_18.PM.mp4
Screenshare.-.2026-02-19.2_21_15.PM.mp4

401 client error displays error

  1. Navigate to https://wasatch-mrt-passwordless-test.mrt-storefront-staging.com/login. This site has deployed a misconfigured retail react app where it's using a private client but useSLASPrivateClient settings are not enabled. This means the /start call will return a 401 Unauthorized as the correct auth headers are not sent.
  2. Verify a "Something went wrong, Try again!" error is displayed
    Screenshot 2026-02-19 at 4 50 51 PM
  3. Repeat for use-auth-modal
    Screenshot 2026-02-19 at 4 51 02 PM

Passkey Registration Errors

Cancelling displays error

  1. Navigate to https://wasatch-mrt-passwordless-poc.mrt-storefront-staging.com/login
  2. Login using your salesforce email
  3. Click "Create Passkey" button
  4. Click "Register Passkey" button when prompted for a nickname
  5. Enter the OTP received in your email
  6. When passkey prompts appear close all of them
  7. Verify a "Something went wrong, Try again!" error is displayed
Screenshare.-.2026-02-19.2_17_17.PM.mp4

401 from entering incorrect token

  1. Navigate to https://wasatch-mrt-passwordless-poc.mrt-storefront-staging.com/login
  2. Login using your salesforce email
  3. Click "Create Passkey" button
  4. When OTP is prompted, enter a random number
  5. Verify "Invalid token, please try again." error is displayed
Screenshare.-.2026-02-19.2_18_39.PM.mp4

Checklists

General

  • Changes are covered by test cases
  • CHANGELOG.md updated with a short description of changes (not required for documentation updates)

Accessibility Compliance

You must check off all items in one of the follow two lists:

  • There are no changes to UI

or...

Localization

  • Changes include a UI text update in the Retail React App (which requires translation)

…n components; add utility function for passkey error messages
…place deprecated error message function with a new utility for improved clarity and add handling for too many registration attempts.
…ude mappings for various error responses and ensure correct message descriptors are returned.
…able passkey login tests, handle user cancellation errors, and ensure proper rendering of UI elements during authentication.
…test clarity; mock configurations for passkey enabled/disabled scenarios, and ensure proper UI rendering during authentication processes.
@cc-prodsec
Copy link
Collaborator

cc-prodsec commented Feb 18, 2026

Snyk checks have passed. No issues have been found so far.

Status Scanner Critical High Medium Low Total (0)
Open Source Security 0 0 0 0 0 issues
Licenses 0 0 0 0 0 issues

💻 Catch issues earlier using the plugins for VS Code, JetBrains IDEs, Visual Studio, and Eclipse.

@hajinsuha1 hajinsuha1 changed the base branch from develop to feature/webauthn-login February 18, 2026 16:48
hajinsuha1 and others added 7 commits February 18, 2026 13:23
…nents; replace showToast with showRegisterPasskeyToast for improved clarity and functionality. Update tests to validate passkey registration toast display after successful login, ensuring proper configuration checks and UI rendering.
… messages for unavailable features and authentication API errors. Update related tests to ensure correct message mappings for various error responses.
…fully, including early returns for 412 status. Improve passkey authentication error handling by adding console error logging in AuthModal and Login components.
@hajinsuha1 hajinsuha1 marked this pull request as ready for review February 19, 2026 19:43
@hajinsuha1 hajinsuha1 requested a review from a team as a code owner February 19, 2026 19:43
…s components to standardize user feedback. Replace specific error messages with a generic "Something went wrong. Try again!" message. Update tests to reflect these changes and ensure consistent error handling in the UI.
Comment on lines -110 to -121
let credential
try {
credential = await navigator.credentials.create({
publicKey
})
} catch (createError) {
// Handle user cancellation or other errors from the WebAuthn API
if (createError.name === 'NotAllowedError' || createError.name === 'AbortError') {
throw new Error('Passkey registration was cancelled or timed out')
}
throw createError
}
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

during registration, any errors from the browser should tell the user that soemthing went wrong. Instead of throwing a custom error, we let the error be thrown automatically and handle it in the catch below

Comment on lines -282 to -298
if (config?.app?.login?.passkey?.enabled) {
// Show passkey registration modal only if Webauthn feature flag is enabled and compatible with the browser
if (
window.PublicKeyCredential &&
window.PublicKeyCredential.isUserVerifyingPlatformAuthenticatorAvailable &&
window.PublicKeyCredential.isConditionalMediationAvailable
) {
Promise.all([
window.PublicKeyCredential.isUserVerifyingPlatformAuthenticatorAvailable(),
window.PublicKeyCredential.isConditionalMediationAvailable()
]).then((results) => {
if (results.every((r) => r === true)) {
showToast()
}
})
}
}
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

moved this logic into showRegisterPasskeyToast as it's duplicated here and in the login page

Comment on lines +46 to +50
// 412 is returned when user attempts to authenticate within 1 minute of a previous attempt
// We return early in this case to avoid showing an error to the user
if (error.response?.status === 412) {
return
}
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The most common 412 error from the startWebauthnAuthenticationResponse is when a user attempts to start the passkey login multiple times within a minute.

Because the passkey login prompt is triggered automatically upon opening the login form, we fail silently for a 412 to avoid causing confusion.

if (error.name == 'NotAllowedError') {
return
}
console.error('Error getting passkey credential from browser:', error)
Copy link
Collaborator Author

@hajinsuha1 hajinsuha1 Feb 19, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we log any errors returned from the browser to help in debugging.
API errors are automatically logged by pwa kit

defaultMessage: 'Failed to register passkey'
})

console.error('Error registering passkey:', err)
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

although API errors are automatically logged, we want to ensure the errors from the browser and custom errors that are thrown are logged to help in debugging issues.

@hajinsuha1 hajinsuha1 added the skip changelog Skip the "Changelog Check" GitHub Actions step even if the Changelog.md files are not updated label Feb 20, 2026
@jeremy-jung1
Copy link
Collaborator

jeremy-jung1 commented Feb 23, 2026

Decisions in the code and errors look fair to me. When putting an invalid OTP for registration, I'm seeing "Something went wrong. Try again!" instead of the invalid token. The API response was

{
  "status_code" : "401 UNAUTHORIZED",
  "message" : "Webauthn action token not found"
}
seeing.something.went.wrong.try.again.mov

@hajinsuha1
Copy link
Collaborator Author

Decisions in the code and errors look fair to me. When putting an invalid OTP for registration, I'm seeing "Something went wrong. Try again!" instead of the invalid token. The API response was

{
  "status_code" : "401 UNAUTHORIZED",
  "message" : "Webauthn action token not found"
}

seeing.something.went.wrong.try.again.mov

Thanks for catching that! Looks like when deployed to MRT the proxy/cdn strips the status messsage. I've updated it to display "Invalid token" on 401. This should be okay as they'd only get a 401 at this step for a invalid token

You can see it working here: https://wasatch-mrt-passwordless-poc.mrt-storefront-staging.com

Screenshot 2026-02-23 at 4 26 42 PM

const otpCode = '12345678'

mockStartWebauthnRegistration.mockRejectedValue(new Error('Unauthorized'))
mockStartWebauthnRegistration.mockRejectedValue(new Error('401'))
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

later if we touch this file again, we should update the tests to mock commerce-sdk-react using msw!

@hajinsuha1 hajinsuha1 merged commit 50f2629 into feature/webauthn-login Feb 23, 2026
42 checks passed
@hajinsuha1 hajinsuha1 deleted the W-21056536-error-handling-passkey-registration-and-login branch February 23, 2026 21:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

skip changelog Skip the "Changelog Check" GitHub Actions step even if the Changelog.md files are not updated

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants