diff --git a/packages/auth/__tests__/providers/cognito/signInWithRedirect.test.ts b/packages/auth/__tests__/providers/cognito/signInWithRedirect.test.ts index 0714c091278..9e8b285a7ed 100644 --- a/packages/auth/__tests__/providers/cognito/signInWithRedirect.test.ts +++ b/packages/auth/__tests__/providers/cognito/signInWithRedirect.test.ts @@ -25,6 +25,7 @@ import { signInWithRedirect } from '../../../src/providers/cognito/apis/signInWi import type { OAuthStore } from '../../../src/providers/cognito/utils/types'; import { mockAuthConfigWithOAuth } from '../../mockData'; +const mockUrlOpener = jest.fn(); jest.mock('@aws-amplify/core/internals/utils', () => ({ ...jest.requireActual('@aws-amplify/core/internals/utils'), assertOAuthConfig: jest.fn(), @@ -39,7 +40,22 @@ jest.mock('@aws-amplify/core', () => { return { Amplify: { - getConfig: jest.fn(() => mockAuthConfigWithOAuth), + getConfig: jest.fn(() => ({ + ...mockAuthConfigWithOAuth, + Auth: { + ...mockAuthConfigWithOAuth.Auth, + Cognito: { + ...mockAuthConfigWithOAuth.Auth?.Cognito, + loginWith: { + ...mockAuthConfigWithOAuth.Auth?.Cognito?.loginWith, + oauth: { + ...mockAuthConfigWithOAuth.Auth?.Cognito?.loginWith?.oauth, + urlOpener: mockUrlOpener, + }, + }, + }, + }, + })), [ACTUAL_ADD_OAUTH_LISTENER]: jest.fn(), }, ConsoleLogger: jest.fn().mockImplementation(() => { @@ -129,6 +145,7 @@ describe('signInWithRedirect', () => { mockToCodeChallenge.mockClear(); mockHandleFailure.mockClear(); mockCompleteOAuthFlow.mockClear(); + mockUrlOpener.mockClear(); (oAuthStore.setAuthConfig as jest.Mock).mockClear(); (oAuthStore.storeOAuthInFlight as jest.Mock).mockClear(); @@ -189,6 +206,11 @@ describe('signInWithRedirect', () => { expect(mockUrlSafeEncode).toHaveBeenCalledWith(expectedCustomState); }); + it('uses custom url opener if specified', async () => { + await signInWithRedirect(); + expect(mockUrlOpener).toHaveBeenCalled(); + }); + describe('specifications on Web', () => { describe('side effect', () => { it('attaches oauth listener to the Amplify singleton', async () => { diff --git a/packages/auth/src/providers/cognito/apis/signInWithRedirect.ts b/packages/auth/src/providers/cognito/apis/signInWithRedirect.ts index bac92589dc8..7c0a694a423 100644 --- a/packages/auth/src/providers/cognito/apis/signInWithRedirect.ts +++ b/packages/auth/src/providers/cognito/apis/signInWithRedirect.ts @@ -80,7 +80,8 @@ const oauthSignIn = async ({ preferPrivateSession?: boolean; options?: SignInWithRedirectInput['options']; }) => { - const { domain, redirectSignIn, responseType, scopes } = oauthConfig; + const { domain, redirectSignIn, responseType, scopes, urlOpener } = + oauthConfig; const { loginHint, lang, nonce } = options ?? {}; const randomState = generateState(); @@ -130,8 +131,12 @@ const oauthSignIn = async ({ // the following is effective only in react-native as openAuthSession resolves only in react-native const { type, error, url } = - (await openAuthSession(oAuthUrl, redirectSignIn, preferPrivateSession)) ?? - {}; + (await openAuthSession( + oAuthUrl, + redirectSignIn, + preferPrivateSession, + urlOpener, + )) ?? {}; try { if (type === 'error') { diff --git a/packages/auth/src/utils/openAuthSession.ts b/packages/auth/src/utils/openAuthSession.ts index 0fc28f89f19..b3a78381a9d 100644 --- a/packages/auth/src/utils/openAuthSession.ts +++ b/packages/auth/src/utils/openAuthSession.ts @@ -3,10 +3,21 @@ import { OpenAuthSession } from './types'; -export const openAuthSession: OpenAuthSession = async (url: string) => { +export const openAuthSession: OpenAuthSession = async ( + url: string, + _redirectUrls: string[], + _preferPrivateSession?: boolean, + urlOpener: (_url: string) => Promise = async (_url: string) => { + window.location.href = _url; + }, +) => { if (!window?.location) { return; } + // enforce HTTPS - window.location.href = url.replace('http://', 'https://'); + const secureUrl = url.replace('http://', 'https://'); + + // Call the provided or default urlOpener + await urlOpener(secureUrl); }; diff --git a/packages/auth/src/utils/types.ts b/packages/auth/src/utils/types.ts index 4a2ddc53ac9..dd0897ca4fc 100644 --- a/packages/auth/src/utils/types.ts +++ b/packages/auth/src/utils/types.ts @@ -5,6 +5,7 @@ export type OpenAuthSession = ( url: string, redirectUrls: string[], preferPrivateSession?: boolean, + urlOpener?: (url: string) => Promise, ) => Promise; type OpenAuthSessionResultType = 'canceled' | 'success' | 'error'; diff --git a/packages/core/src/singleton/Auth/types.ts b/packages/core/src/singleton/Auth/types.ts index fbda92b235d..b03107bc921 100644 --- a/packages/core/src/singleton/Auth/types.ts +++ b/packages/core/src/singleton/Auth/types.ts @@ -181,6 +181,7 @@ export interface OAuthConfig { redirectSignOut: string[]; responseType: 'code' | 'token'; providers?: (OAuthProvider | CustomProvider)[]; + urlOpener?: (url: string) => Promise } export type OAuthProvider = 'Google' | 'Facebook' | 'Amazon' | 'Apple';