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>
This commit is contained in:
Jakob Wennberg
2026-03-02 19:12:33 +01:00
co-authored by Claude Opus 4.6
parent c32bf37a15
commit 31dec292fe
3 changed files with 22 additions and 7 deletions
+10 -3
View File
@@ -17,13 +17,17 @@ export default function LoginPage() {
const { toast } = useToast()
const supabase = createClient()
const handleLogin = async (e: React.FormEvent) => {
const handleLogin = async (e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault()
setIsLoading(true)
// Read from DOM to handle browser autofill (which may not trigger onChange)
const formData = new FormData(e.currentTarget)
const emailValue = (formData.get('email') as string) || email
try {
const { error } = await supabase.auth.signInWithOtp({
email,
email: emailValue,
options: {
emailRedirectTo: `${window.location.origin}/auth/callback`,
},
@@ -38,6 +42,7 @@ export default function LoginPage() {
return
}
setEmail(emailValue)
setIsEmailSent(true)
toast({
title: 'E-post skickad!',
@@ -101,7 +106,9 @@ export default function LoginPage() {
<Label htmlFor="email">E-postadress</Label>
<Input
id="email"
name="email"
type="email"
autoComplete="email"
placeholder="namn@exempel.se"
value={email}
onChange={(e) => setEmail(e.target.value)}
@@ -112,7 +119,7 @@ export default function LoginPage() {
<Button
type="submit"
className="w-full"
disabled={isLoading || !email}
disabled={isLoading}
>
{isLoading ? (
<>
+8
View File
@@ -35,11 +35,19 @@ export async function updateSession(request: NextRequest) {
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
+4 -4
View File
@@ -7,10 +7,10 @@ const supabaseUrl = process.env.NEXT_PUBLIC_SUPABASE_URL ?? "";
const cspDirectives = [
"default-src 'self'",
`connect-src 'self' ${supabaseUrl} https://*.supabase.co wss://*.supabase.co https://*.ingest.sentry.io`,
`style-src 'self' 'unsafe-inline'`,
`script-src 'self'${isDev ? " 'unsafe-eval'" : ""}`,
"img-src 'self' data: blob:",
`connect-src 'self' ${supabaseUrl} https://*.supabase.co wss://*.supabase.co https://*.ingest.sentry.io https://*.enablebanking.com`,
`style-src 'self' 'unsafe-inline' https://*.enablebanking.com`,
`script-src 'self' 'unsafe-inline'${isDev ? " 'unsafe-eval'" : ""} https://*.enablebanking.com`,
"img-src 'self' data: blob: https:",
"font-src 'self'",
"frame-ancestors 'none'",
].join("; ");