From cc8d7ae8dd547a86f6988f1f296c85633a60d09a Mon Sep 17 00:00:00 2001 From: Ryan Bonial Date: Wed, 15 Oct 2025 14:01:21 -0600 Subject: [PATCH 1/2] fix(auth): do not clear the entire hash during login, only a token value --- packages/core/src/auth/utils.test.ts | 34 ++++++++++++++++++++++++++++ packages/core/src/auth/utils.ts | 11 +++++++-- 2 files changed, 43 insertions(+), 2 deletions(-) diff --git a/packages/core/src/auth/utils.test.ts b/packages/core/src/auth/utils.test.ts index e4fc39176..a5332cd4a 100644 --- a/packages/core/src/auth/utils.test.ts +++ b/packages/core/src/auth/utils.test.ts @@ -4,6 +4,7 @@ import {afterEach, beforeEach, describe, expect, it, vi} from 'vitest' import {AUTH_CODE_PARAM, DEFAULT_BASE} from './authConstants' import { getAuthCode, + getCleanedUrl, getDefaultLocation, getDefaultStorage, getStorageEvents, @@ -230,3 +231,36 @@ describe('getTokenFromLocation', () => { expect(result).toBe(testToken) }) }) + +describe('getCleanedUrl', () => { + it('removes only token from hash when it is the only param', () => { + const url = 'http://example.com/page#token=abc' + const cleaned = getCleanedUrl(url) + expect(cleaned).toBe('http://example.com/page') + }) + + it('removes only token from hash and preserves other hash params', () => { + const url = 'http://example.com/page#token=abc&foo=bar' + const cleaned = getCleanedUrl(url) + expect(cleaned).toBe('http://example.com/page#foo=bar') + }) + + it('removes token when it appears among multiple hash params', () => { + const url = 'http://example.com/page#foo=bar&token=abc&baz=qux' + const cleaned = getCleanedUrl(url) + expect(cleaned).toBe('http://example.com/page#foo=bar&baz=qux') + }) + + it('removes sid and url from query string while preserving others', () => { + const url = + 'http://example.com/callback?sid=s1&url=https%3A%2F%2Freturn.example%2Fdone&x=1#token=abc' + const cleaned = getCleanedUrl(url) + expect(cleaned).toBe('http://example.com/callback?x=1') + }) + + it('preserves non key-value hash fragments', () => { + const url = 'http://example.com/page#section' + const cleaned = getCleanedUrl(url) + expect(cleaned).toBe('http://example.com/page#section') + }) +}) diff --git a/packages/core/src/auth/utils.ts b/packages/core/src/auth/utils.ts index 809c4aaf6..61942e5fe 100644 --- a/packages/core/src/auth/utils.ts +++ b/packages/core/src/auth/utils.ts @@ -116,12 +116,19 @@ export function getDefaultLocation(): string { } /** - * Cleans up the URL by removing the hash and the sid and url parameters. + * Cleans up the URL by removing the `token` from the hash and the `sid` and `url` search params. * @internal */ export function getCleanedUrl(locationUrl: string): string { const loc = new URL(locationUrl) - loc.hash = '' + // Remove only the `token` param from the hash while preserving other fragments + const rawHash = loc.hash.startsWith('#') ? loc.hash.slice(1) : loc.hash + if (rawHash && rawHash.includes('=')) { + const hashParams = new URLSearchParams(rawHash) + hashParams.delete('token') + const nextHash = hashParams.toString() + loc.hash = nextHash ? `#${nextHash}` : '' + } loc.searchParams.delete('sid') loc.searchParams.delete('url') return loc.toString() From cf736a204530a75907c8b4e4694ef643a3fb80fa Mon Sep 17 00:00:00 2001 From: Ryan Bonial Date: Wed, 15 Oct 2025 14:12:15 -0600 Subject: [PATCH 2/2] fix(auth): also remove withSid --- packages/core/src/auth/utils.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/core/src/auth/utils.ts b/packages/core/src/auth/utils.ts index 61942e5fe..c04e62103 100644 --- a/packages/core/src/auth/utils.ts +++ b/packages/core/src/auth/utils.ts @@ -126,6 +126,7 @@ export function getCleanedUrl(locationUrl: string): string { if (rawHash && rawHash.includes('=')) { const hashParams = new URLSearchParams(rawHash) hashParams.delete('token') + hashParams.delete('withSid') const nextHash = hashParams.toString() loc.hash = nextHash ? `#${nextHash}` : '' }