Refactor high-complexity React components in Dify frontend. Use when `pnpm analyze-component...
npx skills add WebSmartTeam/COR-CODE --skill "supabase-auth-config"
Install specific skill from multi-skill repository
# Description
Configure Supabase authentication with single callback URL pattern. Covers redirect URLs, auth flow types (recovery, signup, email_change), and the type parameter routing pattern. Triggers: supabase auth, auth callback, redirect URL, password reset not working, auth configuration, login redirect, signup flow.
# SKILL.md
name: supabase-auth-config
description: Configure Supabase authentication with single callback URL pattern. Covers redirect URLs, auth flow types (recovery, signup, email_change), and the type parameter routing pattern. Triggers: supabase auth, auth callback, redirect URL, password reset not working, auth configuration, login redirect, signup flow.
updated: 2025-01-18
Supabase Auth Configuration
🚨 CRITICAL: Redirect URL Configuration
WRONG - Adding multiple redirect URLs:
https://example.com/auth/callback
https://example.com/auth/reset-password
https://example.com/auth/verify-email
https://example.com/auth/signup-confirm
CORRECT - Single callback URL handles ALL flows:
https://example.com/auth/callback
Why Single Callback?
All auth flows need to exchange the code for a session FIRST. The /auth/callback route:
1. Receives the auth code from Supabase
2. Exchanges it for a session
3. THEN routes based on the type parameter
Having separate routes is redundant - they'd all need the same code exchange logic.
Supabase Dashboard Settings
Authentication → URL Configuration:
- Site URL: https://yourdomain.com
- Redirect URLs: https://yourdomain.com/auth/callback
For local development, add:
- http://localhost:3000/auth/callback
The Callback Route Pattern
// app/auth/callback/route.ts (Next.js App Router)
import { createClient } from '@/utils/supabase/server'
import { NextResponse } from 'next/server'
export async function GET(request: Request) {
const { searchParams, origin } = new URL(request.url)
const code = searchParams.get('code')
const type = searchParams.get('type')
const next = searchParams.get('next') ?? '/dashboard'
if (code) {
const supabase = await createClient()
const { error } = await supabase.auth.exchangeCodeForSession(code)
if (!error) {
// Route based on auth flow type
switch (type) {
case 'recovery':
return NextResponse.redirect(`${origin}/auth/reset-password`)
case 'signup':
return NextResponse.redirect(`${origin}/dashboard?welcome=true`)
case 'email_change':
return NextResponse.redirect(`${origin}/dashboard/profile?email_updated=true`)
default:
// Magic link or other - go to dashboard
return NextResponse.redirect(`${origin}${next}`)
}
}
}
// Auth error - redirect to error page
return NextResponse.redirect(`${origin}/auth/error`)
}
Auth Flow Types
| Type | Trigger | Redirect To |
|---|---|---|
recovery |
Password reset email | /auth/reset-password |
signup |
Email confirmation | /dashboard?welcome=true |
email_change |
Email change confirmation | /dashboard/profile?email_updated=true |
magiclink |
Magic link login | /dashboard |
| (none) | Regular magic link | /dashboard |
Common Bug: Ignoring Type Parameter
The bug: Callback route ignores type parameter, sends ALL users to /dashboard.
The problem: Password reset users never reach /auth/reset-password - they can't set their new password!
The fix: Always check type parameter and route accordingly (see pattern above).
Reset Password Page
After routing to /auth/reset-password, user needs a form to set new password:
// app/auth/reset-password/page.tsx
'use client'
import { createClient } from '@/utils/supabase/client'
import { useState } from 'react'
import { useRouter } from 'next/navigation'
export default function ResetPasswordPage() {
const [password, setPassword] = useState('')
const [error, setError] = useState('')
const router = useRouter()
const supabase = createClient()
const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault()
const { error } = await supabase.auth.updateUser({
password: password
})
if (error) {
setError(error.message)
} else {
router.push('/dashboard?password_updated=true')
}
}
return (
<form onSubmit={handleSubmit}>
<input
type="password"
value={password}
onChange={(e) => setPassword(e.target.value)}
placeholder="New password"
minLength={8}
required
/>
{error && <p className="text-red-500">{error}</p>}
<button type="submit">Update Password</button>
</form>
)
}
Email Templates (Supabase Dashboard)
Authentication → Email Templates
Ensure redirect URLs use your callback with type:
- Confirm signup: {{ .SiteURL }}/auth/callback?type=signup
- Reset password: {{ .SiteURL }}/auth/callback?type=recovery
- Magic link: {{ .SiteURL }}/auth/callback
- Change email: {{ .SiteURL }}/auth/callback?type=email_change
Checklist
- [ ] Single redirect URL in Supabase dashboard:
/auth/callback - [ ] Callback route handles
typeparameter - [ ] Recovery type routes to reset password page
- [ ] Reset password page exists with form
- [ ] Email templates use correct type parameters
- [ ] Local dev URL added if needed
# Supported AI Coding Agents
This skill is compatible with the SKILL.md standard and works with all major AI coding agents:
Learn more about the SKILL.md standard and how to use these skills with your preferred AI coding agent.