You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 02:50:55