Open6
next-auth@5.0.0(Auth.js) メモ
strategy
- ユーザセッションの保存方法
- デフォルトでは
jwtになり、Cookieに保存される - アダプタ(データベース)を使用する場合は、
databaseになる- ただし、明示的に
jwtと定義することで、jwtセッションを強制できる
- ただし、明示的に
auth.ts
// データベースを使用し、jwtも使用する場合
export const { handlers, signIn, signOut, auth } = NextAuth({
...authConfig,
adapter: PrismaAdapter(prisma),
session: {strategy: "jwt"},
callbacks: {
session: ({token, session, user}) => {
return {
...session,
user: {
...session.user,
id: token.sub
}
}
}
}
});
OAuthを使用する場合デフォルトで取れる認証情報は以下のものである。
- name
- image
これだけだと不十分なので、今回はSession callbackの中でuser.idにユーザーIDであるtoken.subを追加している。
jwt callback
ここでreturnされるものはすべてJWTに保存され、session callbackに転送される。
引数のuser、account、profileはサインイン時のみ渡される。
auth.ts
callbacks: {
async jwt({ token, user, account, trigger, session }) {
// サインイン時
if (user) {
token.name = user.name;
}
// セッション更新時の処理
if (trigger == "update" && session?.name) {
console.log("-- セッション更新 --")
token.name = session.name;
token.isNewUser = false; // 名前が設定されたらNewUserをfalseに
}
return token;
},
Prismaを使用する場合、引数のuserの中身はschema.prismaによって決まる
accountはほぼスキーマ通りだったが違う部分も見られた。
user
"user": {
"id": "xxxxxxxxxxxxxxxxxxxxxxx",
"name": "atnuhs",
"email": "xxxxxxxxxx@gmail.com",
"emailVerified": null,
"image": "https://xxxxxxxxxxxxxxxxxxxxxxxxx"
},
token
token: {
name: 'atnuhs',
email: 'xxxxxxxxxx@gmail.com',
picture: 'https://xxxxxxxxxxxxx',
sub: 'xxxxxxxxxxxxx' // user.idと一緒
}
account
account: {
access_token: 'xxxxxxxxxxxxx',
expires_in: 3599,
scope: 'https://www.googleapis.com/auth/userinfo.profile openid https://www.googleapis.com/auth/userinfo.email',
token_type: 'bearer',
id_token: 'xxxxxxxxxxxxx',
expires_at: 1728144477,
provider: 'google',
type: 'oidc',
providerAccountId: 'xxxxxxxxxxxxxxxxxxxx'
}
profile
"profile": {
"iss": "https://accounts.google.com",
"azp": "xxxxxxxxxxx",
"aud": "xxxxxxxxxxxxxx",
"sub": "xxxxxxxxxxxx",
"email": "xxxxxxxx@gmail.com",
"email_verified": true,
"at_hash": "xxxxxxx",
"name": "atnuhs",
"picture": "https://xxxxxxxx",
"given_name": "atnuhs",
"iat": 1728123231,
"exp": 1728126831
},
session callback
sessionがチェックされるたびに呼び出される。
-
const session = auth()を呼び出したときにsessionに入る値を決める。 -
token引数はjwt session strategyを使用しているとき、user引数はdatabase session strategyを使用しているときのみ使用可能。(例:jwt strategyを使用しているときはuser引数はundefinedになる) -
token引数はjwt callbackでtokenに追加したものが入る。 -
user引数はDBに保存されたUserデータが入る。
以下はsessionにuserIdを追加する例:
auth.ts
callbacks: {
session: ({ token, session, user }) => {
return {
...session,
user: {
...session.user,
id: token.sub,
},
};
},
},
unstable_update
サーバーサイドでSessionを更新する方法?
ローカルと本番環境でcookieNameが違う
後で見る
middleware.tsのtokenの取得でcookieNameを指定するところを本番環境とローカルで条件分岐させたい
ローカルとvercelの環境変数にTOKEN_COOKIE_NAMEを設定して対応した
型定義の拡張について
- "next-auth"のUserがjwt callbackのuserの定義
- "next-auth/jwt"のJWTがjwt callbackとsession callbackのtokenの定義
- ※AdapterUserの拡張は必要だった気がしたけど、なくてもいけたので要調査
- わかんなくなったときは
auth.tsで引数をホバーしたらわかると思う
next-auth.d.ts
import { UserRole } from "@prisma/client";
import NextAuth, {type DefaultSession } from "next-auth"
declare module "next-auth" {
interface Session {
user: {
id: string;
isProfileComplete: boolean; // 追加
role: UserRole; // 追加
} & DefaultSession['user'];
}
// jwt callbackのuser
interface User {
id: string;
name: string;
email: string;
emailVerified: boolean;
image: string;
isProfileComplete: boolean; // 追加
role: UserRole; // 追加
}
}
declare module "next-auth/jwt" {
// jwt callbackとsession callbackのtoken
interface JWT {
role: UserRole; // 追加
isProfileComplete: boolean; // 追加
}
}
declare module "@auth/core/adapters" {
interface AdapterUser extends User {
isProfileComplete: boolean; // 追加
role: UserRole; // 追加
}
}