diff --git a/.changeset/hungry-bobcats-change.md b/.changeset/hungry-bobcats-change.md new file mode 100644 index 00000000000..e90e445845e --- /dev/null +++ b/.changeset/hungry-bobcats-change.md @@ -0,0 +1,5 @@ +--- +'@shopify/theme': patch +--- + +Fix password validation to support localized URLs when authenticating storefronts. diff --git a/packages/theme/src/cli/utilities/theme-environment/storefront-session.test.ts b/packages/theme/src/cli/utilities/theme-environment/storefront-session.test.ts index 5d5615b0d28..49da135dce4 100644 --- a/packages/theme/src/cli/utilities/theme-environment/storefront-session.test.ts +++ b/packages/theme/src/cli/utilities/theme-environment/storefront-session.test.ts @@ -237,6 +237,24 @@ describe('Storefront API', () => { }) }) + test('returns true when the password is correct and the store redirects to a localized URL', async () => { + // Given + vi.mocked(fetch).mockResolvedValueOnce( + response({ + status: 302, + headers: { + location: 'https://store.myshopify.com/en', + }, + }), + ) + + // When + const result = await isStorefrontPasswordCorrect('correct-password', 'store.myshopify.com') + + // Then + expect(result).toBe(true) + }) + test('returns true when the password is correct and the store name is capitalized', async () => { // Given vi.mocked(fetch).mockResolvedValueOnce( @@ -297,6 +315,24 @@ describe('Storefront API', () => { expect(result).toBe(false) }) + test('returns false when the redirect location has a different origin', async () => { + // Given + vi.mocked(fetch).mockResolvedValueOnce( + response({ + status: 302, + headers: { + location: 'https://another-store.myshopify.com/', + }, + }), + ) + + // When + const result = await isStorefrontPasswordCorrect('correct-password', 'store.myshopify.com') + + // Then + expect(result).toBe(false) + }) + test('throws an error when the server responds with "Too Many Requests"', async () => { // Given vi.mocked(fetch).mockResolvedValueOnce( diff --git a/packages/theme/src/cli/utilities/theme-environment/storefront-session.ts b/packages/theme/src/cli/utilities/theme-environment/storefront-session.ts index 40c68e12e93..32cc452dae9 100644 --- a/packages/theme/src/cli/utilities/theme-environment/storefront-session.ts +++ b/packages/theme/src/cli/utilities/theme-environment/storefront-session.ts @@ -45,9 +45,21 @@ export async function isStorefrontPasswordCorrect(password: string | undefined, ) } - const isValidRedirect = new RegExp(`^${storeUrl}/?$`, 'i') + const locationHeader = response.headers.get('location') ?? '' + let redirectUrl: URL + + try { + redirectUrl = new URL(locationHeader, storeUrl) + } catch (error) { + if (error instanceof TypeError) { + return false + } + throw error + } + + const storeOrigin = new URL(storeUrl).origin - return response.status === 302 && isValidRedirect.test(response.headers.get('location') ?? '') + return response.status === 302 && redirectUrl.origin === storeOrigin } export async function getStorefrontSessionCookies(