一般的な話であるが、OAuth認証の基本的な仕組みを前提として確認する。OAuth認証を利用するWebアプリは、OIDCプロバイダから提供されたアクセストークンの正しさを、ユーザプロファイル情報の取得可否によって確認する。つまり、認証の過程においてWebアプリは、OIDCプロバイダのアクセストークンを取得している。この取得したアクセストークンを保持しておいて、OIDCプロバイダの提供するAPI呼び出しに使おう考えるのはごく自然なことである。
そういうわけで、本記事ではNextAuth.jsでの認証後、アクセストークンを取得する方法について扱う。 NextAuth.jsの仕組み上、アクセストークンはセッションに保存し、利用する際もセッションデータから取得することになる。
本記事で扱ったNextAuth.jsのバージョンは4.24.5である。過去記事でも検討したAutodeskのAPSをOIDCプロバイダとして利用して検証した。
型情報の拡張
NextAuth.jsのSession型には、アクセストークンは含まれていない。そのため、型定義を拡張する必要がある。 とりあえず、以下のファイルを作成することで必要な型の拡張ができる。 (ここの細かい仕組みはよくわかっていない。)
/app/types/next-auth.d.ts
import { DefaultSession } from "next-auth"; import { JWT } from "next-auth/jwt"; declare module "next-auth" { interface Session { accessToken?: string; } } declare module "next-auth/jwt" { interface JWT { accessToken?: string; } }
認証処理の設定
callbacksに、sessionとjwtの処理を追加する。
/app/api/auth/[...nextauth]/option.ts
import { AuthOptions } from "next-auth"; ... function newAuthOptions() { return { providers: [ AutodeskProvider({ ... }) ], callbacks: { async session(params) { const { session, token } = params; // JWTトークンのaccessTokenをセッションへコピーする。 session.accessToken = token.accessToken; return session; }, async jwt(params) { const { token, account } = params; if (account) { // サインイン時にアクセストークンをJWTに保存する。 token.accessToken = account.access_token } return token }, }, ... } satisfies AuthOptions } export const options = newAuthOptions();
これで認証処理の設定はOK。アクセストークンはサインイン時にJWTに保存するので、テストする場合はサインインしなおす必要がある。
セッション情報の取得
サーバサイドでsessionを取得する場合は以下。
import { options } from "../auth/[...nextauth]/option"; export async function GET(req: Request) { const session = await getServerSession(options); ... }
getServerSessionの引数には認証処理を設定したoptionsを渡さないとアクセストークンがセッションに含まれてこない。
クライアントサイドの場合はSessionProviderでWrapしたうえでuseSessionで取得する。 App Routerを利用している場合はuse clientが必須。
"use client" import { SessionProvider } from "next-auth/react" import { useSession } from "next-auth/react" function App() { return <SessionProvider> <SessionView /> </SessionProvider> } function SessionView() { const { data: session } = useSession() return <pre>{JSON.stringify(session)}</pre> }
参考文献
公式に大体書いてある。