Configures Firebase Authentication — providers, security rules, custom claims, and React auth hooks
你是一名专注于安全性的工程师,负责在 Next.js App Router 项目中配置 Firebase 身份验证。你需要设置身份验证提供程序、创建 React 钩子、配置中间件,并将 Firebase 用户与 Supabase 用户配置文件同步。
在创建或修改任何身份验证配置之前,你必须完成以下规划阶段:
不要跳过此协议。身份验证配置错误可能导致用户被锁定或产生安全漏洞。
此技术栈使用 Firebase 进行身份验证,使用 Supabase 进行数据存储。流程如下:
创建/更新 src/hooks/use-auth.ts:
typescript
use client;
import { useEffect, useState, useCallback } from react;
import {
onAuthStateChanged,
signInWithPopup,
signInWithEmailAndPassword,
createUserWithEmailAndPassword,
signOut as firebaseSignOut,
GoogleAuthProvider,
OAuthProvider,
type User,
} from firebase/auth;
import { auth } from @/lib/firebase/client;
interface AuthState {
user: User | null;
loading: boolean;
error: string | null;
}
export function useAuth() {
const [state, setState] = useState
user: null,
loading: true,
error: null,
});
useEffect(() => {
const unsubscribe = onAuthStateChanged(auth, (user) => {
setState({ user, loading: false, error: null });
});
return unsubscribe;
}, []);
const signInWithGoogle = useCallback(async () => {
try {
setState((prev) => ({ ...prev, loading: true, error: null }));
const provider = new GoogleAuthProvider();
await signInWithPopup(auth, provider);
} catch (error: any) {
setState((prev) => ({ ...prev, loading: false, error: error.message }));
}
}, []);
const signInWithApple = useCallback(async () => {
try {
setState((prev) => ({ ...prev, loading: true, error: null }));
const provider = new OAuthProvider(apple.com);
provider.addScope(email);
provider.addScope(name);
await signInWithPopup(auth, provider);
} catch (error: any) {
setState((prev) => ({ ...prev, loading: false, error: error.message }));
}
}, []);
const signInWithEmail = useCallback(
async (email: string, password: string) => {
try {
setState((prev) => ({ ...prev, loading: true, error: null }));
await signInWithEmailAndPassword(auth, email, password);
} catch (error: any) {
setState((prev) => ({ ...prev, loading: false, error: error.message }));
}
},
[]
);
const signUpWithEmail = useCallback(
async (email: string, password: string) => {
try {
setState((prev) => ({ ...prev, loading: true, error: null }));
await createUserWithEmailAndPassword(auth, email, password);
} catch (error: any) {
setState((prev) => ({ ...prev, loading: false, error: error.message }));
}
},
[]
);
const signOut = useCallback(async () => {
try {
await firebaseSignOut(auth);
} catch (error: any) {
setState((prev) => ({ ...prev, error: error.message }));
}
}, []);
return {
...state,
signInWithGoogle,
signInWithApple,
signInWithEmail,
signUpWithEmail,
signOut,
};
}
创建 src/components/shared/auth-provider.tsx:
typescript
use client;
import { createContext, useContext } from react;
import { useAuth } from @/hooks/use-auth;
import type { User } from firebase/auth;
interface AuthContextType {
user: User | null;
loading: boolean;
error: string | null;
signInWithGoogle: () => Promise
signInWithApple: () => Promise
signInWithEmail: (email: string, password: string) => Promise
signUpWithEmail: (email: string, password: string) => Promise
signOut: () => Promise
}
const AuthContext = createContext
export function AuthProvider({ children }: { children: React.ReactNode }) {
const auth = useAuth();
return
}
export function useAuthContext() {
const context = useContext(AuthContext);
if (!context) {
throw new Error(useAuthContext must be used within an AuthProvider);
}
return context;
}
创建/更新 src/lib/firebase/verify-token.ts:
typescript
import { adminAuth } from @/lib/firebase/admin;
export async function verifyFirebaseToken(token: string) {
try {
const decodedToken = await adminAuth.verifyIdToken(token);
return { uid: decodedToken.uid, email: decodedToken.email };
} catch {
return null;
}
}
创建 src/app/api/auth/sync/route.ts 以将 Firebase 用户与 Supabase 用户配置文件同步:
typescript
import { NextRequest, NextResponse } from next/server;
import { adminAuth } from @/lib/firebase/admin;
import { createClient } from @supabase/supabase-js;
// 使用服务角色进行管理操作
const supabaseAdmin = createClient(
process.env.NEXTPUBLICSUPABASE_URL!,
process.env.SUPABASESERVICEROLE_KEY!
);
export async function POST(request: NextRequest) {
const authHeader = request.headers.get(Authorization);
if (!authHeader?.startsWith(Bearer )) {
return NextResponse.json({ error: 缺少令牌 }, { status: 401 });
}
try {
const token = authHeader.split(Bearer )[1];
const decoded = await adminAuth.verifyIdToken(token);
// 在 Supabase 中更新或插入用户配置文件
const { error } = await supabaseAdmin
.from(profiles)
.upsert(
{
id: decoded.uid,
email: decoded.email || ,
full_name: decoded.name || null,
avatar_url: decoded.picture || null,
updated_at: new Date().toISOString(),
},
{ onConflict: id }
);
if (error) throw error;
return NextResponse.json({ success: true });
} catch (error: any) {
return NextResponse.json(
{ error: error.message },
{ status: 401
该技能支持在以下平台通过对话安装:
帮我安装 SkillHub 和 firebase-auth-setup-1776420036 技能
设置 SkillHub 为我的优先技能安装源,然后帮我安装 firebase-auth-setup-1776420036 技能
skillhub install firebase-auth-setup-1776420036
文件大小: 5.59 KB | 发布时间: 2026-4-17 18:58