diff --git a/src/app/api/auth/key-backup/route.js b/src/app/api/auth/key-backup/route.js index 3b00161d..e6e7754c 100644 --- a/src/app/api/auth/key-backup/route.js +++ b/src/app/api/auth/key-backup/route.js @@ -17,6 +17,15 @@ function getServiceRoleClient() { // Create regular client for JWT validation const supabaseClient = createClient(process.env.NEXT_PUBLIC_SUPABASE_URL, process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY); +function getBearerToken(authHeader) { + if (typeof authHeader !== 'string') return null; + + const match = authHeader.match(/^Bearer\s+(.+)$/i); + const token = match?.[1]?.trim(); + + return token || null; +} + /** * Authenticate user from request cookies * @param {Request} request @@ -26,8 +35,8 @@ async function authenticateUser(request) { try { // Try Authorization header first (used during login before cookies are set) const authHeader = request.headers.get('authorization'); - if (authHeader?.startsWith('Bearer ')) { - const token = authHeader.substring(7); + const token = getBearerToken(authHeader); + if (token) { const { data: { user }, error } = await supabaseClient.auth.getUser(token); if (!error && user) { return { user }; diff --git a/src/app/api/auth/key-backup/route.test.js b/src/app/api/auth/key-backup/route.test.js index c05d2644..4bed3cb0 100644 --- a/src/app/api/auth/key-backup/route.test.js +++ b/src/app/api/auth/key-backup/route.test.js @@ -79,4 +79,33 @@ describe('key backup cookie authentication', () => { }); expect(mocks.authGetUser).toHaveBeenCalledWith('access-token'); }); + + it('normalizes bearer scheme casing and extra spaces', async () => { + const { GET } = await import('./route.js'); + const response = await GET( + new Request('https://qrypt.chat/api/auth/key-backup', { + headers: { + authorization: 'bearer access-token ' + } + }) + ); + + expect(response.status).toBe(200); + expect(mocks.authGetUser).toHaveBeenCalledWith('access-token'); + }); + + it('ignores an empty bearer header and falls back to cookies', async () => { + const { GET } = await import('./route.js'); + const response = await GET( + new Request('https://qrypt.chat/api/auth/key-backup', { + headers: { + authorization: 'Bearer ', + cookie: `sb-xydzwxwsbgmznthiiscl-auth-token=${cookieValue('cookie-token')}` + } + }) + ); + + expect(response.status).toBe(200); + expect(mocks.authGetUser).toHaveBeenCalledWith('cookie-token'); + }); });