😊
NextAuthのSessionを拡張する
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 を追加します。
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: {
+ 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 を拡張しましょう
auth.config.ts
+ declare module "next-auth" {
+ interface Session extends DefaultSession {
+ user: {
+ id: string;
+ } & DefaultSession["user"];
+ }
+ }
const prismaAdapter: Adapter = {
// ~~~
}
次は、「id
は token に存在しないよ」、と警告が出るので、これにも対処します。
auth.config.ts
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
も付与しましょう。
auth.config.ts
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",
},
};
これでOK、と思いきや次のような警告が出ます。
Property 'role' does not exist on type 'AdapterUser | User'.
Property 'role' does not exist on type 'AdapterUser'.
- 「今度はUserにroleがないよ」と言われたので追加します。
auth.config.ts
declare module "next-auth" {
+ interface User {
+ role: string;
+ }
interface Session extends DefaultSession {
user: {
id: string;
role: string;
} & DefaultSession["user"];
}
}
これでSessionから role も取得できるようになりました!
完成
最終的にはこんな感じ
auth.config.ts
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",
},
};
終わり
やってみるとシンプルですね。必要なものは拡張して加えていく、それだけ。
「Property 'role' does not exist on type 'AdapterUser | User'.」 を受けてUserを拡張するのは苦戦しましたが、こっちもやってみればシンプル。
これで自由に Session を扱えそうです。
ありがとうございました。
Discussion