supabase-auth-ssr-setup
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseSupabase Auth SSR Setup
Supabase Auth SSR 配置指南
Overview
概述
Configure Supabase Authentication for Next.js App Router with server-side rendering (SSR), secure cookie-based sessions, middleware protection, and complete authentication flows.
为Next.js App Router配置Supabase认证,包含服务端渲染(SSR)、基于安全Cookie的会话、中间件保护及完整的认证流程。
Installation and Configuration Steps
安装与配置步骤
1. Install Dependencies
1. 安装依赖
Install Supabase SSR package for Next.js:
bash
npm install @supabase/supabase-js @supabase/ssr为Next.js安装Supabase SSR包:
bash
npm install @supabase/supabase-js @supabase/ssr2. Create Supabase Client Utilities
2. 创建Supabase客户端工具
Create three client configurations for different contexts (browser, server, middleware):
File: (Browser client)
lib/supabase/client.tsUse the template from . This client:
assets/supabase-client.ts- Runs only in browser context
- Uses secure cookies for session storage
- Automatically refreshes tokens
File: (Server component client)
lib/supabase/server.tsUse the template from . This client:
assets/supabase-server.ts- Creates server-side Supabase client with cookie access
- Used in Server Components and Server Actions
- Provides read-only cookie access for security
File: (Middleware client)
lib/supabase/middleware.tsUse the template from . This client:
assets/supabase-middleware.ts- Used in Next.js middleware for route protection
- Can update cookies in responses
- Refreshes sessions on route navigation
针对不同上下文(浏览器、服务端、中间件)创建三种客户端配置:
文件:(浏览器端客户端)
lib/supabase/client.ts使用中的模板。该客户端:
assets/supabase-client.ts- 仅在浏览器上下文运行
- 使用安全Cookie存储会话
- 自动刷新令牌
文件:(服务端组件客户端)
lib/supabase/server.ts使用中的模板。该客户端:
assets/supabase-server.ts- 创建可访问Cookie的服务端Supabase客户端
- 用于服务端组件和服务端操作(Server Actions)
- 提供只读Cookie访问以保障安全
文件:(中间件客户端)
lib/supabase/middleware.ts使用中的模板。该客户端:
assets/supabase-middleware.ts- 用于Next.js中间件实现路由保护
- 可在响应中更新Cookie
- 路由导航时刷新会话
3. Configure Environment Variables
3. 配置环境变量
Add Supabase credentials to :
.env.localenv
NEXT_PUBLIC_SUPABASE_URL=your-project-url
NEXT_PUBLIC_SUPABASE_ANON_KEY=your-anon-keyGet these values from your Supabase project settings under API.
Security note: The anon key is safe to expose publicly. Real security comes from Row Level Security (RLS) policies in your database.
将Supabase凭据添加到:
.env.localenv
NEXT_PUBLIC_SUPABASE_URL=your-project-url
NEXT_PUBLIC_SUPABASE_ANON_KEY=your-anon-key可从Supabase项目设置的API页面获取这些值。
安全说明:匿名密钥可以安全地公开暴露。真正的安全性来自数据库中的行级安全(RLS)策略。
4. Create Middleware for Route Protection
4. 创建路由保护中间件
Create in project root using the template from . This middleware:
middleware.tsassets/middleware.ts- Refreshes Supabase session on every request
- Protects routes matching specified patterns
- Redirects unauthenticated users to login
- Allows public routes to bypass authentication
Configure protected routes by adjusting the matcher pattern:
typescript
export const config = {
matcher: [
'/dashboard/:path*',
'/settings/:path*',
'/api/protected/:path*',
],
};使用中的模板在项目根目录创建。该中间件:
assets/middleware.tsmiddleware.ts- 每次请求时刷新Supabase会话
- 保护匹配指定规则的路由
- 将未认证用户重定向至登录页
- 允许公开路由绕过认证
通过调整匹配规则配置受保护路由:
typescript
export const config = {
matcher: [
'/dashboard/:path*',
'/settings/:path*',
'/api/protected/:path*',
],
};5. Create Authentication Utilities
5. 创建认证工具函数
Create helper functions for common auth operations using templates from :
assets/auth-utils.tsGet current user server-side:
typescript
import { getCurrentUser } from '@/lib/auth/utils';
const user = await getCurrentUser();Require authentication:
typescript
import { requireAuth } from '@/lib/auth/utils';
const user = await requireAuth(); // Throws error if not authenticatedGet session:
typescript
import { getSession } from '@/lib/auth/utils';
const session = await getSession();These utilities simplify authentication checks in Server Components and Server Actions.
使用中的模板创建通用认证操作的辅助函数:
assets/auth-utils.ts服务端获取当前用户:
typescript
import { getCurrentUser } from '@/lib/auth/utils';
const user = await getCurrentUser();强制认证:
typescript
import { requireAuth } from '@/lib/auth/utils';
const user = await requireAuth(); // 未认证时抛出错误获取会话:
typescript
import { getSession } from '@/lib/auth/utils';
const session = await getSession();这些工具简化了服务端组件和服务端操作中的认证检查。
6. Create Logout Server Action
6. 创建登出服务端操作
Create using the template from . This provides:
app/actions/auth.tsassets/auth-actions.tsLogout action:
- Clears Supabase session
- Removes auth cookies
- Redirects to home page
Use in client components:
typescript
import { logout } from '@/app/actions/auth';
<button onClick={() => logout()}>
Sign Out
</button>使用中的模板创建。该文件提供:
assets/auth-actions.tsapp/actions/auth.ts登出操作:
- 清除Supabase会话
- 删除认证Cookie
- 重定向至首页
在客户端组件中使用:
typescript
import { logout } from '@/app/actions/auth';
<button onClick={() => logout()}>
退出登录
</button>7. Create Login Page
7. 创建登录页面
Create using the template from . This page:
app/login/page.tsxassets/login-page.tsx- Provides email/password login form
- Handles magic link authentication
- Supports OAuth providers (Google, GitHub, etc.)
- Redirects authenticated users
- Shows error messages
Customize the login page:
- Add your branding and styling
- Enable/disable OAuth providers
- Add password reset link
- Include sign-up link
使用中的模板创建。该页面:
assets/login-page.tsxapp/login/page.tsx- 提供邮箱/密码登录表单
- 处理魔法链接认证
- 支持OAuth提供商(Google、GitHub等)
- 已认证用户自动重定向
- 显示错误信息
自定义登录页面:
- 添加品牌标识和样式
- 启用/禁用OAuth提供商
- 添加密码重置链接
- 包含注册链接
8. Create Protected Route Example
8. 创建受保护路由示例
Create a protected dashboard page at using the template from . This demonstrates:
app/dashboard/page.tsxassets/dashboard-page.tsx- Using to protect routes
requireAuth() - Displaying user information
- Including logout functionality
- Server-side authentication check
使用中的模板在创建受保护的仪表盘页面。该示例展示:
assets/dashboard-page.tsxapp/dashboard/page.tsx- 使用保护路由
requireAuth() - 显示用户信息
- 包含登出功能
- 服务端认证检查
9. Set Up Callback Route for OAuth
9. 配置OAuth回调路由
If using OAuth providers, create using the template from . This handler:
app/auth/callback/route.tsassets/auth-callback-route.ts- Exchanges OAuth code for session
- Sets secure session cookies
- Redirects to intended destination
- Handles OAuth errors
Configure OAuth in Supabase dashboard:
- Go to Authentication > Providers
- Enable desired providers (Google, GitHub, etc.)
- Add redirect URL:
https://your-domain.com/auth/callback
若使用OAuth提供商,使用中的模板创建。该处理器:
assets/auth-callback-route.tsapp/auth/callback/route.ts- 用OAuth代码交换会话
- 设置安全会话Cookie
- 重定向至目标页面
- 处理OAuth错误
在Supabase控制台配置OAuth:
- 进入认证 > 提供商
- 启用所需提供商(Google、GitHub等)
- 添加重定向URL:
https://your-domain.com/auth/callback
Authentication Flow
认证流程
Login Flow
登录流程
- User visits
/login - User enters credentials or clicks OAuth
- Supabase authenticates and sets session cookie
- User redirected to dashboard or intended page
- Middleware validates session on protected routes
- 用户访问
/login - 用户输入凭据或点击OAuth按钮
- Supabase完成认证并设置会话Cookie
- 用户被重定向至仪表盘或目标页面
- 中间件在受保护路由上验证会话
Session Refresh Flow
会话刷新流程
- User navigates to any route
- Middleware runs and refreshes session if needed
- Updated session cookie sent to client
- Server Components have access to fresh session
- 用户导航至任意路由
- 中间件运行并在需要时刷新会话
- 更新后的会话Cookie发送至客户端
- 服务端组件可获取最新会话
Logout Flow
登出流程
- User clicks logout button
- Server Action calls Supabase
signOut() - Session and cookies cleared
- User redirected to home page
- 用户点击登出按钮
- 服务端操作调用Supabase
signOut() - 会话和Cookie被清除
- 用户被重定向至首页
Route Protection Patterns
路由保护模式
Protecting Individual Pages
保护单个页面
Use at the top of Server Components:
requireAuth()typescript
import { requireAuth } from '@/lib/auth/utils';
export default async function ProtectedPage() {
const user = await requireAuth();
return <div>Hello {user.email}</div>;
}在服务端组件顶部使用:
requireAuth()typescript
import { requireAuth } from '@/lib/auth/utils';
export default async function ProtectedPage() {
const user = await requireAuth();
return <div>你好,{user.email}</div>;
}Protecting Route Groups
保护路由组
Use Next.js route groups with layout:
typescript
// app/(protected)/layout.tsx
import { requireAuth } from '@/lib/auth/utils';
export default async function ProtectedLayout({ children }) {
await requireAuth();
return <>{children}</>;
}All routes in group are automatically protected.
(protected)使用Next.js路由组和布局:
typescript
// app/(protected)/layout.tsx
import { requireAuth } from '@/lib/auth/utils';
export default async function ProtectedLayout({ children }) {
await requireAuth();
return <>{children}</>;
}(protected)Optional Authentication
可选认证
Check if user is logged in without requiring it:
typescript
import { getCurrentUser } from '@/lib/auth/utils';
export default async function OptionalAuthPage() {
const user = await getCurrentUser();
return (
<div>
{user ? `Welcome ${user.email}` : 'Please log in'}
</div>
);
}检查用户是否登录但不强制要求:
typescript
import { getCurrentUser } from '@/lib/auth/utils';
export default async function OptionalAuthPage() {
const user = await getCurrentUser();
return (
<div>
{user ? `欢迎,${user.email}` : '请登录'}
</div>
);
}Server Actions with Authentication
带认证的服务端操作
Protect Server Actions using :
requireAuth()typescript
'use server';
import { requireAuth } from '@/lib/auth/utils';
import { createServerClient } from '@/lib/supabase/server';
export async function updateProfile(formData: FormData) {
const user = await requireAuth();
const supabase = createServerClient();
const { error } = await supabase
.from('profiles')
.update({ name: formData.get('name') })
.eq('id', user.id);
if (error) throw error;
}使用保护服务端操作:
requireAuth()typescript
'use server';
import { requireAuth } from '@/lib/auth/utils';
import { createServerClient } from '@/lib/supabase/server';
export async function updateProfile(formData: FormData) {
const user = await requireAuth();
const supabase = createServerClient();
const { error } = await supabase
.from('profiles')
.update({ name: formData.get('name') })
.eq('id', user.id);
if (error) throw error;
}Troubleshooting
故障排除
Session not persisting: Verify cookies are being set. Check browser dev tools > Application > Cookies. Ensure domain matches.
Middleware redirect loop: Check matcher pattern doesn't include login page. Verify is accessible without auth.
/loginOAuth redirect fails: Confirm callback URL matches exactly in Supabase dashboard. Check for trailing slashes.
TypeScript errors: Install types: . Ensure is typed correctly.
npm install -D @types/nodesupabase401 errors on protected routes: Session may be expired. Check Supabase dashboard > Authentication > Settings for session timeout.
会话不持久:验证Cookie是否已设置。查看浏览器开发者工具 > 应用 > Cookie,确保域名匹配。
中间件重定向循环:检查匹配规则是否包含登录页。确保无需认证即可访问。
/loginOAuth重定向失败:确认回调URL与Supabase控制台中的设置完全一致,注意避免末尾斜杠。
TypeScript错误:安装类型定义:。确保的类型配置正确。
npm install -D @types/nodesupabase受保护路由返回401错误:会话可能已过期。查看Supabase控制台 > 认证 > 设置中的会话超时时间。
Resources
资源
scripts/
scripts/
No executable scripts needed for this skill.
本技能无需可执行脚本。
references/
references/
- - Common auth patterns and best practices for Next.js + Supabase
authentication-patterns.md - - Security best practices for session handling and cookie configuration
security-considerations.md
- - Next.js + Supabase的通用认证模式与最佳实践
authentication-patterns.md - - 会话处理与Cookie配置的安全最佳实践
security-considerations.md
assets/
assets/
- - Browser-side Supabase client configuration
supabase-client.ts - - Server-side Supabase client for Server Components
supabase-server.ts - - Middleware Supabase client for session refresh
supabase-middleware.ts - - Next.js middleware for route protection
middleware.ts - - Helper functions for authentication checks
auth-utils.ts - - Server Actions for logout and other auth operations
auth-actions.ts - - Complete login page with email/password and OAuth
login-page.tsx - - Example protected page using requireAuth
dashboard-page.tsx - - OAuth callback handler for provider authentication
auth-callback-route.ts
- - 浏览器端Supabase客户端配置
supabase-client.ts - - 服务端组件专用的服务端Supabase客户端
supabase-server.ts - - 用于会话刷新的中间件Supabase客户端
supabase-middleware.ts - - 用于路由保护的Next.js中间件
middleware.ts - - 认证检查的辅助函数
auth-utils.ts - - 登出及其他认证操作的服务端操作
auth-actions.ts - - 包含邮箱/密码和OAuth的完整登录页
login-page.tsx - - 使用requireAuth的受保护页面示例
dashboard-page.tsx - - 提供商认证的OAuth回调处理器
auth-callback-route.ts