Skip to content

Commit 9cec46e

Browse files
authored
Merge branch 'develop' into W-20448811-shopper-can-manually-enter-otp-in-login-flows-2
Signed-off-by: Jinsu Ha <91205717+hajinsuha1@users.noreply.github.com>
2 parents b542c8d + 5f9738e commit 9cec46e

File tree

43 files changed

+231
-36
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

43 files changed

+231
-36
lines changed

packages/pwa-kit-create-app/CHANGELOG.md

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
## v3.16.0-dev (Dec 17, 2025)
22
- Add new One-Click Checkout configuration [#3609](https://github.com/SalesforceCommerceCloud/pwa-kit/pull/3609)
3-
4-
## v3.15.0-dev (Nov 05, 2025)
53
- Support email mode by default for passwordless login and password reset in a generated app. [#3525](https://github.com/SalesforceCommerceCloud/pwa-kit/pull/3525)
4+
- Util function for passwordless callback URI [#3630](https://github.com/SalesforceCommerceCloud/pwa-kit/pull/3630)
65
- Add `tokenLength` to login configuration [#3554](https://github.com/SalesforceCommerceCloud/pwa-kit/pull/3554)
76

87
## v3.15.0 (Dec 17, 2025)

packages/pwa-kit-create-app/assets/bootstrap/js/overrides/app/components/_app-config/index.jsx.hbs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,9 @@ import {
2222
getEnvBasePath,
2323
slasPrivateProxyPath
2424
} from '@salesforce/pwa-kit-runtime/utils/ssr-namespace-paths'
25-
import {absoluteUrl, createUrlTemplate} from '@salesforce/retail-react-app/app/utils/url'
25+
import {createUrlTemplate} from '@salesforce/retail-react-app/app/utils/url'
2626
import createLogger from '@salesforce/pwa-kit-runtime/utils/logger-factory'
27+
import {getPasswordlessCallbackUrl} from '@salesforce/retail-react-app/app/utils/auth-utils'
2728

2829
import {CommerceApiProvider} from '@salesforce/commerce-sdk-react'
2930
import {withReactQuery} from '@salesforce/pwa-kit-react-sdk/ssr/universal/components/with-react-query'
@@ -62,8 +63,9 @@ const AppConfig = ({children, locals = {}}) => {
6263
const commerceApiConfig = locals.appConfig.commerceAPI
6364

6465
const appOrigin = getAppOrigin()
65-
66-
const passwordlessCallback = locals.appConfig.login?.passwordless?.callbackURI
66+
const passwordlessCallbackURI = getPasswordlessCallbackUrl(
67+
locals.appConfig.login?.passwordless?.callbackURI
68+
)
6769

6870
const storeLocatorConfig = {
6971
radius: STORE_LOCATOR_RADIUS,
@@ -79,7 +81,6 @@ const AppConfig = ({children, locals = {}}) => {
7981
const redirectURI = `${appOrigin}${getEnvBasePath()}/callback`
8082
const proxy = `${appOrigin}${getEnvBasePath()}${commerceApiConfig.proxyPath}`
8183
const slasPrivateClientProxyEndpoint = `${appOrigin}${getEnvBasePath()}${slasPrivateProxyPath}`
82-
const passwordlessLoginCallbackURI = absoluteUrl(passwordlessCallback, appOrigin)
8384

8485
return (
8586
<CommerceApiProvider
@@ -94,7 +95,7 @@ const AppConfig = ({children, locals = {}}) => {
9495
headers={headers}
9596
defaultDnt={DEFAULT_DNT_STATE}
9697
logger={createLogger({packageName: 'commerce-sdk-react'})}
97-
passwordlessLoginCallbackURI={passwordlessLoginCallbackURI}
98+
passwordlessLoginCallbackURI={passwordlessCallbackURI}
9899
// Set 'enablePWAKitPrivateClient' to true to use SLAS private client login flows.
99100
// Make sure to also enable useSLASPrivateClient in ssr.js when enabling this setting.
100101
{{#if answers.project.commerce.isSlasPrivate}}

packages/pwa-kit-create-app/assets/templates/@salesforce/retail-react-app/app/components/_app-config/index.jsx.hbs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,9 @@ import {
2323
getEnvBasePath,
2424
slasPrivateProxyPath
2525
} from '@salesforce/pwa-kit-runtime/utils/ssr-namespace-paths'
26-
import {absoluteUrl, createUrlTemplate} from '@salesforce/retail-react-app/app/utils/url'
26+
import {createUrlTemplate} from '@salesforce/retail-react-app/app/utils/url'
2727
import createLogger from '@salesforce/pwa-kit-runtime/utils/logger-factory'
28+
import {getPasswordlessCallbackUrl} from '@salesforce/retail-react-app/app/utils/auth-utils'
2829

2930
import {CommerceApiProvider} from '@salesforce/commerce-sdk-react'
3031
import {withReactQuery} from '@salesforce/pwa-kit-react-sdk/ssr/universal/components/with-react-query'
@@ -63,7 +64,9 @@ const AppConfig = ({children, locals = {}}) => {
6364

6465
const appOrigin = useAppOrigin()
6566

66-
const passwordlessCallback = locals.appConfig.login?.passwordless?.callbackURI
67+
const passwordlessCallbackURI = getPasswordlessCallbackUrl(
68+
locals.appConfig.login?.passwordless?.callbackURI
69+
)
6770

6871
const storeLocatorConfig = {
6972
radius: STORE_LOCATOR_RADIUS,
@@ -79,7 +82,6 @@ const AppConfig = ({children, locals = {}}) => {
7982
const redirectURI = `${appOrigin}${getEnvBasePath()}/callback`
8083
const proxy = `${appOrigin}${getEnvBasePath()}${commerceApiConfig.proxyPath}`
8184
const slasPrivateClientProxyEndpoint = `${appOrigin}${getEnvBasePath()}${slasPrivateProxyPath}`
82-
const passwordlessLoginCallbackURI = absoluteUrl(passwordlessCallback, appOrigin)
8385

8486
return (
8587
<CommerceApiProvider
@@ -94,7 +96,7 @@ const AppConfig = ({children, locals = {}}) => {
9496
headers={headers}
9597
defaultDnt={DEFAULT_DNT_STATE}
9698
logger={createLogger({packageName: 'commerce-sdk-react'})}
97-
passwordlessLoginCallbackURI={passwordlessLoginCallbackURI}
99+
passwordlessLoginCallbackURI={passwordlessCallbackURI}
98100
// Set 'enablePWAKitPrivateClient' to true to use SLAS private client login flows.
99101
// Make sure to also enable useSLASPrivateClient in ssr.js when enabling this setting.
100102
{{#if answers.project.commerce.isSlasPrivate}}

packages/template-retail-react-app/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
- BOPIS multishipment with OMS [#3613] (https://github.com/SalesforceCommerceCloud/pwa-kit/pull/3613)
1212
- [Feature] Update passwordless login and password reset to use email mode by default. The mode can now be configured across the login page, auth modal, and checkout page [#3525](https://github.com/SalesforceCommerceCloud/pwa-kit/pull/3525)
1313
- Update "Continue Securely" button text to "Continue" for passwordless login [#3556](https://github.com/SalesforceCommerceCloud/pwa-kit/pull/3556)
14+
- Util function for passwordless callback URI [#3630](https://github.com/SalesforceCommerceCloud/pwa-kit/pull/3630)
1415
- Allow shopper to manually input OTP during passwordless login [#3554](https://github.com/SalesforceCommerceCloud/pwa-kit/pull/3554)
1516

1617
## v8.3.0 (Dec 17, 2025)

packages/template-retail-react-app/app/components/_app-config/index.jsx

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,9 @@ import {
3232
getEnvBasePath,
3333
slasPrivateProxyPath
3434
} from '@salesforce/pwa-kit-runtime/utils/ssr-namespace-paths'
35-
import {absoluteUrl, createUrlTemplate} from '@salesforce/retail-react-app/app/utils/url'
35+
import {createUrlTemplate} from '@salesforce/retail-react-app/app/utils/url'
3636
import createLogger from '@salesforce/pwa-kit-runtime/utils/logger-factory'
37+
import {getPasswordlessCallbackUrl} from '@salesforce/retail-react-app/app/utils/auth-utils'
3738

3839
import {CommerceApiProvider} from '@salesforce/commerce-sdk-react'
3940
import {withReactQuery} from '@salesforce/pwa-kit-react-sdk/ssr/universal/components/with-react-query'
@@ -72,7 +73,9 @@ const AppConfig = ({children, locals = {}}) => {
7273

7374
const appOrigin = useAppOrigin()
7475

75-
const passwordlessCallback = locals.appConfig.login?.passwordless?.callbackURI
76+
const passwordlessCallbackURI = getPasswordlessCallbackUrl(
77+
locals.appConfig.login?.passwordless?.callbackURI
78+
)
7679

7780
const storeLocatorConfig = {
7881
radius: STORE_LOCATOR_RADIUS,
@@ -88,7 +91,6 @@ const AppConfig = ({children, locals = {}}) => {
8891
const redirectURI = `${appOrigin}${getEnvBasePath()}/callback`
8992
const proxy = `${appOrigin}${getEnvBasePath()}${commerceApiConfig.proxyPath}`
9093
const slasPrivateClientProxyEndpoint = `${appOrigin}${getEnvBasePath()}${slasPrivateProxyPath}`
91-
const passwordlessLoginCallbackURI = absoluteUrl(passwordlessCallback, appOrigin)
9294

9395
return (
9496
<CommerceApiProvider
@@ -99,7 +101,7 @@ const AppConfig = ({children, locals = {}}) => {
99101
locale={locals.locale?.id}
100102
currency={locals.locale?.preferredCurrency}
101103
redirectURI={redirectURI}
102-
passwordlessLoginCallbackURI={passwordlessLoginCallbackURI}
104+
passwordlessLoginCallbackURI={passwordlessCallbackURI}
103105
proxy={proxy}
104106
headers={headers}
105107
defaultDnt={DEFAULT_DNT_STATE}

packages/template-retail-react-app/app/hooks/use-auth-modal.js

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ import {usePrevious} from '@salesforce/retail-react-app/app/hooks/use-previous'
4343
import {usePasswordReset} from '@salesforce/retail-react-app/app/hooks/use-password-reset'
4444
import {isServer} from '@salesforce/retail-react-app/app/utils/utils'
4545
import {getConfig} from '@salesforce/pwa-kit-runtime/utils/ssr-config'
46-
import {absoluteUrl} from '@salesforce/retail-react-app/app/utils/url'
46+
import {getPasswordlessCallbackUrl} from '@salesforce/retail-react-app/app/utils/auth-utils'
4747
import useMultiSite from '@salesforce/retail-react-app/app/hooks/use-multi-site'
4848

4949
export const LOGIN_VIEW = 'login'
@@ -92,9 +92,8 @@ export const AuthModal = ({
9292
const authorizePasswordlessLogin = useAuthHelper(AuthHelpers.AuthorizePasswordless)
9393
const loginPasswordless = useAuthHelper(AuthHelpers.LoginPasswordlessUser)
9494
const passwordlessConfig = getConfig().app.login?.passwordless
95-
const passwordlessConfigCallback = passwordlessConfig?.callbackURI
9695
const passwordlessMode = passwordlessConfig?.mode
97-
const callbackURL = absoluteUrl(passwordlessConfigCallback)
96+
const callbackURL = getPasswordlessCallbackUrl(passwordlessConfig?.callbackURI)
9897

9998
const {data: baskets} = useCustomerBaskets(
10099
{parameters: {customerId}},

packages/template-retail-react-app/app/hooks/use-password-reset.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import {useToast} from '@salesforce/retail-react-app/app/hooks/use-toast'
99
import {useIntl} from 'react-intl'
1010
import {getConfig} from '@salesforce/pwa-kit-runtime/utils/ssr-config'
1111
import useMultiSite from '@salesforce/retail-react-app/app/hooks/use-multi-site'
12-
import {absoluteUrl} from '@salesforce/retail-react-app/app/utils/url'
12+
import {getPasswordlessCallbackUrl} from '@salesforce/retail-react-app/app/utils/auth-utils'
1313

1414
/**
1515
* This hook provides commerce-react-sdk hooks to simplify the reset password flow.
@@ -19,8 +19,8 @@ export const usePasswordReset = () => {
1919
const {formatMessage} = useIntl()
2020
const {locale} = useMultiSite()
2121
const config = getConfig().app.login?.resetPassword
22-
const callbackURI = absoluteUrl(config?.callbackURI)
2322
const resetPasswordLandingPath = config?.landingPath
23+
const callbackURI = getPasswordlessCallbackUrl(config?.callbackURI)
2424

2525
const getPasswordResetTokenMutation = useAuthHelper(AuthHelpers.GetPasswordResetToken)
2626
const resetPasswordMutation = useAuthHelper(AuthHelpers.ResetPassword)

packages/template-retail-react-app/app/pages/checkout-one-click/partials/one-click-contact-info.jsx

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -53,8 +53,8 @@ import {formatPhoneNumber} from '@salesforce/retail-react-app/app/utils/phone-ut
5353
import useMultiSite from '@salesforce/retail-react-app/app/hooks/use-multi-site'
5454
import {isPickupShipment} from '@salesforce/retail-react-app/app/utils/shipment-utils'
5555
import {getConfig} from '@salesforce/pwa-kit-runtime/utils/ssr-config'
56-
import {absoluteUrl} from '@salesforce/retail-react-app/app/utils/url'
5756
import {useLocation} from 'react-router-dom'
57+
import {getPasswordlessCallbackUrl} from '@salesforce/retail-react-app/app/utils/auth-utils'
5858

5959
const ContactInfo = ({isSocialEnabled = false, idps = [], onRegisteredUserChoseGuest}) => {
6060
const {formatMessage} = useIntl()
@@ -75,9 +75,7 @@ const ContactInfo = ({isSocialEnabled = false, idps = [], onRegisteredUserChoseG
7575
const loginPasswordless = useAuthHelper(AuthHelpers.LoginPasswordlessUser)
7676
const {locale} = useMultiSite()
7777
const passwordlessConfig = getConfig().app.login?.passwordless
78-
const callbackURL = passwordlessConfig?.callbackURI
79-
? absoluteUrl(passwordlessConfig.callbackURI)
80-
: ''
78+
const callbackURL = getPasswordlessCallbackUrl(passwordlessConfig?.callbackURI)
8179
const redirectPath = location.pathname + location.search
8280

8381
const {step, STEPS, goToStep, goToNextStep, setContactPhone} = useCheckout()

packages/template-retail-react-app/app/pages/checkout/partials/contact-info.jsx

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,10 @@ import {useCurrentCustomer} from '@salesforce/retail-react-app/app/hooks/use-cur
4343
import {useCurrentBasket} from '@salesforce/retail-react-app/app/hooks/use-current-basket'
4444
import {AuthHelpers, useAuthHelper, useShopperBasketsMutation} from '@salesforce/commerce-sdk-react'
4545
import {getConfig} from '@salesforce/pwa-kit-runtime/utils/ssr-config'
46-
import {absoluteUrl} from '@salesforce/retail-react-app/app/utils/url'
47-
import {getAuthorizePasswordlessErrorMessage} from '@salesforce/retail-react-app/app/utils/auth-utils'
46+
import {
47+
getPasswordlessCallbackUrl,
48+
getAuthorizePasswordlessErrorMessage
49+
} from '@salesforce/retail-react-app/app/utils/auth-utils'
4850
import useMultiSite from '@salesforce/retail-react-app/app/hooks/use-multi-site'
4951

5052
const ContactInfo = ({isSocialEnabled = false, isPasswordlessEnabled = false, idps = []}) => {
@@ -76,8 +78,7 @@ const ContactInfo = ({isSocialEnabled = false, isPasswordlessEnabled = false, id
7678
const authModal = useAuthModal(authModalView)
7779
const passwordlessConfig = getConfig().app.login?.passwordless
7880
const passwordlessConfigMode = passwordlessConfig?.mode
79-
const passwordlessConfigCallback = passwordlessConfig?.callbackURI
80-
const callbackURL = absoluteUrl(passwordlessConfigCallback)
81+
const callbackURL = getPasswordlessCallbackUrl(passwordlessConfig?.callbackURI)
8182

8283
const handlePasswordlessLogin = async (email) => {
8384
try {

packages/template-retail-react-app/app/pages/login/index.jsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,10 +32,10 @@ import {isServer, noop} from '@salesforce/retail-react-app/app/utils/utils'
3232
import {
3333
getAuthorizePasswordlessErrorMessage,
3434
getLoginPasswordlessErrorMessage
35+
getPasswordlessCallbackUrl
3536
} from '@salesforce/retail-react-app/app/utils/auth-utils'
3637
import {getConfig} from '@salesforce/pwa-kit-runtime/utils/ssr-config'
3738
import useMultiSite from '@salesforce/retail-react-app/app/hooks/use-multi-site'
38-
import {absoluteUrl} from '@salesforce/retail-react-app/app/utils/url'
3939

4040
const LOGIN_ERROR_MESSAGE = defineMessage({
4141
defaultMessage: 'Incorrect username or password, please try again.',
@@ -63,7 +63,8 @@ const Login = ({initialView = LOGIN_VIEW}) => {
6363
const isPasswordlessEnabled = !!passwordless?.enabled
6464
const passwordlessMode = passwordless?.mode
6565
const passwordlessLoginLandingPath = passwordless?.landingPath
66-
const passwordlessConfigCallback = absoluteUrl(passwordless?.callbackURI)
66+
67+
const passwordlessConfigCallback = getPasswordlessCallbackUrl(passwordless?.callbackURI)
6768

6869
const isSocialEnabled = !!social?.enabled
6970
const idps = social?.idps

0 commit comments

Comments
 (0)