@@ -307,11 +307,22 @@ export default class GoTrueClient {
307307 */
308308 private async _initialize ( ) : Promise < InitializeResult > {
309309 try {
310- const isPKCEFlow = isBrowser ( ) ? await this . _isPKCEFlow ( ) : false
311- this . _debug ( '#_initialize()' , 'begin' , 'is PKCE flow' , isPKCEFlow )
312-
313- if ( isPKCEFlow || ( this . detectSessionInUrl && this . _isImplicitGrantFlow ( ) ) ) {
314- const { data, error } = await this . _getSessionFromURL ( isPKCEFlow )
310+ const params = parseParametersFromURL ( window . location . href )
311+ let callbackUrlType = 'none'
312+ if ( this . _isImplicitGrantCallback ( params ) ) {
313+ callbackUrlType = 'implicit'
314+ } else if ( await this . _isPKCECallback ( params ) ) {
315+ callbackUrlType = 'pkce'
316+ }
317+
318+ /**
319+ * Attempt to get the session from the URL only if these conditions are fulfilled
320+ *
321+ * Note: If the URL isn't one of the callback url types (implicit or pkce),
322+ * then there could be an existing session so we don't want to prematurely remove it
323+ */
324+ if ( isBrowser ( ) && this . detectSessionInUrl && callbackUrlType !== 'none' ) {
325+ const { data, error } = await this . _getSessionFromURL ( params , callbackUrlType )
315326 if ( error ) {
316327 this . _debug ( '#_initialize()' , 'error detecting session from URL' , error )
317328
@@ -1414,7 +1425,10 @@ export default class GoTrueClient {
14141425 /**
14151426 * Gets the session data from a URL string
14161427 */
1417- private async _getSessionFromURL ( isPKCEFlow : boolean ) : Promise <
1428+ private async _getSessionFromURL (
1429+ params : { [ parameter : string ] : string } ,
1430+ callbackUrlType : string
1431+ ) : Promise <
14181432 | {
14191433 data : { session : Session ; redirectType : string | null }
14201434 error : null
@@ -1423,15 +1437,39 @@ export default class GoTrueClient {
14231437 > {
14241438 try {
14251439 if ( ! isBrowser ( ) ) throw new AuthImplicitGrantRedirectError ( 'No browser detected.' )
1426- if ( this . flowType === 'implicit' && ! this . _isImplicitGrantFlow ( ) ) {
1427- throw new AuthImplicitGrantRedirectError ( 'Not a valid implicit grant flow url.' )
1428- } else if ( this . flowType == 'pkce' && ! isPKCEFlow ) {
1429- throw new AuthPKCEGrantCodeExchangeError ( 'Not a valid PKCE flow url.' )
1440+
1441+ // If there's an error in the URL, it doesn't matter what flow it is, we just return the error.
1442+ if ( params . error || params . error_description || params . error_code ) {
1443+ // The error class returned implies that the redirect is from an implicit grant flow
1444+ // but it could also be from a redirect error from a PKCE flow.
1445+ throw new AuthImplicitGrantRedirectError (
1446+ params . error_description || 'Error in URL with unspecified error_description' ,
1447+ {
1448+ error : params . error || 'unspecified_error' ,
1449+ code : params . error_code || 'unspecified_code' ,
1450+ }
1451+ )
14301452 }
14311453
1432- const params = parseParametersFromURL ( window . location . href )
1454+ // Checks for mismatches between the flowType initialised in the client and the URL parameters
1455+ switch ( callbackUrlType ) {
1456+ case 'implicit' :
1457+ if ( this . flowType === 'pkce' ) {
1458+ throw new AuthPKCEGrantCodeExchangeError ( 'Not a valid PKCE flow url.' )
1459+ }
1460+ break
1461+ case 'pkce' :
1462+ if ( this . flowType === 'implicit' ) {
1463+ throw new AuthImplicitGrantRedirectError ( 'Not a valid implicit grant flow url.' )
1464+ }
1465+ break
1466+ default :
1467+ // there's no mismatch so we continue
1468+ }
14331469
1434- if ( isPKCEFlow ) {
1470+ // Since this is a redirect for PKCE, we attempt to retrieve the code from the URL for the code exchange
1471+ if ( callbackUrlType === 'pkce' ) {
1472+ this . _debug ( '#_initialize()' , 'begin' , 'is PKCE flow' , true )
14351473 if ( ! params . code ) throw new AuthPKCEGrantCodeExchangeError ( 'No code detected.' )
14361474 const { data, error } = await this . _exchangeCodeForSession ( params . code )
14371475 if ( error ) throw error
@@ -1444,16 +1482,6 @@ export default class GoTrueClient {
14441482 return { data : { session : data . session , redirectType : null } , error : null }
14451483 }
14461484
1447- if ( params . error || params . error_description || params . error_code ) {
1448- throw new AuthImplicitGrantRedirectError (
1449- params . error_description || 'Error in URL with unspecified error_description' ,
1450- {
1451- error : params . error || 'unspecified_error' ,
1452- code : params . error_code || 'unspecified_code' ,
1453- }
1454- )
1455- }
1456-
14571485 const {
14581486 provider_token,
14591487 provider_refresh_token,
@@ -1531,18 +1559,14 @@ export default class GoTrueClient {
15311559 /**
15321560 * Checks if the current URL contains parameters given by an implicit oauth grant flow (https://www.rfc-editor.org/rfc/rfc6749.html#section-4.2)
15331561 */
1534- private _isImplicitGrantFlow ( ) : boolean {
1535- const params = parseParametersFromURL ( window . location . href )
1536-
1537- return ! ! ( isBrowser ( ) && ( params . access_token || params . error_description ) )
1562+ private _isImplicitGrantCallback ( params : { [ parameter : string ] : string } ) : boolean {
1563+ return Boolean ( params . access_token || params . error_description )
15381564 }
15391565
15401566 /**
15411567 * Checks if the current URL and backing storage contain parameters given by a PKCE flow
15421568 */
1543- private async _isPKCEFlow ( ) : Promise < boolean > {
1544- const params = parseParametersFromURL ( window . location . href )
1545-
1569+ private async _isPKCECallback ( params : { [ parameter : string ] : string } ) : Promise < boolean > {
15461570 const currentStorageContent = await getItemAsync (
15471571 this . storage ,
15481572 `${ this . storageKey } -code-verifier`
0 commit comments