Skip to content

@W-20279798 support setting passwordless login mode in config#3492

Merged
hajinsuha1 merged 19 commits intofeature/email-otpfrom
W-20279798-support-setting-passwordless-login-mode-in-config
Dec 10, 2025
Merged

@W-20279798 support setting passwordless login mode in config#3492
hajinsuha1 merged 19 commits intofeature/email-otpfrom
W-20279798-support-setting-passwordless-login-mode-in-config

Conversation

@hajinsuha1
Copy link
Collaborator

@hajinsuha1 hajinsuha1 commented Dec 3, 2025

Description

Added a new mode to the passwordless configuration that allows merchants to configure the mode they want to use for all oauth/passwordless/login calls:

  • packages/template-retail-react-app/app/hooks/use-auth-modal.js
  • packages/template-retail-react-app/app/pages/login/index.jsx
  • packages/template-retail-react-app/app/pages/checkout/partials/contact-info.jsx

Now it will set the passwordless login mode to the following

# Email mode
passwordless: {
   enabled: true,
   mode: 'email',
   landingPath: '/passwordless-login-landing'
},

# Callbackmode
passwordless: {
   enabled: true,
   mode: 'callback',
   callbackURI: 'https://webhook.site/e6f88064-36bc-4605-8128-a94810bd4318',
   landingPath: '/passwordless-login-landing'
},

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

  • commerce-sdk-react
    • added locale to Auth object
    • Update authorizePasswordless to pass locale and simplify mode selection to respect user's explicit mode choice while still defaulting to callback mode for backward compatibility
  • template-retail-react-app
    • Update passwordless login to use email mode by default
    • The passwordless login mode can now be configured across the login page, auth modal, and checkout page

How to Test-Drive This PR

Email mode

This tests when default.js is configured to the following:

passwordless: {
   enabled: true,
   mode: 'email',
   landingPath: '/passwordless-login-landing'
},
  1. Configure and start the template-retail-react-app
    # Checkout this branch
    git checkout W-20279798-support-setting-passwordless-login-mode-in-config
    
    # Revert this commit to setup `template-retail-react-app` with private client and updates the default.js commerceApi configuraton
    git revert 66bcafa4d5677e691c1f55fa37987e17b71e66d3
    
    # Build commerce-sdk-react locally by building the entire app
    npm ci
    
    # Set the private client secret via env vars and start the `template-retail-react-app`
    export PWA_KIT_SLAS_CLIENT_SECRET=SECRET
    cd packages/template-retail-react-app
    npm start
    
  2. Once the app has started, login using the Continue Securely button after entering your email to trigger passwordless login
  3. Verify the Check your email screen is shown
    Screenshot 2025-12-05 at 9 57 50 AM
  4. Verify an email was sent to you with the OTP
  5. Repeat steps 2-4 for the http://localhost:3000/us/login page (verify the locale that is sent is en-US instead of en-GB)
  6. Repeat steps 2-4 for the login from the checkout page

Callback mode

  1. Update default.js to
                passwordless: {
                    enabled: true,
                    mode: 'callback',
                    callbackURI: 'https://webhook.site/e6f88064-36bc-4605-8128-a94810bd4318',
                    landingPath: '/passwordless-login-landing'
                },
    
  2. Restart the server
    npm start
    
  3. Once the app has started, login using the Continue Securely button after entering your email to trigger passwordless login
  4. Verify the Check your email screen is shown
    Screenshot 2025-12-05 at 9 57 50 AM
  5. Verify SLAS sent a POST request to the webhook callback uri: https://webhook.site/#!/view/e6f88064-36bc-4605-8128-a94810bd4318
  6. Repeat steps 2-4 for the http://localhost:3000/login page
  7. Repeat steps 2-4 for the login from the checkout page

Backwards Compatibilty with template-retail-react-app

