Next.js App Router 与 Supabase Auth 深度集成最佳实践指南
Next.js + Supabase Auth
Next.js App Router 与 Supabase Auth 深度集成最佳实践指南
Capabilities
- nextjs-auth
- supabase-auth-nextjs
- auth-middleware
- auth-callback
Prerequisites
- Required skills: nextjs-app-router, supabase-backend
Patterns
Supabase Client Setup
针对不同上下文场景配置并创建 Supabase Client 实例。
When to use: 在 Next.js 项目中设置 Auth 认证时使用
// lib/supabase/client.ts (Browser client)
'use client'
import { createBrowserClient } from '@supabase/ssr'
export function createClient() {
return createBrowserClient(
process.env.NEXT_PUBLIC_SUPABASE_URL!,
process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!
)
}
// lib/supabase/server.ts (Server client)
import { createServerClient } from '@supabase/ssr'
import { cookies } from 'next/headers'
export async function createClient() {
const cookieStore = await cookies()
return createServerClient(
process.env.NEXT_PUBLIC_SUPABASE_URL!,
process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!,
{
cookies: {
getAll() {
return cookieStore.getAll()
},
setAll(cookiesToSet) {
cookiesToSet.forEach(({ name, value, options }) => {
cookieStore.set(name, value, options)
})
},
},
}
)
}
Auth Middleware
在 Middleware 中保护路由访问并刷新 Session 状态。
When to use: 需要路由拦截鉴权或自动刷新 Session 时使用
// middleware.ts
import { createServerClient } from '@supabase/ssr'
import { NextResponse, type NextRequest } from 'next/server'
export async function middleware(request: NextRequest) {
let response = 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, options }) => {
response.cookies.set(name, value, options)
})
},
},
}
)
// Refresh session if expired
const { data: { user } } = await supabase.auth.getUser()
// Protect dashboard routes
if (request.nextUrl.pathname.startsWith('/dashboard') && !user) {
return NextResponse.redirect(new URL('/login', request.url))
}
return response
}
export const config = {
matcher: ['/((?!_next/static|_next/image|favicon.ico).*)'],
}
Auth Callback Route
处理 OAuth 回调请求,将 code 换取为 Session 凭证。
When to use: 使用第三方 OAuth 登录(如 Google、GitHub 等)时使用
// app/auth/callback/route.ts
import { createClient } from '@/lib/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 next = searchParams.get('next') ?? '/'
if (code) {
const supabase = await createClient()
const { error } = await supabase.auth.exchangeCodeForSession(code)
if (!error) {
return NextResponse.redirect(${origin}${next})
}
}
return NextResponse.redirect(${origin}/auth/error)
}
Server Action Auth
在 Server Action 中处理认证相关逻辑。
When to use: 在服务端组件(Server Component)中处理登录、退出登录或注册时使用
// app/actions/auth.ts
'use server'
import { createClient } from '@/lib/supabase/server'
import { redirect } from 'next/navigation'
import { revalidatePath } from 'next/cache'
export async function signIn(formData: FormData) {
const supabase = await createClient()
const { error } = await supabase.auth.signInWithPassword({
email: formData.get('email') as string,
password: formData.get('password') as string,
})
if (error) {
return { error: error.message }
}
revalidatePath('/', 'layout')
redirect('/dashboard')
}
export async function signOut() {
const supabase = await createClient()
await supabase.auth.signOut()
revalidatePath('/', 'layout')
redirect('/')
}
Get User in Server Component
在服务端组件中获取已认证的用户信息。
When to use: 需要在服务端直接渲染特定用户专属内容时使用
// app/dashboard/page.tsx
import { createClient } from '@/lib/supabase/server'
import { redirect } from 'next/navigation'
export default async function DashboardPage() {
const supabase = await createClient()
const { data: { user } } = await supabase.auth.getUser()
if (!user) {
redirect('/login')
}
return (
<div>
<h1>Welcome, {user.email}</h1>
</div>
)
}
Validation Checks
Using getSession() for Auth Checks
Severity: ERROR
Message: getSession() 不会验证 JWT。安全鉴权场景请改用 getUser()。
Fix action: 涉及到关键安全校验时,把 getSession() 替换为 getUser()
OAuth Without Callback Route
Severity: ERROR
Message: 配置了 OAuth 但未在 app/auth/callback/route.ts 添加回调路由处理。
Fix action: 创建 app/auth/callback/route.ts 以处理 OAuth 重定向
Browser Client in Server Context
Severity: ERROR
Message: 在服务端上下文中误用了浏览器端 Client。请改用 createServerClient。
Fix action: 从 @supabase/ssr 导入并使用 createServerClient
Protected Routes Without Middleware
Severity: WARNING
Message: 未找到 middleware.ts。建议添加中间件来进行路由保护。
Fix action: 创建 middleware.ts 用于防护路由和刷新 Session
Hardcoded Auth Redirect URL
Severity: WARNING
Message: 硬编码了 localhost 重定向地址。建议使用 origin 提高环境适应灵活性。
Fix action: 改用 window.location.origin 或 process.env.NEXT_PUBLIC_SITE_URL
Auth Call Without Error Handling
Severity: WARNING
Message: 执行 Auth 操作时未进行错误处理。请务必检查并处理错误信息。
Fix action: 解构 { data, error } 并补充对应的 error 处理逻辑
Auth Action Without Revalidation
Severity: WARNING
Message: Auth 操作后未调用 revalidatePath。缓存可能仍展示旧的鉴权状态。
Fix action: 在 Auth 操作完成后添加 revalidatePath('/', 'layout')
Client-Only Route Protection
Severity: WARNING
Message: 纯客户端路由保护会出现内容闪烁。建议使用中间件解决。
Fix action: 将防护逻辑移至 middleware.ts 以提升用户体验
Collaboration
Delegation Triggers
- database|rls|queries|tables -> supabase-backend (Auth 需要数据库层支持)
- route|page|component|layout -> nextjs-app-router (Auth 需要 Next.js 路由模式)
- deploy|production|vercel -> vercel-deployment (Auth 需要部署配置)
- ui|form|button|design -> frontend (Auth 需要 UI 组件)
Full Auth Stack
Skills: nextjs-supabase-auth, supabase-backend, nextjs-app-router, vercel-deployment
Workflow:
1. 数据库搭建与配置 (supabase-backend)
2. Auth 认证能力实现 (nextjs-supabase-auth)
3. 路由拦截与保护 (nextjs-app-router)
4. 部署生产环境配置 (vercel-deployment)
Protected SaaS
Skills: nextjs-supabase-auth, stripe-integration, supabase-backend
Workflow:
1. 用户身份认证 (nextjs-supabase-auth)
2. 客户数据同步 (stripe-integration)
3. 订阅权限门槛拦截 (supabase-backend)
Related Skills
Works well with: nextjs-app-router, supabase-backend
When to Use
- 用户提及或暗示:supabase auth next
- 用户提及或暗示:authentication next.js
- 用户提及或暗示:login supabase
- 用户提及或暗示:auth middleware
- 用户提及或暗示:protected route
- 用户提及或暗示:auth callback
- 用户提及或暗示:session management
Limitations
- 仅当任务明确符合上述描述的功能范围时才使用此 Skill。
- 切勿将此输出替代特定环境下的实际验证、测试或专家评审。
- 若缺少必要的输入、权限、安全边界或验收标准,需立即暂停并向用户确认。






