扩展 NextAuth 会话

327 阅读2分钟

next-auth@4.24.5

想在Session中追加id和role等…!

NextAuth的Session只能直接获取name, email, image。 但是根据情况,想从Session取得id和role。

所以我想在Session中添加id和role。 因为那个方法苦战了很久,所以留下了。

// auth.config.ts
// 初期状態
export const authOptions: NextAuthOptions = {
  adapter: PrismaAdapter(prismaClient),
  providers: [
    GoogleProvider({
      clientId: process.env.GOOGLE_CLIENT_ID as string,
      clientSecret: process.env.GOOGLE_CLIENT_SECRET as string,
    }),
  ],
  session: {
    strategy: "jwt",
  },
  secret: process.env.NEXTAUTH_SECRET,
  callbacks: {},
  pages: {
    signIn: "login",
  },
};

赋予id

首先给Session添加User.id。 为此在options中添加callbacks。

export const authOptions: NextAuthOptions = {
  adapter: PrismaAdapter(prismaClient),
  providers: [
    GoogleProvider({
      clientId: process.env.GOOGLE_CLIENT_ID as string,
      clientSecret: process.env.GOOGLE_CLIENT_SECRET as string,
    }),
  ],
  session: {
    strategy: "jwt",
  },
  secret: process.env.NEXTAUTH_SECRET,
  callbacks: {
+    async jwt({ token, user }) {
+      if (user) {
+        token.id = user.id;
+      }
+
+      return token;
+    },
+    async session({ session, token }) {
+      if (token) {
+        session.user.id = token.id;
+      }
+      return session;
+    },
+  },
  pages: {
    signIn: "login",
  },
};

然后就会出现“id不存在于session.user”的警告。 所以我们扩展Session。

+ declare module "next-auth" {
+  interface Session extends DefaultSession {
+    user: {
+      id: string;
+    } & DefaultSession["user"];
+  }
+ }

const prismaAdapter: Adapter = {
  // ~~~
}
···

接下来是“id不存在于token”的警告:

 declare module "next-auth" {
  interface Session extends DefaultSession {
    user: {
      id: string;
    } & DefaultSession["user"];
 }
 
+ declare module "next-auth/jwt" {
+  interface JWT {
+    id: string;
+  }
+ }

const prismaAdapter: Adapter = {
 // ~~~
}

这样Session就有了id。

赋予role

像添加id一样添加role。

declare module "next-auth" {
  interface Session extends DefaultSession {
    user: {
      id: string;
+     role: string;
    } & DefaultSession["user"];
  }
}

declare module "next-auth/jwt" {
  interface JWT {
    id: string;
+   role: string;
  }
}

export const authOptions: NextAuthOptions = {
  adapter: PrismaAdapter(prismaClient),
  providers: [
    GoogleProvider({
      clientId: process.env.GOOGLE_CLIENT_ID as string,
      clientSecret: process.env.GOOGLE_CLIENT_SECRET as string,
    }),
  ],
  session: {
    strategy: "jwt",
  },
  secret: process.env.NEXTAUTH_SECRET,
  callbacks: {
    async jwt({ token, user }) {
      if (user) {
        token.id = user.id;
+       token.role = user.role;
      }

      return token;
    },
    async session({ session, token }) {
      if (token) {
        session.user.id = token.id;
+        session.user.role = token.role;
      }
      return session;
    },
  },
  pages: {
    signIn: "login",
  },
};

本以为这样就可以了,没想到会出现以下警告。

Property 'role' does not exist on type 'AdapterUser | User'.
Property 'role' does not exist on type 'AdapterUser'.
  • 报错提示“这次User没有role”,所以追加。
declare module "next-auth" {
+  interface User {
+    role: string;
+  }
  interface Session extends DefaultSession {
    user: {
      id: string;
      role: string;
    } & DefaultSession["user"];
  }
}

这样就可以从Session中获取role了!

完成

import { PrismaAdapter } from "@next-auth/prisma-adapter";
import {
  DefaultSession,
  NextAuthOptions,
  getServerSession,
} from "next-auth";
import GoogleProvider from "next-auth/providers/google";
import prismaClient from "@/lib/prisma";
import { Adapter, AdapterUser } from "next-auth/adapters";

declare module "next-auth" {
  interface User {
    role: string;
  }
  interface Session extends DefaultSession {
    user: {
      id: string;
      role: string;
    } & DefaultSession["user"];
  }
}

declare module "next-auth/jwt" {
  interface JWT {
    id: string;
    role: string;
  }
}

export const authOptions: NextAuthOptions = {
  adapter: PrismaAdapter(prismaClient),
  providers: [
    GoogleProvider({
      clientId: process.env.GOOGLE_CLIENT_ID as string,
      clientSecret: process.env.GOOGLE_CLIENT_SECRET as string,
    }),
  ],
  session: {
    strategy: "jwt",
  },
  secret: process.env.NEXTAUTH_SECRET,
  callbacks: {
    async jwt({ token, user }) {
      if (user) {
        token.id = user.id;
        token.role = user.role;
      }

      return token;
    },
    async session({ session, token }) {
      if (token) {
        session.user.id = token.id;
        session.user.role = token.role;
      }
      return session;
    },
  },
  pages: {
    signIn: "login",
  },
};