This commit is contained in:
Emil
2026-02-21 16:08:01 +01:00
parent 928e4ba489
commit 6f6fbb19d0
2 changed files with 65 additions and 26 deletions
+64 -25
View File
@@ -1,35 +1,74 @@
import { createClient } from '@/lib/supabase/server'
import { NextResponse } from 'next/server'
import { createServerClient } from '@supabase/ssr'
import { type NextRequest, NextResponse } from 'next/server'
export async function GET(request: Request) {
export async function GET(request: NextRequest) {
const { searchParams, origin } = new URL(request.url)
const code = searchParams.get('code')
const token_hash = searchParams.get('token_hash')
const type = searchParams.get('type')
const next = searchParams.get('next') ?? '/'
if (code) {
const supabase = await createClient()
const { error } = await supabase.auth.exchangeCodeForSession(code)
// Collect cookies that Supabase sets during auth so we can
// explicitly forward them on the redirect response.
const pendingCookies: { name: string; value: string; options: Record<string, unknown> }[] = []
if (!error) {
// Check if user has completed onboarding
const { data: { user } } = await supabase.auth.getUser()
if (user) {
const { data: settings } = await supabase
.from('company_settings')
.select('onboarding_complete')
.eq('user_id', user.id)
.single()
if (!settings?.onboarding_complete) {
return NextResponse.redirect(`${origin}/onboarding`)
}
}
return NextResponse.redirect(`${origin}${next}`)
const supabase = createServerClient(
process.env.NEXT_PUBLIC_SUPABASE_URL!,
process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!,
{
cookies: {
getAll() {
return request.cookies.getAll()
},
setAll(cookiesToSet) {
pendingCookies.length = 0
cookiesToSet.forEach((cookie) => pendingCookies.push(cookie))
},
},
}
)
let authenticated = false
// Handle PKCE flow (code exchange)
if (code) {
const { error } = await supabase.auth.exchangeCodeForSession(code)
authenticated = !error
}
// Handle token hash flow (email verification / magic link)
else if (token_hash && type) {
const { error } = await supabase.auth.verifyOtp({
token_hash,
type: type as 'signup' | 'invite' | 'magiclink' | 'recovery' | 'email_change' | 'email',
})
authenticated = !error
}
// Return the user to an error page with instructions
return NextResponse.redirect(`${origin}/login?error=auth_error`)
if (authenticated) {
let redirectPath = next
// Check if user has completed onboarding
const { data: { user } } = await supabase.auth.getUser()
if (user) {
const { data: settings } = await supabase
.from('company_settings')
.select('onboarding_complete')
.eq('user_id', user.id)
.single()
if (!settings?.onboarding_complete) {
redirectPath = '/onboarding'
}
}
// Create redirect and explicitly set auth cookies on the response
const response = NextResponse.redirect(new URL(redirectPath, origin))
for (const { name, value, options } of pendingCookies) {
response.cookies.set({ name, value, ...options })
}
return response
}
// Authentication failed — redirect to login with error
return NextResponse.redirect(new URL('/login?error=auth_error', origin))
}
+1 -1
View File
@@ -24,7 +24,7 @@ export default function LoginPage() {
const { error } = await supabase.auth.signInWithOtp({
email,
options: {
emailRedirectTo: `${process.env.NEXT_PUBLIC_APP_URL || window.location.origin}/auth/callback`,
emailRedirectTo: `${window.location.origin}/auth/callback`,
},
})