NextJS - NextAuth:getToken在middleware.ts中总是返回null

moiiocjp  于 2023-04-11  发布在  其他
关注(0)|答案(1)|浏览(190)

使用getToken({req, secret})无法获取token数据,始终返回null。Next JS 13.1.1和next-auth 4.3.4

package.json:

{
  "name": "frontend",
  "version": "0.1.0",
  "private": true,
  "scripts": {
    "dev": "next dev",
    "build": "next build",
    "start": "next start",
    "lint": "next lint",
    "deploy": "npx serverless"
  },
  "dependencies": {
    "@emotion/react": "^11.10.0",
    "@emotion/styled": "^11.10.0",
    "@mui/icons-material": "^5.8.4",
    "@mui/lab": "^5.0.0-alpha.95",
    "@mui/material": "^5.10.0",
    "@reduxjs/toolkit": "^1.8.4",
    "animate.css": "^4.1.1",
    "chart.js": "^3.9.1",
    "cookie": "^0.5.0",
    "html-to-image": "^1.11.4",
    "jsonwebtoken": "^9.0.0",
    "jspdf": "^2.1.0",
    "moment": "^2.29.4",
    "next": "^13.1.1",
    "next-auth": "^4.3.4",
    "react": "^18.2.0",
    "react-chartjs-2": "^4.3.1",
    "react-cookie": "^4.1.1",
    "react-dom": "^18.2.0",
    "react-dropzone": "^14.2.2",
    "react-hook-form": "^7.34.1",
    "react-redux": "^8.0.2",
    "sass": "^1.54.4",
    "swr": "^1.3.0",
    "uuid": "^8.3.2"
  },
  "devDependencies": {
    "@types/cookie": "^0.5.1",
    "@types/jsonwebtoken": "^9.0.0",
    "@types/node": "18.7.5",
    "@types/react": "18.0.17",
    "@types/react-dom": "18.0.6",
    "@types/uuid": "^8.3.4",
    "eslint": "8.22.0",
    "eslint-config-next": "^13.1.1",
    "typescript": "4.7.4"
  }
}

[...nextauth].js:

import NextAuth, { NextAuthOptions } from "next-auth";

// Providers
import Credentials from "next-auth/providers/credentials";

// Services
import { authService, refreshAccessToken } from "../../../services";

export const authOptions: NextAuthOptions = {
  providers: [
    Credentials({
      name: "Credentials",
      credentials: {
        username: {
          label: "Username",
          type: "text",
          placeholder: "C.C.",
          autoComplete: true,
        },
        password: {
          label: "Password",
          type: "password",
          placeholder: "Type your password...",
          autoComplete: true,
        },
      },
      async authorize(credentials) {
        return await authService({
          username: credentials!.username,
          password: credentials!.password,
        });
      },
    }),
  ],
  pages: {
    signIn: "/auth/login",
  },
  session: {
    strategy: "jwt",
    maxAge: 60 * 60 * 7, // 7 hours
    updateAge: 60 * 60 * 2,
  },
  callbacks: {
    async jwt({ token, account, user }) {
      if (user) {
        token.accessToken = user.accessToken;
        token.refreshToken = user.refreshToken;

        if (account) {
          switch (account.type) {
            case "credentials":
              token.user = user.user;
              token.accessTokenExpires = user.accessTokenExpires;
              break;
          }
        }
      }

      if (Date.now() / 1000 < (token.accessTokenExpires as number)) {
        return token;
      }

      return await refreshAccessToken(token);
    },
    async session({ session, token }) {
      session.accessToken = token.accessToken;
      session.user = token.user as any;

      return session;
    },
  },
  // secret: process.env.NEXTAUTH_SECRET!,
  secret: process.env.NEXTAUTH_SECRET,
};

export default NextAuth(authOptions);

和中间件.ts:

import { getToken } from "next-auth/jwt";
import { withAuth } from "next-auth/middleware";
import { NextResponse } from "next/server";

// Interfaces
import { IUser } from "./interfaces";

const secret = process.env.NEXTAUTH_SECRET;

export default withAuth(async function middleware(req) {
  const token = await getToken({ req, secret }); // ALWAYS returns null
  const { user } = (token as { user: IUser; accessToken: string }) || {};

  const isAuth = !!token;
  const isAuthPage = req.nextUrl.pathname.startsWith("/auth");

  if (isAuthPage) {
    if (isAuth) {
      // return NextResponse.redirect(new URL(`/${user.hierarchy}`, req.url));
      return NextResponse.redirect(new URL(`/role`, req.url));
    }

    return null;
  }

  if (!isAuth) {
    let from = req.nextUrl.pathname;
    if (req.nextUrl.search) {
      from += req.nextUrl.search;
    }

    return NextResponse.redirect(new URL(`/auth/login`, req.url));
  }
});

process.env.NEXTAUTH_SECRET = secret。
我试着用nextAuth调试,但是当isAuth为false时中间件工作正常(如果我尝试加载受保护的路由,中间件重定向到/auth),只是当getToken函数尝试获取cookie来验证auth时失败,这是什么问题?:(

pepwfjgg

pepwfjgg1#

在这种情况下,需要在getToken中传递cookieName参数。

export async function middleware(request: NextRequest) {
  const secret = process.env.JWT_SECRET;
  const token = await getToken({
    req: request,
    secret: secret,
    cookieName: "next-auth.session-token",
  });

development tools中可以看出,如果没有为cookieName设置自定义名称值,cookieName应该是下图中的名称。

相关问题