@@ -12,7 +12,10 @@ import {
12
12
13
13
import '../utils/oauth/enableOAuthListener' ;
14
14
import { cognitoHostedUIIdentityProviderMap } from '../types/models' ;
15
- import { getAuthUserAgentValue , openAuthSession } from '../../../utils' ;
15
+ import {
16
+ openAuthSession as _openAuthSession ,
17
+ getAuthUserAgentValue ,
18
+ } from '../../../utils' ;
16
19
import { assertUserNotAuthenticated } from '../utils/signInHelpers' ;
17
20
import { SignInWithRedirectInput } from '../types' ;
18
21
import {
@@ -25,6 +28,7 @@ import {
25
28
} from '../utils/oauth' ;
26
29
import { createOAuthError } from '../utils/oauth/createOAuthError' ;
27
30
import { listenForOAuthFlowCancellation } from '../utils/oauth/cancelOAuthFlow' ;
31
+ import { OpenAuthSession } from '../../../utils/types' ;
28
32
29
33
/**
30
34
* Signs in a user with OAuth. Redirects the application to an Identity Provider.
@@ -66,6 +70,7 @@ export async function signInWithRedirect(
66
70
nonce : input ?. options ?. nonce ,
67
71
prompt : input ?. options ?. prompt ,
68
72
} ,
73
+ authSessionOpener : input ?. options ?. authSessionOpener ,
69
74
} ) ;
70
75
}
71
76
@@ -76,17 +81,20 @@ const oauthSignIn = async ({
76
81
customState,
77
82
preferPrivateSession,
78
83
options,
84
+ authSessionOpener,
79
85
} : {
80
86
oauthConfig : OAuthConfig ;
81
87
provider : string ;
82
88
clientId : string ;
83
89
customState ?: string ;
84
90
preferPrivateSession ?: boolean ;
85
91
options ?: SignInWithRedirectInput [ 'options' ] ;
92
+ authSessionOpener ?: OpenAuthSession ;
86
93
} ) => {
87
94
const { domain, redirectSignIn, responseType, scopes } = oauthConfig ;
88
95
const { loginHint, lang, nonce, prompt } = options ?? { } ;
89
96
const randomState = generateState ( ) ;
97
+ const openAuthSession = authSessionOpener || _openAuthSession ;
90
98
91
99
/* encodeURIComponent is not URL safe, use urlSafeEncode instead. Cognito
92
100
single-encodes/decodes url on first sign in and double-encodes/decodes url
@@ -105,28 +113,25 @@ const oauthSignIn = async ({
105
113
oAuthStore . storeOAuthState ( state ) ;
106
114
oAuthStore . storePKCE ( value ) ;
107
115
108
- const queryString = Object . entries ( {
109
- redirect_uri : redirectUri ,
110
- response_type : responseType ,
111
- client_id : clientId ,
112
- identity_provider : provider ,
113
- scope : scopes . join ( ' ' ) ,
114
- // eslint-disable-next-line camelcase
115
- ...( loginHint && { login_hint : loginHint } ) ,
116
- ...( lang && { lang } ) ,
117
- ...( nonce && { nonce } ) ,
118
- ...( prompt && { prompt : prompt . toLowerCase ( ) } ) , // Cognito expects lowercase prompt values
119
- state,
120
- ...( responseType === 'code' && {
121
- code_challenge : toCodeChallenge ( ) ,
122
- code_challenge_method : method ,
123
- } ) ,
124
- } )
125
- . map ( ( [ k , v ] ) => `${ encodeURIComponent ( k ) } =${ encodeURIComponent ( v ) } ` )
126
- . join ( '&' ) ;
127
-
128
- // TODO(v6): use URL object instead
129
- const oAuthUrl = `https://${ domain } /oauth2/authorize?${ queryString } ` ;
116
+ const params = new URLSearchParams ( [
117
+ [ 'redirect_uri' , redirectUri ] ,
118
+ [ 'response_type' , responseType ] ,
119
+ [ 'client_id' , clientId ] ,
120
+ [ 'identity_provider' , provider ] ,
121
+ [ 'scope' , scopes . join ( ' ' ) ] ,
122
+ ] ) ;
123
+
124
+ loginHint && params . append ( 'login_hint' , loginHint ) ;
125
+ lang && params . append ( 'lang' , lang ) ;
126
+ nonce && params . append ( 'nonce' , nonce ) ;
127
+ prompt && params . append ( 'prompt' , prompt . toLowerCase ( ) ) ;
128
+ params . append ( 'state' , state ) ;
129
+ if ( responseType === 'code' ) {
130
+ params . append ( 'code_challenge' , toCodeChallenge ( ) ) ;
131
+ params . append ( 'code_challenge_method' , method ) ;
132
+ }
133
+ const oAuthUrl = new URL ( '/oauth2/authorize' , `https://${ domain } /` ) ;
134
+ oAuthUrl . search = params . toString ( ) ;
130
135
131
136
// this will only take effect in the following scenarios:
132
137
// 1. the user cancels the OAuth flow on web via back button, and
@@ -135,8 +140,11 @@ const oauthSignIn = async ({
135
140
136
141
// the following is effective only in react-native as openAuthSession resolves only in react-native
137
142
const { type, error, url } =
138
- ( await openAuthSession ( oAuthUrl , redirectSignIn , preferPrivateSession ) ) ??
139
- { } ;
143
+ ( await openAuthSession (
144
+ oAuthUrl . href ,
145
+ redirectSignIn ,
146
+ preferPrivateSession ,
147
+ ) ) ?? { } ;
140
148
141
149
try {
142
150
if ( type === 'error' ) {
0 commit comments