docs: improve auth flow documentation and fix email confirmation redirect

**Auth Callback Improvements:**
- Fix default redirect from /clients to /epd/clients (correct route)
- Add smart detection for password vs magic link users
- Password signup users now go directly to /epd/clients after email confirmation
- Magic link users still get optional /set-password page

**Documentation:**
- Add comprehensive AUTH_FLOW_EXPLAINED.md with step-by-step flow diagrams
- Update RELEASE_AUTH_IMPROVEMENTS.md with magic link migration instructions
- Update emails/README.md with aispeedrun.nl redirect URL configuration
- Document Site URL vs Redirect URLs difference
- Add troubleshooting for common issues (localhost in emails, invalid redirect)

**Key Changes:**
- Email confirmation now correctly redirects password users to EPD
- Clear instructions for Supabase configuration (Site URL + Redirect URLs)
- Both development and production URLs documented for dual environment support

All documentation includes practical examples and FAQ section.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
colinislit
2025-11-19 11:38:57 +01:00
parent 2fcf609e27
commit 9dd129c258
4 changed files with 281 additions and 9 deletions

View File

@@ -12,7 +12,7 @@ import type { NextRequest } from 'next/server'
export async function GET(request: NextRequest) { export async function GET(request: NextRequest) {
const requestUrl = new URL(request.url) const requestUrl = new URL(request.url)
const code = requestUrl.searchParams.get('code') const code = requestUrl.searchParams.get('code')
const next = requestUrl.searchParams.get('next') ?? '/clients' const next = requestUrl.searchParams.get('next') ?? '/epd/clients'
if (code) { if (code) {
const supabase = await createClient() const supabase = await createClient()
@@ -25,12 +25,18 @@ export async function GET(request: NextRequest) {
const isNewUser = new Date(data.user.created_at).getTime() === const isNewUser = new Date(data.user.created_at).getTime() ===
new Date(data.user.last_sign_in_at || '').getTime() new Date(data.user.last_sign_in_at || '').getTime()
if (isNewUser) { // Check if user signed up with password (has identity provider = 'email')
// Redirect new users to set-password page const hasPassword = data.user.identities?.some(
identity => identity.provider === 'email'
)
if (isNewUser && !hasPassword) {
// Redirect new magic link users to set-password page (optional)
return NextResponse.redirect(new URL('/set-password', request.url)) return NextResponse.redirect(new URL('/set-password', request.url))
} }
// Redirect to the specified next URL or default to /clients // Redirect to the specified next URL or default to /epd/clients
// This includes: password signups, confirmed email users, and returning users
return NextResponse.redirect(new URL(next, request.url)) return NextResponse.redirect(new URL(next, request.url))
} }
} }

206
docs/AUTH_FLOW_EXPLAINED.md Normal file
View File

