@@ -307,11 +307,22 @@ export default class GoTrueClient {
307
307
*/
308
308
private async _initialize ( ) : Promise < InitializeResult > {
309
309
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 )
315
326
if ( error ) {
316
327
this . _debug ( '#_initialize()' , 'error detecting session from URL' , error )
317
328
@@ -1414,7 +1425,10 @@ export default class GoTrueClient {
1414
1425
/**
1415
1426
* Gets the session data from a URL string
1416
1427
*/
1417
- private async _getSessionFromURL ( isPKCEFlow : boolean ) : Promise <
1428
+ private async _getSessionFromURL (
1429
+ params : { [ parameter : string ] : string } ,
1430
+ callbackUrlType : string
1431
+ ) : Promise <
1418
1432
| {
1419
1433
data : { session : Session ; redirectType : string | null }
1420
1434
error : null
@@ -1423,15 +1437,39 @@ export default class GoTrueClient {
1423
1437
> {
1424
1438
try {
1425
1439
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
+ )
1430
1452
}
1431
1453
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
+ }
1433
1469
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 )
1435
1473
if ( ! params . code ) throw new AuthPKCEGrantCodeExchangeError ( 'No code detected.' )
1436
1474
const { data, error } = await this . _exchangeCodeForSession ( params . code )
1437
1475
if ( error ) throw error
@@ -1444,16 +1482,6 @@ export default class GoTrueClient {
1444
1482
return { data : { session : data . session , redirectType : null } , error : null }
1445
1483
}
1446
1484
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
-
1457
1485
const {
1458
1486
provider_token,
1459
1487
provider_refresh_token,
@@ -1531,18 +1559,14 @@ export default class GoTrueClient {
1531
1559
/**
1532
1560
* 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)
1533
1561
*/
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 )
1538
1564
}
1539
1565
1540
1566
/**
1541
1567
* Checks if the current URL and backing storage contain parameters given by a PKCE flow
1542
1568
*/
1543
- private async _isPKCEFlow ( ) : Promise < boolean > {
1544
- const params = parseParametersFromURL ( window . location . href )
1545
-
1569
+ private async _isPKCECallback ( params : { [ parameter : string ] : string } ) : Promise < boolean > {
1546
1570
const currentStorageContent = await getItemAsync (
1547
1571
this . storage ,
1548
1572
`${ this . storageKey } -code-verifier`
0 commit comments