NextAuthについて
400ばかり帰ってくる
/api/auth
のエンドポイントに繋いだところ、以下エラーが出る。
Error: This action with HTTP GET is not supported by NextAuth.js
なんてことはない。こちらのファイルの置きミスだった。
src/app/[...nextauth]/route.ts
にきちんと置くこと。
NextAuthの公式ドキュメントを参照せず、誰かが書いたページを鵜呑みにしてしまっていた。
公式ドキュメント(App Router): https://next-auth.js.org/configuration/initialization#route-handlers-app
(しかしNextAuthのApp Routerのドキュメント見つけにくいよ。。。)
DBにemailやnameを保存したくない
NextAuthのPrisma AdapterでOIDCするとemailやnameをDBに保存する設定にデフォルトではなっている。
それを回避したい。
/usr/src/app/src/app/api/auth/[...nextauth]/route.ts
以下のようにscopeとprofileの設定をオーバーライドすることでemailやnameを使わないようにした
参考: https://github.com/nextauthjs/next-auth/blob/v4/packages/next-auth/src/providers/google.ts
import NextAuth from "next-auth/next";
import GoogleProvider from "next-auth/providers/google";
import { PrismaAdapter } from "@auth/prisma-adapter";
import { PrismaClient } from "@prisma/client";
const prisma = new PrismaClient();
const handler = NextAuth({
session: {
strategy: "database",
},
adapter: PrismaAdapter(prisma),
providers: [
GoogleProvider({
clientId: process.env.GOOGLE_CLIENT_ID || "",
clientSecret: process.env.GOOGLE_CLIENT_SECRET || "",
authorization: { params: { scope: "openid" } },
profile(profile) {
return {
id: profile.sub,
};
},
}),
],
secret: process.env.NEXTAUTH_SECRET,
});
export { handler as GET, handler as POST };
/usr/src/app/prisma/schema.prisma
スキーマのUserモデルからもname, email, imageを消した。emailVerifiedは残さないとエラーが起きるので残している(何かはわかっていない)。
参考: https://authjs.dev/getting-started/adapters/prisma
model User {
id String @id @default(cuid())
emailVerified DateTime?
accounts Account[]
sessions Session[]
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}
sessionに任意のフィールドを追加したい
表題の通り、sessionにuserIdとかを追加したい。
「いやいやcallbackに追加するだけでしょ?」と思っていたのですが、buildしたときにsessionオブジェクトにフィールドがないとかでエラーが起きます。これは困る。
困ったなと思っていたら、以下の記事に書いてあった。
参考: https://annjose.com/post/how-to-customize-nextauth-session/
src/types/next-auth.d.ts
に拡張したsessionオブジェクトを書くだけ。以下の感じ。
import NextAuth from "next-auth";
declare module "next-auth" {
interface Session {
userId: string;
}
}
あと自分で設定した認証方法(databaseによるsessionとか)で getServerSession()
を使いたい場合、nextAuthOptionsをexportする必要がある。ここで
src/app/api/auth/[...nextauth]/route.ts
に nextAuthOptions を直接書いて export してはいけない。これは、[...nextauth]/route.ts
ではexportするオブジェクトが決まっているため。
src/app/api/auth/[...nextauth]/route.ts
import NextAuth from "next-auth/next";
import { nextAuthOptions } from "./authOptions";
const handler = NextAuth(nextAuthOptions);
export { handler as GET, handler as POST };
src/app/api/auth/[...nextauth]/authOptions.ts
import GoogleProvider from "next-auth/providers/google";
import { PrismaAdapter } from "@auth/prisma-adapter";
import { PrismaClient } from "@prisma/client";
import type { NextAuthOptions } from "next-auth";
const prisma = new PrismaClient();
export const nextAuthOptions: NextAuthOptions = {
session: {
strategy: "database",
},
adapter: PrismaAdapter(prisma),
providers: [
GoogleProvider({
clientId: process.env.GOOGLE_CLIENT_ID || "",
clientSecret: process.env.GOOGLE_CLIENT_SECRET || "",
authorization: { params: { scope: "openid" } },
profile(profile) {
return {
id: profile.sub,
};
},
}),
],
secret: process.env.NEXTAUTH_SECRET,
callbacks: {
async session({ session, user }) {
if (session?.user) {
session.userId = user.id;
}
return session;
},
},
};