@@ -0,0 +1,206 @@
# Hoe werkt de Authenticatie Flow? 🔐
Een simpele uitleg van wat er gebeurt wanneer gebruikers zich aanmelden.
---
## 📧 Email Confirmatie Flow (nieuwe gebruikers)
### Stap 1: Gebruiker meldt zich aan
```
Gebruiker vult in op /login:
├─ Email: jan@example.com
└─ Wachtwoord: Geheim123!
```
### Stap 2: Supabase stuurt email
```
Supabase maakt account aan → Stuurt bevestigingsmail
De email bevat een link zoals:
https://aispeedrun.nl/auth/callback?token=xyz123&type=signup
└─────┬─────┘
Dit is de redirect URL!
```
### Stap 3: Gebruiker klikt op link in email
```
Browser gaat naar: /auth/callback?token=xyz123
De callback route doet:
1. ✅ Controleert de token
2. ✅ Activeert het account
3. ✅ Logt gebruiker in
4. → Stuurt door naar /epd/clients (omdat ze al wachtwoord hebben)
```
---
## 🔑 Wachtwoord Reset Flow
### Stap 1: Gebruiker klikt "Wachtwoord vergeten?"
```
Gaat naar: /reset-password
Vult in: jan@example.com
```
### Stap 2: Supabase stuurt reset email
```
Email bevat link:
https://aispeedrun.nl/auth/callback?token=abc789&type=recovery&next=/update-password
└─────┬─────┘ └────┬────┘
Callback route Waar naartoe daarna?
```
### Stap 3: Gebruiker klikt link
```
/auth/callback ontvangt de token
├─ Controleert token ✅
├─ Logt gebruiker tijdelijk in
└─ Redirect naar: /update-password (van de 'next' parameter)
```
### Stap 4: Nieuw wachtwoord instellen
```
Op /update-password:
├─ Gebruiker vult nieuw wachtwoord in
├─ Wachtwoord wordt opgeslagen
└─ Redirect naar /login → Gebruiker kan inloggen!
```
---
## ✉️ Magic Link Flow (oude methode)
### Stap 1: Gebruiker vraagt magic link aan
```
Vult alleen email in (geen wachtwoord)
```
### Stap 2: Email met magic link
```
Link: https://aispeedrun.nl/auth/callback?token=magic456
```
### Stap 3: Eerste keer inloggen
```
/auth/callback detecteert: "nieuwe magic link gebruiker"
└─ Redirect naar /set-password (optioneel wachtwoord instellen)
├─ Wachtwoord instellen → /epd/clients
└─ Overslaan → /epd/clients (blijf magic link gebruiken)
```
---
## 🌐 Waarom de Redirect URLs belangrijk zijn
Supabase moet weten welke URLs **veilig** zijn om naar terug te sturen.
### Zonder redirect URLs in Supabase:
```
❌ Link in email: https://aispeedrun.nl/auth/callback?token=xyz
Supabase zegt: "Deze URL ken ik niet, BLOCKED!"
Gebruiker ziet error 😞
```
### Met redirect URLs in Supabase:
```
✅ Link in email: https://aispeedrun.nl/auth/callback?token=xyz
Supabase zegt: "Deze URL staat in mijn lijst, OK!"
Gebruiker wordt ingelogd en doorgestuurd 🎉
```
---
## 🔧 De Site URL vs Redirect URLs
### Site URL (1 URL)
```
Dit is je "hoofd" URL waar Supabase denkt dat je app draait.
Supabase gebruikt dit voor:
├─ {{ .ConfirmationURL }} in emails (de basis)
└─ Default redirects
Development: http://localhost:3000
Production: https://aispeedrun.nl
```
### Redirect URLs (meerdere URLs mogelijk)
```
Dit is de "whitelist" van URLs waar Supabase naartoe MAG redirecten.
Je moet ALLE mogelijke auth callbacks toevoegen:
├─ /auth/callback → Email confirmaties, magic links
├─ /update-password → Na password reset
├─ /set-password → Nieuwe users (optioneel wachtwoord)
└─ /reset-password → Password reset pagina
Voor zowel localhost als productie!
```
---
## 🎯 Simpel Gezegd
1. **Site URL** = Waar draait je app?
- Tijdens development: `http://localhost:3000`
- Live op internet: `https://aispeedrun.nl`
2. **Redirect URLs** = Welke paginas mag Supabase bezoeken na login/reset?
- Voeg ALLE auth-gerelateerde URLs toe
- Voor zowel development als productie
3. **Email links** = Gebouwd met Site URL + token
- Als Site URL = localhost → emails gaan naar localhost ❌
- Als Site URL = aispeedrun.nl → emails gaan naar je website ✅
---
## 📝 Voorbeeld Flow in de Praktijk
```
[Gebruiker]
↓ Registreert op /login
[Jouw App]
↓ POST naar Supabase "maak account"
[Supabase]
↓ Stuurt email naar gebruiker
↓ Email link = [Site URL]/auth/callback?token=xyz
[Email Inbox]
↓ Gebruiker klikt link
[Browser]
↓ Gaat naar aispeedrun.nl/auth/callback?token=xyz
[Supabase]
↓ Checkt: staat "aispeedrun.nl/auth/callback" in Redirect URLs?
↓ JA ✅ → Verifieert token
[Jouw App - /auth/callback route]
↓ Token geldig? → Login gebruiker
↓ Nieuwe gebruiker met wachtwoord?
↓ JA → Redirect naar /epd/clients
[Gebruiker is ingelogd! 🎉]
```
---
## ❓ Veelgestelde Vragen
### Waarom krijg ik localhost links in productie emails?
→ Je Site URL staat nog op `http://localhost:3000` in Supabase. Wijzig naar `https://aispeedrun.nl`
### Waarom krijg ik "Invalid Redirect URL" errors?
→ De URL staat niet in je Redirect URLs lijst. Voeg hem toe in Supabase Dashboard.
### Kan ik zowel localhost als productie tegelijk gebruiken?
→ JA! Voeg beide toe aan Redirect URLs. Wissel alleen de Site URL afhankelijk van waar je test.
### Moet ik www. ook toevoegen?
→ Als je site bereikbaar is via `www.aispeedrun.nl`, voeg dan ook die URLs toe.
---
**Hopelijk is het nu duidelijk! 🚀**

