diff --git a/packages/core/auth-js/src/GoTrueClient.ts b/packages/core/auth-js/src/GoTrueClient.ts index 4de54bd57..befc79cb3 100644 --- a/packages/core/auth-js/src/GoTrueClient.ts +++ b/packages/core/auth-js/src/GoTrueClient.ts @@ -2052,6 +2052,28 @@ export default class GoTrueClient { } = params if (!access_token || !expires_in || !refresh_token || !token_type) { + if (provider_token || provider_refresh_token) { + const { data: sessionData, error: sessionError } = await this._useSession( + async (result) => result + ) + if (sessionError) throw sessionError + if (!sessionData.session) { + throw new AuthImplicitGrantRedirectError('No session defined in URL') + } + + const session: Session = { + ...sessionData.session, + provider_token, + provider_refresh_token, + } + + // Remove tokens from URL + window.location.hash = '' + this._debug('#_getSessionFromURL()', 'clearing window.location.hash') + + return this._returnResult({ data: { session, redirectType: params.type }, error: null }) + } + throw new AuthImplicitGrantRedirectError('No session defined in URL') } @@ -2126,7 +2148,12 @@ export default class GoTrueClient { if (typeof this.detectSessionInUrl === 'function') { return this.detectSessionInUrl(new URL(window.location.href), params) } - return Boolean(params.access_token || params.error_description) + return Boolean( + params.access_token || + params.error_description || + params.provider_token || + params.provider_refresh_token + ) } /** diff --git a/packages/core/auth-js/test/GoTrueClient.browser.test.ts b/packages/core/auth-js/test/GoTrueClient.browser.test.ts index b0b0a15d9..2214c6b57 100644 --- a/packages/core/auth-js/test/GoTrueClient.browser.test.ts +++ b/packages/core/auth-js/test/GoTrueClient.browser.test.ts @@ -346,6 +346,32 @@ describe('Callback URL handling', () => { expect(session?.refresh_token).toBe('test-refresh-token') }) + it('should attach provider token when callback only includes provider tokens', async () => { + window.location.href = + 'http://localhost:9999/callback#provider_token=provider-token&provider_refresh_token=provider-refresh&type=link' + + const expiresAt = Math.floor(Date.now() / 1000) + 3600 + storedSession = JSON.stringify({ + access_token: 'existing-access-token', + refresh_token: 'existing-refresh-token', + expires_in: 3600, + expires_at: expiresAt, + token_type: 'bearer', + user: { id: 'test-user' }, + }) + + const client = getClientWithSpecificStorage(mockStorage) + await client.initialize() + + const { + data: { session }, + } = await client.getSession() + expect(session).toBeDefined() + expect(session?.access_token).toBe('existing-access-token') + expect(session?.provider_token).toBe('provider-token') + expect(session?.provider_refresh_token).toBe('provider-refresh') + }) + it('should handle error in callback URL', async () => { // Set up URL with error parameters window.location.href =