Skip to content

Commit a43c632

Browse files
committed
fix: code verifier remains in storage during edge cases
1 parent dfb40d2 commit a43c632

File tree

2 files changed

+24
-1
lines changed

2 files changed

+24
-1
lines changed

src/GoTrueClient.ts

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -460,6 +460,8 @@ export default class GoTrueClient {
460460
const { data, error } = res
461461

462462
if (error || !data) {
463+
await removeItemAsync(this.storage, `${this.storageKey}-code-verifier`)
464+
await this._notifyAllSubscribers('STORAGE_UPDATED', null)
463465
return { data: { user: null, session: null }, error: error }
464466
}
465467

@@ -473,6 +475,8 @@ export default class GoTrueClient {
473475

474476
return { data: { user, session }, error: null }
475477
} catch (error) {
478+
await removeItemAsync(this.storage, `${this.storageKey}-code-verifier`)
479+
await this._notifyAllSubscribers('STORAGE_UPDATED', null)
476480
if (isAuthError(error)) {
477481
return { data: { user: null, session: null }, error }
478482
}
@@ -613,6 +617,8 @@ export default class GoTrueClient {
613617
return { data: { ...data, redirectType: redirectType ?? null }, error }
614618
} catch (error) {
615619
if (isAuthError(error)) {
620+
await removeItemAsync(this.storage, `${this.storageKey}-code-verifier`)
621+
await this._notifyAllSubscribers('STORAGE_UPDATED', null)
616622
return { data: { user: null, session: null, redirectType: null }, error }
617623
}
618624

@@ -721,6 +727,8 @@ export default class GoTrueClient {
721727
}
722728
throw new AuthInvalidCredentialsError('You must provide either an email or phone number.')
723729
} catch (error) {
730+
await removeItemAsync(this.storage, `${this.storageKey}-code-verifier`)
731+
await this._notifyAllSubscribers('STORAGE_UPDATED', null)
724732
if (isAuthError(error)) {
725733
return { data: { user: null, session: null }, error }
726734
}
@@ -820,6 +828,8 @@ export default class GoTrueClient {
820828
xform: _ssoResponse,
821829
})
822830
} catch (error) {
831+
await removeItemAsync(this.storage, `${this.storageKey}-code-verifier`)
832+
await this._notifyAllSubscribers('STORAGE_UPDATED', null)
823833
if (isAuthError(error)) {
824834
return { data: null, error }
825835
}
@@ -1221,6 +1231,7 @@ export default class GoTrueClient {
12211231
emailRedirectTo?: string | undefined
12221232
} = {}
12231233
): Promise<UserResponse> {
1234+
let session: Session | null = null
12241235
try {
12251236
return await this._useSession(async (result) => {
12261237
const { data: sessionData, error: sessionError } = result
@@ -1230,7 +1241,7 @@ export default class GoTrueClient {
12301241
if (!sessionData.session) {
12311242
throw new AuthSessionMissingError()
12321243
}
1233-
const session: Session = sessionData.session
1244+
session = sessionData.session
12341245
let codeChallenge: string | null = null
12351246
let codeChallengeMethod: string | null = null
12361247
if (this.flowType === 'pkce' && attributes.email != null) {
@@ -1258,6 +1269,8 @@ export default class GoTrueClient {
12581269
return { data: { user: session.user }, error: null }
12591270
})
12601271
} catch (error) {
1272+
await removeItemAsync(this.storage, `${this.storageKey}-code-verifier`)
1273+
await this._notifyAllSubscribers('STORAGE_UPDATED', session)
12611274
if (isAuthError(error)) {
12621275
return { data: { user: null }, error }
12631276
}
@@ -1686,6 +1699,8 @@ export default class GoTrueClient {
16861699
redirectTo: options.redirectTo,
16871700
})
16881701
} catch (error) {
1702+
await removeItemAsync(this.storage, `${this.storageKey}-code-verifier`)
1703+
await this._notifyAllSubscribers('STORAGE_UPDATED', null)
16891704
if (isAuthError(error)) {
16901705
return { data: null, error }
16911706
}
@@ -1722,9 +1737,11 @@ export default class GoTrueClient {
17221737
* This method supports the PKCE flow.
17231738
*/
17241739
async linkIdentity(credentials: SignInWithOAuthCredentials): Promise<OAuthResponse> {
1740+
let session: Session | null = null
17251741
try {
17261742
const { data, error } = await this._useSession(async (result) => {
17271743
const { data, error } = result
1744+
session = data.session
17281745
if (error) throw error
17291746
const url: string = await this._getUrlForProvider(
17301747
`${this.url}/user/identities/authorize`,
@@ -1747,6 +1764,8 @@ export default class GoTrueClient {
17471764
}
17481765
return { data: { provider: credentials.provider, url: data?.url }, error: null }
17491766
} catch (error) {
1767+
await removeItemAsync(this.storage, `${this.storageKey}-code-verifier`)
1768+
await this._notifyAllSubscribers('STORAGE_UPDATED', session)
17501769
if (isAuthError(error)) {
17511770
return { data: { provider: credentials.provider, url: null }, error }
17521771
}
@@ -2032,6 +2051,9 @@ export default class GoTrueClient {
20322051
// so we can safely suppress the warning returned by future getSession calls
20332052
this.suppressGetSessionWarning = true
20342053
await setItemAsync(this.storage, this.storageKey, session)
2054+
2055+
// cleanup potentially unused code verifier
2056+
await removeItemAsync(this.storage, `${this.storageKey}-code-verifier`)
20352057
}
20362058

20372059
private async _removeSession() {

src/lib/types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ export type AuthChangeEvent =
3939
| 'PASSWORD_RECOVERY'
4040
| 'SIGNED_IN'
4141
| 'SIGNED_OUT'
42+
| 'STORAGE_UPDATED'
4243
| 'TOKEN_REFRESHED'
4344
| 'USER_UPDATED'
4445
| AuthChangeEventMFA

0 commit comments

Comments
 (0)