View File

@@ -49,6 +49,40 @@ Alle foutmeldingen zijn nu duidelijker en helpen je beter op weg:
--- ---
## 📋 Voor Bestaande Magic Link Gebruikers
Heb je je eerder aangemeld met een magic link en wil je nu ook met een wachtwoord kunnen inloggen? Dat kan!
### Hoe stel je een wachtwoord in?
1. **Ga naar de wachtwoord reset pagina**
- Klik op "Wachtwoord vergeten?" op de login pagina
- Of ga direct naar `/reset-password`
2. **Vul je email in**
- Gebruik hetzelfde emailadres waarmee je via magic link inlogt
- Klik op "Stuur Reset Link"
3. **Check je inbox**
- Je ontvangt binnen enkele minuten een email
- Klik op de link in de email (geldig voor 1 uur)
4. **Stel je wachtwoord in**
- Kies een sterk wachtwoord (minimaal 8 tekens)
- Bevestig het wachtwoord
- Klaar!
### Na het instellen van een wachtwoord
Je kunt nu kiezen hoe je wilt inloggen:
- 🔑 **Met wachtwoord** - Sneller, direct inloggen zonder email te checken
- ✉️ **Met magic link** - Blijft ook gewoon werken zoals voorheen
Beide methodes blijven beschikbaar, je kiest zelf wat je het prettigst vindt!
---
## 🚀 Voor Ontwikkelaars ## 🚀 Voor Ontwikkelaars
De volgende functies zijn toegevoegd aan `lib/auth/client.ts`: De volgende functies zijn toegevoegd aan `lib/auth/client.ts`:

View File

@@ -28,12 +28,38 @@ Deze directory bevat HTML email templates die gebruikt kunnen worden in Supabase
## Hoe te gebruiken in Supabase ## Hoe te gebruiken in Supabase
### Stap 1: Site URL Configureren
**BELANGRIJK:** Zorg eerst dat je Site URL correct is ingesteld, anders verwijzen alle email links naar localhost!
1. Log in op je Supabase Dashboard 1. Log in op je Supabase Dashboard
2. Ga naar **Authentication****Email Templates** 2. Ga naar **Authentication****URL Configuration**
3. Selecteer het juiste template type (Confirm signup of Reset Password) 3. Stel de **Site URL** in:
4. Kopieer de volledige HTML inhoud van het corresponderende `.html` bestand - **Development:** `http://localhost:3000`
5. Plak deze in het Supabase email template veld - **Production:** `https://aispeedrun.nl`
6. Klik op **Save** 4. Voeg de volgende **Redirect URLs** toe (één per regel):
```
http://localhost:3000/auth/callback
http://localhost:3000/update-password
http://localhost:3000/set-password
http://localhost:3000/reset-password
https://aispeedrun.nl/auth/callback
https://aispeedrun.nl/update-password
https://aispeedrun.nl/set-password
https://aispeedrun.nl/reset-password
```
**Note:** Je kunt zowel localhost als productie URLs toevoegen, zodat beide omgevingen werken.
5. Klik op **Save**
### Stap 2: Email Templates Instellen
1. Ga naar **Authentication** → **Email Templates**
2. Selecteer het juiste template type (Confirm signup of Reset Password)
3. Kopieer de volledige HTML inhoud van het corresponderende `.html` bestand
4. Plak deze in het Supabase email template veld
5. Klik op **Save**
## Design Kenmerken ## Design Kenmerken