Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 | 1x 9x 9x 9x 9x 1x 1x 8x 8x 2x 2x 6x | import type { RequestHandler } from './$types';
import { CALLBACK_ERROR } from '$lib/auth/errors';
export const GET: RequestHandler = async ({ url, locals: { supabase } }) => {
const code = url.searchParams.get('code');
const next = url.searchParams.get('next') ?? '/dashboard';
// Validate next to prevent open redirect — only allow relative paths
const safeNext =
next.startsWith('/') && !next.startsWith('//') && !next.includes('\\') ? next : '/dashboard';
if (!code) {
console.error('Auth callback: no code parameter', {
url: url.pathname,
params: Object.fromEntries(url.searchParams),
});
return new Response(null, {
status: 303,
headers: { location: `/login?error=${CALLBACK_ERROR.MISSING_CODE}` },
});
}
const { data, error } = await supabase.auth.exchangeCodeForSession(code);
if (error || !data.session) {
console.error('Auth callback: code exchange failed', {
error: error?.message,
code: code.substring(0, 8) + '…',
});
return new Response(null, {
status: 303,
headers: { location: `/login?error=${CALLBACK_ERROR.LINK_EXPIRED}` },
});
}
return new Response(null, {
status: 303,
headers: { location: safeNext },
});
};
|