From 9a08db0c248de21cbc826d65a64afa9f5fbcc6a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filipe=20Caba=C3=A7o?= Date: Thu, 11 Sep 2025 15:45:13 +0100 Subject: [PATCH 1/3] fix: use setAuth for realtime in signup flows also --- package-lock.json | 89 +++++---- src/SupabaseClient.ts | 1 + test/deno/integration.test.ts | 1 - test/integration.test.ts | 2 - test/integration/bun/integration.test.ts | 1 - test/unit/SupabaseClient.test.ts | 232 ++++++++++++++--------- 6 files changed, 199 insertions(+), 127 deletions(-) diff --git a/package-lock.json b/package-lock.json index f82d2e6b1..12d09e119 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1589,19 +1589,6 @@ "dev": true, "license": "MIT" }, - "node_modules/accepts": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", - "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", - "dev": true, - "dependencies": { - "mime-types": "~2.1.34", - "negotiator": "0.6.3" - }, - "engines": { - "node": ">= 0.6" - } - }, "node_modules/acorn": { "version": "8.8.2", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz", @@ -2564,6 +2551,7 @@ "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz", "integrity": "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==", "dev": true, + "license": "MIT", "dependencies": { "mime-db": ">= 1.43.0 < 2" }, @@ -2572,28 +2560,40 @@ } }, "node_modules/compression": { - "version": "1.7.4", - "resolved": "https://registry.npmjs.org/compression/-/compression-1.7.4.tgz", - "integrity": "sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ==", + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/compression/-/compression-1.8.1.tgz", + "integrity": "sha512-9mAqGPHLakhCLeNyxPkK4xVo746zQ/czLH1Ky+vkitMnWfWZps8r0qXuwhwizagCRttsL4lfG4pIOvaWLpAP0w==", "dev": true, + "license": "MIT", "dependencies": { - "accepts": "~1.3.5", - "bytes": "3.0.0", - "compressible": "~2.0.16", + "bytes": "3.1.2", + "compressible": "~2.0.18", "debug": "2.6.9", - "on-headers": "~1.0.2", - "safe-buffer": "5.1.2", + "negotiator": "~0.6.4", + "on-headers": "~1.1.0", + "safe-buffer": "5.2.1", "vary": "~1.1.2" }, "engines": { "node": ">= 0.8.0" } }, + "node_modules/compression/node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, "node_modules/compression/node_modules/debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "dev": true, + "license": "MIT", "dependencies": { "ms": "2.0.0" } @@ -2602,7 +2602,29 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "dev": true + "dev": true, + "license": "MIT" + }, + "node_modules/compression/node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" }, "node_modules/concat-map": { "version": "0.0.1", @@ -5699,10 +5721,11 @@ "dev": true }, "node_modules/negotiator": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", - "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "version": "0.6.4", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.4.tgz", + "integrity": "sha512-myRT3DiWPHqho5PrJaIRyaMv2kgYf0mUVgBNOYMuCH5Ki1yEiQaf/ZJuQ62nvpc44wL5WDbTX7yGJi1Neevw8w==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.6" } @@ -5997,10 +6020,11 @@ } }, "node_modules/on-headers": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", - "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.1.0.tgz", + "integrity": "sha512-737ZY3yNnXy37FHkQxPzt4UZ2UWPWiCZWLvFZ4fu5cueciegX0zGPnrlY6bwRg4FdQOe9YU8MkmJwGhoMybl8A==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.8" } @@ -7168,9 +7192,9 @@ } }, "node_modules/serve": { - "version": "14.2.4", - "resolved": "https://registry.npmjs.org/serve/-/serve-14.2.4.tgz", - "integrity": "sha512-qy1S34PJ/fcY8gjVGszDB3EXiPSk5FKhUa7tQe0UPRddxRidc2V6cNHPNewbE1D7MAkgLuWEt3Vw56vYy73tzQ==", + "version": "14.2.5", + "resolved": "https://registry.npmjs.org/serve/-/serve-14.2.5.tgz", + "integrity": "sha512-Qn/qMkzCcMFVPb60E/hQy+iRLpiU8PamOfOSYoAHmmF+fFFmpPpqa6Oci2iWYpTdOUM3VF+TINud7CfbQnsZbA==", "dev": true, "license": "MIT", "dependencies": { @@ -7181,7 +7205,7 @@ "chalk": "5.0.1", "chalk-template": "0.4.0", "clipboardy": "3.0.0", - "compression": "1.7.4", + "compression": "1.8.1", "is-port-reachable": "4.0.0", "serve-handler": "6.1.6", "update-check": "1.5.4" @@ -8331,6 +8355,7 @@ "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.8" } diff --git a/src/SupabaseClient.ts b/src/SupabaseClient.ts index 4fa749388..ff9569fe3 100644 --- a/src/SupabaseClient.ts +++ b/src/SupabaseClient.ts @@ -371,6 +371,7 @@ export default class SupabaseClient< this.changedAccessToken !== token ) { this.changedAccessToken = token + this.realtime.setAuth() } else if (event === 'SIGNED_OUT') { this.realtime.setAuth() if (source == 'STORAGE') this.auth.signOut() diff --git a/test/deno/integration.test.ts b/test/deno/integration.test.ts index 4107ddb7b..7210fb32b 100644 --- a/test/deno/integration.test.ts +++ b/test/deno/integration.test.ts @@ -156,7 +156,6 @@ Deno.test( await supabase.auth.signUp({ email, password }) const config = { broadcast: { self: true }, private: true } channel = supabase.channel(channelName, { config }) - await supabase.realtime.setAuth() const testMessage = { message: 'test' } let receivedMessage: any diff --git a/test/integration.test.ts b/test/integration.test.ts index 55478ddcb..d9553405b 100644 --- a/test/integration.test.ts +++ b/test/integration.test.ts @@ -278,8 +278,6 @@ describe('Supabase Integration Tests', () => { const config = { broadcast: { self: true }, private: true } channel = supabase.channel(channelName, { config }) - - await supabase.realtime.setAuth() }) afterEach(async () => { diff --git a/test/integration/bun/integration.test.ts b/test/integration/bun/integration.test.ts index 985a172c9..e35749229 100644 --- a/test/integration/bun/integration.test.ts +++ b/test/integration/bun/integration.test.ts @@ -14,7 +14,6 @@ test('should subscribe to realtime channel', async () => { const email = `bun-test-${Date.now()}@example.com` const password = 'password123' await supabase.auth.signUp({ email, password }) - await supabase.realtime.setAuth() const channelName = `bun-channel-${crypto.randomUUID()}` const config = { broadcast: { self: true }, private: true } diff --git a/test/unit/SupabaseClient.test.ts b/test/unit/SupabaseClient.test.ts index 5c82f446b..c7f59a319 100644 --- a/test/unit/SupabaseClient.test.ts +++ b/test/unit/SupabaseClient.test.ts @@ -219,124 +219,174 @@ describe('SupabaseClient', () => { }) }) - describe('Access Token Handling', () => { - test('should use custom accessToken when provided', async () => { - const customToken = 'custom-jwt-token' - const client = createClient(URL, KEY, { - accessToken: async () => customToken, + describe('Token Management', () => { + describe('Token Resolution', () => { + test('should resolve token from session', async () => { + const expectedToken = 'test-jwt-token' + const client = createClient(URL, KEY) + + client.auth.getSession = jest.fn().mockResolvedValue({ + data: { session: { access_token: expectedToken } }, + }) + + // @ts-ignore - accessing private method + const token = await client._getAccessToken() + expect(token).toBe(expectedToken) }) - // Access the private method through the client instance - const accessToken = await (client as any)._getAccessToken() - expect(accessToken).toBe(customToken) - }) - - test('should fallback to session access token when no custom accessToken', async () => { - const client = createClient(URL, KEY) + test('should use custom accessToken callback', async () => { + const customToken = 'custom-access-token' + const customAccessTokenFn = jest.fn().mockResolvedValue(customToken) + const client = createClient(URL, KEY, { accessToken: customAccessTokenFn }) - // Mock the auth.getSession method - const mockSession = { - data: { - session: { - access_token: 'session-jwt-token', - }, - }, - } - client.auth.getSession = jest.fn().mockResolvedValue(mockSession) - - const accessToken = await (client as any)._getAccessToken() - expect(accessToken).toBe('session-jwt-token') - }) + // @ts-ignore - accessing private method + const token = await client._getAccessToken() + expect(token).toBe(customToken) + expect(customAccessTokenFn).toHaveBeenCalled() + }) - test('should fallback to supabaseKey when no session', async () => { - const client = createClient(URL, KEY) + test('should fallback to supabaseKey when no session available', async () => { + const client = createClient(URL, KEY) - // Mock the auth.getSession method to return no session - const mockSession = { - data: { - session: null, - }, - } - client.auth.getSession = jest.fn().mockResolvedValue(mockSession) + client.auth.getSession = jest.fn().mockResolvedValue({ + data: { session: null }, + }) - const accessToken = await (client as any)._getAccessToken() - expect(accessToken).toBe(KEY) + // @ts-ignore - accessing private method + const token = await client._getAccessToken() + expect(token).toBe(KEY) + }) }) - }) - describe('Auth Event Handling', () => { - test('should handle TOKEN_REFRESHED event', () => { - const client = createClient(URL, KEY) - const newToken = 'new-refreshed-token' + describe('Realtime Authentication', () => { + test('should provide access token to realtime client', async () => { + const expectedToken = 'test-jwt-token' + const client = createClient(URL, KEY) - // Mock realtime.setAuth - client.realtime.setAuth = jest.fn() - ;(client as any)._handleTokenChanged('TOKEN_REFRESHED', 'CLIENT', newToken) + client.auth.getSession = jest.fn().mockResolvedValue({ + data: { session: { access_token: expectedToken } }, + }) - expect((client as any).changedAccessToken).toBe(newToken) - }) + const realtimeToken = await client.realtime.accessToken!() + expect(realtimeToken).toBe(expectedToken) + }) - test('should listen for auth events', () => { - const client = createClient(URL, KEY) + test('should handle authentication state changes', async () => { + const client = createClient(URL, KEY) + const setAuthSpy = jest.spyOn(client.realtime, 'setAuth') - // Mock auth.onAuthStateChange - const mockCallback = jest.fn() - client.auth.onAuthStateChange = jest.fn().mockReturnValue(mockCallback) + // @ts-ignore - accessing private method for testing + client._handleTokenChanged('TOKEN_REFRESHED', 'CLIENT', 'new-token') + expect(setAuthSpy).toHaveBeenCalledWith() - // Call the private method - const result = (client as any)._listenForAuthEvents() + setAuthSpy.mockClear() - expect(client.auth.onAuthStateChange).toHaveBeenCalled() - expect(result).toBe(mockCallback) - }) + // @ts-ignore - accessing private method for testing + client._handleTokenChanged('SIGNED_IN', 'CLIENT', 'signin-token') + expect(setAuthSpy).toHaveBeenCalledWith() - test('should handle SIGNED_IN event', () => { - const client = createClient(URL, KEY) - const newToken = 'new-signed-in-token' + setAuthSpy.mockClear() - // Mock realtime.setAuth - client.realtime.setAuth = jest.fn() - ;(client as any)._handleTokenChanged('SIGNED_IN', 'CLIENT', newToken) + // @ts-ignore - accessing private method for testing + client._handleTokenChanged('SIGNED_OUT', 'CLIENT') + expect(setAuthSpy).toHaveBeenCalledWith() + }) - expect((client as any).changedAccessToken).toBe(newToken) + test('should update token in realtime client when setAuth is called', async () => { + const client = createClient(URL, KEY) + const testToken = 'test-realtime-token' + + client.realtime.setAuth = jest.fn(async (token) => { + if (token) { + ;(client.realtime as any).accessTokenValue = token + } else { + const freshToken = await client.realtime.accessToken!() + ;(client.realtime as any).accessTokenValue = freshToken + } + }) + + await client.realtime.setAuth(testToken) + expect(client.realtime.setAuth).toHaveBeenCalledWith(testToken) + expect((client.realtime as any).accessTokenValue).toBe(testToken) + }) }) - test('should not update token if it is the same', () => { - const client = createClient(URL, KEY) - const existingToken = 'existing-token' - ;(client as any).changedAccessToken = existingToken + describe('FetchWithAuth Token Integration', () => { + test('should pass correct token to fetchWithAuth wrapper', async () => { + const expectedToken = 'test-fetch-token' + const mockFetch = jest.fn().mockResolvedValue({ + ok: true, + json: () => Promise.resolve({}), + }) - // Mock realtime.setAuth - client.realtime.setAuth = jest.fn() - ;(client as any)._handleTokenChanged('TOKEN_REFRESHED', 'CLIENT', existingToken) + const client = createClient(URL, KEY, { + global: { fetch: mockFetch }, + }) - expect((client as any).changedAccessToken).toBe(existingToken) - }) + client.auth.getSession = jest.fn().mockResolvedValue({ + data: { session: { access_token: expectedToken } }, + }) - test('should handle SIGNED_OUT event from CLIENT source', () => { - const client = createClient(URL, KEY) - ;(client as any).changedAccessToken = 'old-token' + await client.from('test').select('*') - // Mock realtime.setAuth - client.realtime.setAuth = jest.fn() - ;(client as any)._handleTokenChanged('SIGNED_OUT', 'CLIENT') + expect(mockFetch).toHaveBeenCalled() + const [, options] = mockFetch.mock.calls[0] + expect(options.headers.get('Authorization')).toBe(`Bearer ${expectedToken}`) + expect(options.headers.get('apikey')).toBe(KEY) + }) - expect(client.realtime.setAuth).toHaveBeenCalled() - expect((client as any).changedAccessToken).toBeUndefined() - }) + test('should work across all fetchWithAuth services', async () => { + const expectedToken = 'test-multi-service-token' + const mockFetch = jest + .fn() + .mockResolvedValueOnce({ ok: true, json: () => Promise.resolve({}) }) // rest + .mockResolvedValueOnce({ ok: true, json: () => Promise.resolve({ data: [] }) }) // storage + .mockResolvedValueOnce({ + ok: true, + text: () => Promise.resolve('{}'), + headers: new Map(), + }) // functions + + const client = createClient(URL, KEY, { + global: { fetch: mockFetch }, + }) + + client.auth.getSession = jest.fn().mockResolvedValue({ + data: { session: { access_token: expectedToken } }, + }) + + await client.from('test').select('*') + await client.storage.from('test').list() + await client.functions.invoke('test-function') + + expect(mockFetch).toHaveBeenCalledTimes(3) + + mockFetch.mock.calls.forEach(([, options]) => { + expect(options.headers.get('Authorization')).toBe(`Bearer ${expectedToken}`) + }) + }) - test('should handle SIGNED_OUT event from STORAGE source', () => { - const client = createClient(URL, KEY) - ;(client as any).changedAccessToken = 'old-token' + test('should use supabaseKey fallback in fetchWithAuth', async () => { + const mockFetch = jest.fn().mockResolvedValue({ + ok: true, + json: () => Promise.resolve({}), + }) - // Mock realtime.setAuth and auth.signOut - client.realtime.setAuth = jest.fn() - client.auth.signOut = jest.fn() - ;(client as any)._handleTokenChanged('SIGNED_OUT', 'STORAGE') + const client = createClient(URL, KEY, { + global: { fetch: mockFetch }, + }) - expect(client.realtime.setAuth).toHaveBeenCalled() - expect(client.auth.signOut).toHaveBeenCalled() - expect((client as any).changedAccessToken).toBeUndefined() + client.auth.getSession = jest.fn().mockResolvedValue({ + data: { session: null }, + }) + + await client.from('test').select('*') + + expect(mockFetch).toHaveBeenCalled() + const [, options] = mockFetch.mock.calls[0] + expect(options.headers.get('Authorization')).toBe(`Bearer ${KEY}`) + expect(options.headers.get('apikey')).toBe(KEY) + }) }) }) }) From 23825c6301efa11f62232d063140864eb74e7620 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filipe=20Caba=C3=A7o?= Date: Fri, 12 Sep 2025 15:58:57 +0100 Subject: [PATCH 2/3] fix ci --- .github/workflows/ci.yml | 8 ++++++++ supabase/.temp/cli-latest | 2 +- test/integration/bun/bun.lockb | Bin 0 -> 7699 bytes 3 files changed, 9 insertions(+), 1 deletion(-) create mode 100755 test/integration/bun/bun.lockb diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b5105729a..da40a7239 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -316,6 +316,14 @@ jobs: - name: Start Supabase run: supabase start + - name: Create storage bucket for tests + run: | + SERVICE_ROLE_KEY="$(supabase status --output json | jq -r '.SERVICE_ROLE_KEY')" + curl -X POST 'http://127.0.0.1:54321/storage/v1/bucket' \ + -H "Authorization: Bearer $SERVICE_ROLE_KEY" \ + -H 'Content-Type: application/json' \ + -d '{"id": "test-bucket", "name": "test-bucket", "public": true}' + - name: Install dependencies and run tests run: | cd test/integration/bun diff --git a/supabase/.temp/cli-latest b/supabase/.temp/cli-latest index 8e00c6d6f..75788def2 100644 --- a/supabase/.temp/cli-latest +++ b/supabase/.temp/cli-latest @@ -1 +1 @@ -v2.33.9 \ No newline at end of file +v2.40.7 \ No newline at end of file diff --git a/test/integration/bun/bun.lockb b/test/integration/bun/bun.lockb new file mode 100755 index 0000000000000000000000000000000000000000..f9fdf6ddd03b351838f7cc2907f7a490527f2e93 GIT binary patch literal 7699 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 F{{|-j;hX>f literal 0 HcmV?d00001 From a0ee8b660a76f5b96fb2e95298125e5ecb4223c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filipe=20Caba=C3=A7o?= Date: Fri, 12 Sep 2025 16:29:11 +0100 Subject: [PATCH 3/3] push token instead of using binded expression --- src/SupabaseClient.ts | 2 +- test/unit/SupabaseClient.test.ts | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/SupabaseClient.ts b/src/SupabaseClient.ts index ff9569fe3..3acd10edf 100644 --- a/src/SupabaseClient.ts +++ b/src/SupabaseClient.ts @@ -371,7 +371,7 @@ export default class SupabaseClient< this.changedAccessToken !== token ) { this.changedAccessToken = token - this.realtime.setAuth() + this.realtime.setAuth(token) } else if (event === 'SIGNED_OUT') { this.realtime.setAuth() if (source == 'STORAGE') this.auth.signOut() diff --git a/test/unit/SupabaseClient.test.ts b/test/unit/SupabaseClient.test.ts index c7f59a319..6f7304114 100644 --- a/test/unit/SupabaseClient.test.ts +++ b/test/unit/SupabaseClient.test.ts @@ -277,13 +277,13 @@ describe('SupabaseClient', () => { // @ts-ignore - accessing private method for testing client._handleTokenChanged('TOKEN_REFRESHED', 'CLIENT', 'new-token') - expect(setAuthSpy).toHaveBeenCalledWith() + expect(setAuthSpy).toHaveBeenCalledWith('new-token') setAuthSpy.mockClear() // @ts-ignore - accessing private method for testing client._handleTokenChanged('SIGNED_IN', 'CLIENT', 'signin-token') - expect(setAuthSpy).toHaveBeenCalledWith() + expect(setAuthSpy).toHaveBeenCalledWith('signin-token') setAuthSpy.mockClear()