The current template-retail-react-app does not specify a mode and only specifies a callbackURI. Let's make sure our changes in commerce-sdk-react are backwards compatible!
This ensures when mode is missing but callbackURI is set in default.js, callback mode is used

            passwordless: {
                enabled: true,
                callbackURI: 'https://webhook.site/e6f88064-36bc-4605-8128-a94810bd4318',
                landingPath: '/passwordless-login-landing'
            },
  1. Checkout this test branch that contains the commerce-sdk-react changes and sets up template-retail-react-app with a private client and start the app
    git checkout W-20279798-j.ha-test-commerce-sdk-react-email-otp-backward-compatibility
    
    # Build commerce-sdk-react locally by building the entire app
    npm ci
    
    # Set the private client secret and a test webhook callback URI via env vars and start the `template-retail-react-app`
    export PWA_KIT_SLAS_CLIENT_SECRET=SECRET
    export PASSWORDLESS_LOGIN_CALLBACK_URI=https://webhook.site/e6f88064-36bc-4605-8128-a94810bd4318
    cd packages/template-retail-react-app
    npm start
    
  2. Once the app has started, login using the Continue Securely button after entering your email to trigger passwordless login
  3. Verify the Check your email screen is shown
    Screenshot 2025-12-05 at 9 57 50 AM
  4. Verify SLAS sent a POST request to the webhook callback uri: https://webhook.site/#!/view/e6f88064-36bc-4605-8128-a94810bd4318

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)

@cc-prodsec
Copy link
Collaborator

cc-prodsec commented Dec 3, 2025

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/email-otp December 4, 2025 21:21
…Commerce API parameters to test with staging-001
… update Commerce API parameters to test with staging-001"

This reverts commit 0f3f211.
organizationId,
shortCode,
siteId,
locale,
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 locale that is passed to the authorizePasswordless endpoint is the one associated to the current site in config/sites.js

For example,
http://localhost:3000/us/ sets locale to en-US
http://localhost:3000/global sets locale to en-GB
http://localhost:3000/us/en-CA sets locale to en-CA

@hajinsuha1 hajinsuha1 marked this pull request as ready for review December 5, 2025 15:53
@hajinsuha1 hajinsuha1 requested a review from a team as a code owner December 5, 2025 15:53
@hajinsuha1
Copy link
Collaborator Author

hajinsuha1 commented Dec 5, 2025

note I'll update the .hbs files in a separate ticket to keep the testing/changes small: https://gus.lightning.force.com/lightning/r/ADM_Work__c/a07EE00002QhntzYAB/view

Comment on lines +1268 to +1270
const mode = parameters.mode || 'callback'
const callbackURI = parameters.callbackURI || this.passwordlessLoginCallbackURI
const finalMode = callbackURI ? 'callback' : parameters.mode || 'sms'
const locale = this.locale
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

simplified mode selection to respect user's explicit mode choice while still defaulting to callback mode for backward compatibility

@jeremy-jung1
Copy link
Collaborator

jeremy-jung1 commented Dec 9, 2025

When clicking on the link after initiating passwordless login in en-US, it goes to the en-GB passwordless login landing page. It may be beneficial for the locale to be included in the link in the template, so the language stays consistent.

Unfortunately it seems currently the template API in SLAS uses the same link for all locales, making it difficult to have a unique link with the /global/{locale} for each locale. This is a hard database schema relationship of 1 link to many templates, so this change would need an overhaul of the current schema for password action template. I'll look into what work this would be on SLAS side to allow link to be unique to each locale, but would appreciate to know if there are solutions on PWA Kit side as well:
A) Maybe in the template we can include a query parameter like ${link}&locale=ko-KR and make the locale consistent that way?
B) Or is locale stored in browser settings?

Also, if we're going to use the way of including /global/{locale} in the link to make the language consistent, I think I'm noticing an issue in PWA Kit where the call to /shopper/auth/v1/organizations/f_ecom_zzrf_001/oauth2/passwordless/token is not being made if that part of the URL exists, e.g. http://localhost:3000/global/ko-KR/passwordless-login-landing?token=11111111. Not sure if that is a bug, but if it is and there is no other way we would need to fix it

…, update Commerce API parameters to test with staging-001"

This reverts commit 66bcafa.
@hajinsuha1
Copy link
Collaborator Author

hajinsuha1 commented Dec 9, 2025

When clicking on the link after initiating passwordless login in en-US, it goes to the en-GB passwordless login landing page. It may be beneficial for the locale to be included in the link in the template, so the language stays consistent.

