Skip to content

Commit

Permalink
fix: add password recoery flow support for pkce (#813)
Browse files Browse the repository at this point in the history
## What kind of change does this PR introduce?

Currently, `PASSWORD_RECOVERY` auth event is not emitted during a
password recovery flow using pkce.

## What is the current behavior?

Calling `resetPasswordForEmail()` method 

## What is the new behavior?

Calling `resetPasswordForEmail()` sets a code verifier and the auth flow
`PASSWORD_RECOVERY` with a `/` separator on the local storage like this:
`${codeVerifier}/PASSWORD_RECOVERY`

Within `_exchangeCodeForSession()`, the auth flow and the code verifier
is extracted from local storage, and if the auth flow is
`PASSWORD_RECOVERY`, then `PASSWORD_RECOVERY` event is fired instead of
`SIGNED_IN` event.
  • Loading branch information
dshukertjr authored Nov 29, 2023
1 parent c9296bb commit e46a324
Showing 1 changed file with 21 additions and 6 deletions.
27 changes: 21 additions & 6 deletions src/GoTrueClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -499,8 +499,16 @@ export default class GoTrueClient {
})
}

private async _exchangeCodeForSession(authCode: string): Promise<AuthTokenResponse> {
const codeVerifier = await getItemAsync(this.storage, `${this.storageKey}-code-verifier`)
private async _exchangeCodeForSession(authCode: string): Promise<
| {
data: { session: Session; user: User; redirectType: string | null }
error: null
}
| { data: { session: null; user: null; redirectType: null }; error: AuthError }
> {
const [codeVerifier, redirectType] = (
(await getItemAsync(this.storage, `${this.storageKey}-code-verifier`)) as string
).split('/')
const { data, error } = await _request(
this.fetch,
'POST',
Expand All @@ -516,15 +524,18 @@ export default class GoTrueClient {
)
await removeItemAsync(this.storage, `${this.storageKey}-code-verifier`)
if (error) {
return { data: { user: null, session: null }, error }
return { data: { user: null, session: null, redirectType: null }, error }
} else if (!data || !data.session || !data.user) {
return { data: { user: null, session: null }, error: new AuthInvalidTokenResponseError() }
return {
data: { user: null, session: null, redirectType: null },
error: new AuthInvalidTokenResponseError(),
}
}
if (data.session) {
await this._saveSession(data.session)
await this._notifyAllSubscribers('SIGNED_IN', data.session)
}
return { data, error }
return { data: { ...data, redirectType: redirectType ?? null }, error }
}

/**
Expand Down Expand Up @@ -1538,7 +1549,11 @@ export default class GoTrueClient {
let codeChallengeMethod: string | null = null
if (this.flowType === 'pkce') {
const codeVerifier = generatePKCEVerifier()
await setItemAsync(this.storage, `${this.storageKey}-code-verifier`, codeVerifier)
await setItemAsync(
this.storage,
`${this.storageKey}-code-verifier`,
`${codeVerifier}/PASSWORD_RECOVERY`
)
codeChallenge = await generatePKCEChallenge(codeVerifier)
codeChallengeMethod = codeVerifier === codeChallenge ? 'plain' : 's256'
}
Expand Down

0 comments on commit e46a324

Please sign in to comment.