ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

create-t3-app 中的 NextAuth.js 集成指南:从会话上下文到受保护路由的完整实战

create-t3-app 中的 NextAuth.js 集成指南:从会话上下文到受保护路由的完整实战 create-t3-app 中的 NextAuth.js 集成指南从会话上下文到受保护路由的完整实战【免费下载链接】create-t3-appThe best way to start a full-stack, typesafe Next.js app项目地址: https://gitcode.com/gh_mirrors/cr/create-t3-app本篇技术指南聚焦 create-t3-app 脚手架对 NextAuth.js 的完整集成方案涵盖 SessionProvider 上下文注入、session.user.id的类型安全扩展、与 tRPC 的protectedProcedure组合、Prisma/Drizzle 适配器的底层实现以及 Discord OAuth 提供商的落地配置。读完本篇你将掌握如何在新生成的 T3 应用中直接使用这套开箱即用的认证体系并能独立扩展角色字段、新增 OAuth 提供商。为什么 create-t3-app 选择 NextAuth.js 作为默认认证方案在 Next.js 应用中接入一套完整的认证系统往往意味着要自己处理 OAuth 流程、会话管理、数据库持久化与 CSRF 防护等一系列安全细节。NextAuth.js现归属 Auth.js 生态恰好把这一整套复杂性封装成了开箱即用的方案它内置了覆盖主流平台的 OAuth 提供商列表并为大量数据库和 ORM 提供了官方适配器。当你在 create-t3-app 交互式命令行中选择 NextAuth.js 选项后脚手架会通过 nextAuthInstaller 自动完成三件事写入next-auth依赖若同时选择了 Prisma 或 Drizzle则追加对应的适配器包auth/prisma-adapter或auth/drizzle-adapter复制 App Router 的 API 路由处理器到src/app/api/auth/[...nextauth]/route.ts依据所选数据库从 模板目录 中挑选base.ts、with-prisma.ts或with-drizzle.ts作为src/server/auth/config.ts并生成src/server/auth/index.ts。也就是说你拿到的是一个已经完成会话与会话状态接线、随时可以填入 Discord 凭据即可运行的认证模块。SessionProvider把会话状态注入整个应用Pages Router 中的上下文注入在采用 Pages Router 的项目里应用入口pages/_app.tsx会被包裹在一个 SessionProvider 中SessionProvider session{session} Component {...pageProps} / /SessionProvider这个上下文提供器让应用中的任何组件都能通过useSession钩子读取会话数据而无需层层传递 props。典型的非受保护页面用法如下import { useSession } from next-auth/react; const User () { const { data: session } useSession(); if (!session) { // Manejar el estado no autenticado, ejemplo: renderizar un componente SignIn return SignIn /; } return pBienvenido {session.user.name}!/p; };当session为空时说明用户尚未登录此时应渲染登录引导组件否则即可安全地读取session.user.name等字段进行页面渲染。App Router 中的对应封装对于使用 App Router 的项目模板在src/app/api/auth/[...nextauth]/route.ts中只做了一件事——把~/server/auth导出的handlers中的GET与POST原样导出为路由处理器import { handlers } from ~/server/auth; export const { GET, POST } handlers;而认证的核心配置集中在src/server/auth/index.ts它调用NextAuth(authConfig)生成handlers、signIn、signOut并用 React 的cache对auth函数做服务端缓存Server Component 中调用auth()即可获取会话与 Pages Router 的getServerSession效果对齐。把user.id纳入 Session回调 模块增强create-t3-app默认在 NextAuth.js 配置中启用了 session 回调把用户 ID 塞进session对象这样前端和后端都能直接通过session.user.id定位当前用户callbacks: { session({ session, user }) { if (session.user) { session.user.id user.id; } return session; }, },与之配套的是一个类型声明文件确保session.user.id在 TypeScript 下可写、有类型提示import { DefaultSession } from next-auth; declare module next-auth { interface Session { user?: { id: string; } DefaultSession[user]; } }这正是 NextAuth.js 官方的 Module Augmentation注释中还预留了role: UserRole的扩展位。同样的模式可以扩展任意字段例如给session追加role但请务必牢记不要用它把敏感数据如 token、密码哈希塞进客户端可见的session对象。与 tRPC 组合两步构建受保护过程NextAuth.js 与 tRPC 的整合是 T3 技术栈的标志性能力。create-t3-app 已经为你搭好了全部接线让你能够在认证过的 procedure 中直接访问会话对象。整个过程分两步第一步从请求头取会话并注入 tRPC 上下文脚手架生成了一个辅助函数它基于unstable_getServerSession抽象出跨框架的会话获取逻辑。这个函数名里的unstable仅代表 API 的底层实现未来可能调整函数本身是纯服务端调用不会像getSession那样触发额外的网络请求因此是安全的export const getServerAuthSession async (ctx: { req: GetServerSidePropsContext[req]; res: GetServerSidePropsContext[res]; }) { return await unstable_getServerSession(ctx.req, ctx.res, nextAuthOptions); };在 Pages Router 的 tRPC 上下文创建处调用它把session交给内部上下文import { getServerAuthSession } from ../common/get-server-auth-session; export const createContext async (opts: CreateNextContextOptions) { const { req, res } opts; const session await getServerAuthSession({ req, res }); return await createContextInner({ session, }); };而在 App Router 模板中这一逻辑被精简为在 createTRPCContext 里直接调用auth()读取会话并把session并入 context——对比 无认证版本的 base.ts 可以看到唯一的差异就是会话的注入。第二步用中间件定义protectedProcedure创建一个校验用户是否已认证的 tRPC 中间件再把它包装成protectedProcedure。任何未登录用户调用这类 procedure 都会抛出UNAUTHORIZED错误由客户端妥善处理export const protectedProcedure t.procedure.use(({ ctx, next }) { if (!ctx.session?.user) { throw new TRPCError({ code: UNAUTHORIZED }); } return next({ ctx: { // infers the session as non-nullable session: { ...ctx.session, user: ctx.session.user }, }, }); })在最新模板的 trpc-app/with-auth.ts 中protectedProcedure在timingMiddleware之上叠加会话校验并通过类型收窄让后续代码确信ctx.session.user非空。由于session只是用户的轻量最小化表示仅包含少量字段因此当你在protectedProcedure中拿到user.id后通常还要回数据库查询完整用户数据const userRouter router({ me: protectedProcedure.query(({ ctx }) { const user await prisma.user.findUnique({ where: { id: ctx.session.user.id, }, }); return user; }), });与 Prisma 集成模型已就绪新增字段要带默认值让 NextAuth.js 与 Prisma 协同工作本来需要大量初始化配置。create-t3-app 替你全部处理好了只要同时选择 Prisma 与 NextAuth.js你就能得到一个完全可用的认证系统所需的User、Account、Session、VerificationToken四个模型已经在 with-auth.prisma 中预配置完毕且Account与Session通过onDelete: Cascade与User建立外键关系。在配置侧Prisma 版本通过 with-prisma.ts 的adapter: PrismaAdapter(db)接入数据库Drizzle 版本则在 with-drizzle.ts 中显式传入usersTable、accountsTable、sessionsTable、verificationTokensTable四张表。扩展模型字段的黄金法则当你给User、Account、Session或VerificationToken最常改的是User新增字段时必须意识到Prisma Adapter 在新用户注册/登录时自动为这些模型创建记录它并不知道你加的字段。因此任何新增字段都必须提供默认值。例如给User增加role字段需要同步定义一个枚举并加上default enum Role { USER ADMIN } model User { ... role Role default(USER) }不提供默认值会导致 Adapter 自动创建用户时因缺少必填字段而写入失败——这是集成中最容易踩的坑。与 Next.js Middleware 搭配的会话策略约束如果你计划在 Next.js Middleware如middleware.ts中的路由守卫中使用认证信息那么必须切换到JWT 会话策略。原因是 Middleware 运行在 Edge 环境、只能读取 cookie 中的 JWT而默认情况下 create-t3-app 配置的是数据库会话策略与 Prisma Adapter 配合使用。修改方式是在authConfig中增加session: { strategy: jwt }并相应调整session回调的取值来源JWT 模式下从token而非user取id。数据库策略下想走 Middleware 会取不到会话这是官方文档明确指出的 caveat。配置默认的 DiscordProvidercreate-t3-app 之所以默认预置 Discord OAuth是因为它是上手成本最低的提供商之一只需要把两个 token 填入.env即可完成对接。完整步骤如下打开 Discord 开发者门户的应用管理页点击 New Application 创建应用在 OAuth2 General 配置区复制Client ID粘贴到.env的AUTH_DISCORD_ID在 Client Secret 处点击 Reset Secret 并把生成的字符串粘贴到.env的AUTH_DISCORD_SECRET注意这个值只会显示一次重置会使旧 secret 立即失效点击 Add Redirect粘贴app url/api/auth/callback/discord本地开发即为http://localhost:3000/api/auth/callback/discord保存所有更改。create-t3-app 会为你生成.env与.env.example两份文件envVars.ts.env.example只含占位的AUTH_DISCORD_ID、AUTH_DISCORD_SECRET而.env中的AUTH_SECRET会由脚手架用crypto.getRandomValues生成 32 字节随机数并自动填入。对应的运行时校验位于 src/env.jsAUTH_DISCORD_ID与AUTH_DISCORD_SECRET为必填字符串AUTH_SECRET仅在 production 下强制要求开发环境可缺省。一些实践建议可以但不推荐在开发与生产环境共用同一个 Discord 应用更稳妥的做法是为两个环境分别创建应用。开发阶段也可以考虑 mock 提供商避免依赖外部 OAuth 服务。想要添加更多提供商时直接在 auth 配置 的providers数组中追加即可。但要注意某些提供商需要给Account等模型补充额外字段例如 GitHub 提供商要求Account模型包含refresh_token_expires_in字段该字段在 with-auth.prisma 中已预留。务必先阅读目标提供商的官方文档确认所需字段齐全。总结create-t3-app 的 NextAuth.js 集成是一套选中即用的完整方案SessionProvider负责客户端会话注入session 回调加模块增强保证session.user.id的类型安全getServerAuthSession/auth()与 tRPC 上下文打通服务端会话protectedProcedure提供声明式的路由保护Prisma/Drizzle 适配器与预置模型免去初始化成本。开发者只需补齐 Discord 凭据即可启动后续无论是扩展角色字段还是接入新提供商都遵循字段带默认值、读文档确认模型差异两条主线即可平稳演进。【免费下载链接】create-t3-appThe best way to start a full-stack, typesafe Next.js app项目地址: https://gitcode.com/gh_mirrors/cr/create-t3-app创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表