Unfortunately it seems currently the template API in SLAS uses the same link for all locales, making it difficult to have a unique link with the /global/{locale} for each locale. This is a hard database schema relationship of 1 link to many templates, so this change would need an overhaul of the current schema for password action template. I'll look into what work this would be on SLAS side to allow link to be unique to each locale, but would appreciate to know if there are solutions on PWA Kit side as well: A) Maybe in the template we can include a query parameter like ${link}&locale=ko-KR and make the locale consistent that way? B) Or is locale stored in browser settings?

Also, if we're going to use the way of including /global/{locale} in the link to make the language consistent, I think I'm noticing an issue in PWA Kit where the call to /shopper/auth/v1/organizations/f_ecom_zzrf_001/oauth2/passwordless/token is not being made if that part of the URL exists, e.g. http://localhost:3000/global/ko-KR/passwordless-login-landing?token=11111111. Not sure if that is a bug, but if it is and there is no other way we would need to fix it

@jeremy-jung1 Thanks for catching this!
So yes we can make it work from the PWA side. I've pushed a fix to allow the /passwordless-login-landing path to support localized url like /global/ko-KR/passwordless-login-landing.
Now what a merchant would need to do is setup their password-action-templates in SLAS Admin like so where

  • link is set to the base URL of the site
  • the template has the path to the /password-login-landing path prefixed with the localized path (e.g., /us/en-CA/, /global/ko-KR/)
# Set template for en-CA in RefArch
curl --location --request PUT 'https://staging-001.api.commercecloud.salesforce.com/shopper/auth-admin/v1/tenants/zzrf_001/clients/bb1e8c16-7767-4ed8-bc5d-83efc59a208a/password-action-templates \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer xxx' \
--data '{
    "channelId": "RefArch",
    "name": "Password Template",
    "locale": "en-CA",
    "subject": "Your one time verification code",
    "actionType": "PWDLESS_LOGIN",
    "templateType": "EMAIL",
    "link": "https://wasatch-mrt-passwordless-test.mrt-storefront-staging.com", 
    "template": "[en-CA] Your one time verification code is ${token}\nHere is the link to login: ${link}/us/en-CA/passwordless-login-landing?token=${token}"
}'

# Set template for en-GB in RefArchGlobal
curl --location --request PUT 'https://staging-001.api.commercecloud.salesforce.com/shopper/auth-admin/v1/tenants/zzrf_001/clients/bb1e8c16-7767-4ed8-bc5d-83efc59a208a/password-action-templates \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer xxx' \
--data '{
    "channelId": "RefArchGlobal",
    "name": "Password Template",
    "locale": "en-GB",
    "subject": "Your one time verification code",
    "actionType": "PWDLESS_LOGIN",
    "templateType": "EMAIL",
    "link": "https://wasatch-mrt-passwordless-test.mrt-storefront-staging.com", 
    "template": "[en-GB] Your one time verification code is ${token}\nHere is the link to login: ${link}/passwordless-login-landing?token=${token}"
}'

# Set template for ko-KR in RefArchGlobal
curl --location --request PUT 'https://staging-001.api.commercecloud.salesforce.com/shopper/auth-admin/v1/tenants/zzrf_001/clients/bb1e8c16-7767-4ed8-bc5d-83efc59a208a/password-action-templates \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer xxx' \
--data '{
    "channelId": "RefArch",
    "name": "Password Template",
    "locale": "ko-KR",
    "subject": "Your one time verification code",
    "actionType": "PWDLESS_LOGIN",
    "templateType": "EMAIL",
    "link": "https://wasatch-mrt-passwordless-test.mrt-storefront-staging.com", 
    "template": "[ko-KR] [소매점용 React PWA 스타터 스토어] Your one time verification code is ${token}\nHere is the link to login: ${link}/global/ko-KR/passwordless-login-landing?token=${token}"
}'

This can be tested on this deployed instance:

hajinsuha1 and others added 3 commits December 9, 2025 13:42
…ail mode, update Commerce API parameters to test with staging-001""

This reverts commit 465b813.
Copy link
Collaborator

@jeremy-jung1 jeremy-jung1 left a comment

Choose a reason for hiding this comment

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

Followed the test steps and things are working as expected

@hajinsuha1 hajinsuha1 merged commit 7877887 into feature/email-otp Dec 10, 2025
39 of 40 checks passed
@hajinsuha1 hajinsuha1 deleted the W-20279798-support-setting-passwordless-login-mode-in-config branch December 10, 2025 14:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants