Files
accounted/lib/supabase/middleware.ts
T
Jakob Wennberg 31dec292fe fix: CSP blocking hydration and Enable Banking widget, stale auth cleanup
- Add 'unsafe-inline' to script-src so Next.js hydration scripts run
- Whitelist *.enablebanking.com in CSP (script, style, connect, img)
- Allow HTTPS images broadly for third-party bank logos
- Clear stale refresh tokens in middleware (skip on /auth callback)
- Fix login button disabled on browser autofill by reading email from form DOM

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 19:12:33 +01:00

108 lines
3.1 KiB
TypeScript

import { createServerClient } from '@supabase/ssr'
import { NextResponse, type NextRequest } from 'next/server'
export async function updateSession(request: NextRequest) {
let supabaseResponse = NextResponse.next({
request,
})
const supabase = createServerClient(
process.env.NEXT_PUBLIC_SUPABASE_URL!,
process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!,
{
cookies: {
getAll() {
return request.cookies.getAll()
},
setAll(cookiesToSet) {
cookiesToSet.forEach(({ name, value }) =>
request.cookies.set(name, value)
)
supabaseResponse = NextResponse.next({
request,
})
cookiesToSet.forEach(({ name, value, options }) =>
supabaseResponse.cookies.set(name, value, options)
)
},
},
}
)
// IMPORTANT: Avoid writing any logic between createServerClient and
// supabase.auth.getUser(). A simple mistake could make it very hard to debug
// issues with users being randomly logged out.
const {
data: { user },
error: authError,
} = await supabase.auth.getUser()
// Get the pathname
const pathname = request.nextUrl.pathname
// If the refresh token is stale/invalid, clear the session cookies
// so the browser stops sending them on every request.
// Skip on auth routes — the callback needs PKCE cookies intact.
if (authError && !user && !pathname.startsWith('/auth')) {
await supabase.auth.signOut()
}
// Auth routes - allow access
if (pathname.startsWith('/login') || pathname.startsWith('/auth')) {
// If user is logged in and trying to access login, redirect to dashboard or onboarding
if (user) {
// Check if onboarding is complete
const { data: settings } = await supabase
.from('company_settings')
.select('onboarding_complete')
.eq('user_id', user.id)
.single()
if (!settings?.onboarding_complete) {
return NextResponse.redirect(new URL('/onboarding', request.url))
}
return NextResponse.redirect(new URL('/', request.url))
}
return supabaseResponse
}
// Protected routes - require authentication
if (!user) {
const url = request.nextUrl.clone()
url.pathname = '/login'
return NextResponse.redirect(url)
}
// Onboarding route - only accessible if not complete
if (pathname.startsWith('/onboarding')) {
const { data: settings } = await supabase
.from('company_settings')
.select('onboarding_complete')
.eq('user_id', user.id)
.single()
// If onboarding is complete, redirect to dashboard
if (settings?.onboarding_complete) {
return NextResponse.redirect(new URL('/', request.url))
}
return supabaseResponse
}
// Dashboard routes - require completed onboarding
const { data: settings } = await supabase
.from('company_settings')
.select('onboarding_complete')
.eq('user_id', user.id)
.single()
// If no settings or onboarding not complete, redirect to onboarding
if (!settings?.onboarding_complete) {
return NextResponse.redirect(new URL('/onboarding', request.url))
}
return supabaseResponse
}