基于T3创建的Next.js App Router集成Auth0遇问题求助
Next.js + Auth0 集成问题排查
我用npm create t3 latest重建了Next.js应用,选择了TypeScript、TRPC、Tailwind和Prisma ORM。由于Auth0已满足需求且NextAuth存在局限,未使用NextAuth。为适配旧项目版本,将Next.js从15.0.3降级至14.2.5。
按照Auth0官方文档配置App Router集成Auth0后,遇到两个核心问题:
问题1:用户登录后无法获取用户数据
根据文档,应能根据会话中的用户状态条件渲染组件(如显示登录/登出按钮),但实际情况:
- 服务端组件调用
getSession返回null - 客户端组件调用
useUser返回undefined - 调用
await getAccessToken()时报错:
AccessTokenError: The user does not have a valid session. at Object.getAccessToken
我已在根布局中添加<UserProvider>{children}</UserProvider>。
问题2:登出后登录会话仍保留
用户登出后需重新输入凭证才能登录,但点击登出按钮后再点击登录,无需输入凭证即可直接返回站点,存在安全隐患。我已尝试Auth0官方登出文档方案,但无效。
相关代码文件
src/app/layout.tsx
import "@/styles/globals.css"; import { GeistSans } from "geist/font/sans"; import { type Metadata } from "next"; import { TRPCReactProvider } from "@/trpc/react"; import { UserProvider } from "@auth0/nextjs-auth0/client"; export const metadata: Metadata = { title: "Title", description: "Description", icons: [{ rel: "icon", url: "/favicon.ico" }], }; export default async function RootLayout({ children, }: Readonly<{ children: React.ReactNode }>) { return ( <html lang="en" className={`${GeistSans.variable}`}> <body> <UserProvider> {/* <TRPCReactProvider> */} {children} {/* </TRPCReactProvider> */} </UserProvider> </body> </html> ); }
src/app/user/[step]/page.tsx
import LoginButtons from "@/app/components/loginButtons"; import SignOut from "@/app/components/signOut"; import { getAccessToken } from "@auth0/nextjs-auth0"; import Test from "@/app/components/test"; const Step = async ({ params }: { params: { step: string } }) => { const { accessToken } = await getAccessToken(); console.log("Access Token in Step", accessToken); if (!params.step) { return <div>Loading...</div>; } return ( <div> <h1>Step {params.step}</h1> <p>This is the {params.step} step</p> <SignOut /> <Test /> </div> ); } export default Step;
app/components/loginButtons.tsx
import React from "react"; import { getSession } from "@auth0/nextjs-auth0"; export default async function LoginButtons() { const user = await getSession(); console.log("log user in buttons component", user); return ( <main className="flex justify-between"> <div className="w-dvw min-h-dvh h-full items-center text-sm grid grid-cols-3 bg-main"> {user && (<a href="/api/auth/logout" >Logout</a>)} {!user && ( <> <a href="/api/auth/login">Login</a> <a href="/api/auth/signup">SignUp</a> <a href="/api/auth/logout" >Logout</a> </> )} </div> </main> ) }
app/components/test.tsx(测试客户端组件与useUser())
"use client"; import { useUser } from "@auth0/nextjs-auth0/client"; export default function Test() { const { user } = useUser(); console.log("Log user in test client component", user); return ( <div> user: <pre>{JSON.stringify(user, null, 2)}</pre> </div> ); }
package.json
{ "name": "gothrive.app", "version": "0.1.0", "private": true, "type": "module", "@snaplet/seed": { "config": "prisma\\seed\\seed.config.ts" }, "scripts": { "build": "next build", "check": "next lint && tsc --noEmit", "db:generate": "prisma migrate dev", "db:migrate": "prisma migrate deploy", "db:push": "prisma db push", "db:studio": "prisma studio", "dev": "next dev --turbo", "format:check": "prettier --check \"**/*.{ts,tsx,js,jsx,mdx}\" --cache", "format:write": "prettier --write \"**/*.{ts,tsx,js,jsx,mdx}\" --cache", "postinstall": "prisma generate", "lint": "next lint", "lint:fix": "next lint --fix", "preview": "next build && next start", "start": "next start", "typecheck": "tsc --noEmit", "test:watch": "jest --watchAll", "test:integration": "yarn docker:up && yarn prisma migrate deploy && jest -i", "docker:up": "docker compose up -d", "docker:down": "docker compose down", "test": "yarn docker:up && yarn prisma migrate deploy && jest -i", "postmigrate": "npx @snaplet/seed sync", "seed": "prisma db seed", "storybook": "storybook dev -p 6006", "build-storybook": "storybook build" }, "dependencies": { "@auth0/nextjs-auth0": "^3.5.0", "@prisma/client": "^5.14.0", "@t3-oss/env-nextjs": "^0.10.1", "@tanstack/react-query": "^5.50.0", "@trpc/client": "^11.0.0-rc.446", "@trpc/react-query": "^11.0.0-rc.446", "@trpc/server": "^11.0.0-rc.446", "geist": "^1.3.0", "next": "14.2.5", "prisma-field-encryption": "^1.6.0", "react": "^18.3.1", "react-dom": "^18.3.1", "server-only": "^0.0.1", "snaplet": "^0.42.1", "superjson": "^2.2.1", "tsx": "^4.19.2", "zod": "^3.23.3" }, "devDependencies": { "@chromatic-com/storybook": "3.2.2", "@storybook/addon-essentials": "8.4.5", "@storybook/addon-interactions": "8.4.5", "@storybook/addon-onboarding": "8.4.5", "@storybook/blocks": "8.4.5", "@storybook/nextjs": "8.4.5", "@storybook/react": "8.4.5", "@storybook/test": "8.4.5", "@types/eslint": "^8.56.10", "@types/node": "^20.14.10", "@types/react": "^18.3.3", "@types/react-dom": "^18.3.0", "@typescript-eslint/eslint-plugin": "^8.1.0", "@typescript-eslint/parser": "^8.1.0", "eslint": "^8.57.0", "eslint-config-next": "^15.0.1", "eslint-plugin-storybook": "^0.11.1", "postcss": "^8.4.39", "prettier": "^3.3.2", "prettier-plugin-tailwindcss": "^0.6.5", "prisma": "^5.14.0", "storybook": "8.4.5", "tailwindcss": "^3.4.3", "typescript": "^5.5.3" }, "ct3aMetadata": { "initVersion": "7.38.1" } }
内容的提问来源于stack exchange,提问作者Andy Vennells
相关产品推荐
相关产品推荐

