NextAuthを使ってAPIで認証するのに鬼ほど苦戦したので雑にメモ。
環境変数
よくわかってないけど設定しないとうまく動かない。
これが原因と分からずずっと動かなかった。
・NEXTAUTH_URL
認証系のURLの設定
https://next-auth.js.org/configuration/options#nextauth_url
・NEXTAUTH_SECRET
認証してJWTをなんやかんやするのに必要らしい
https://next-auth.js.org/configuration/options#nextauth_secret
NEXTAUTH_URL=http://localhost:3000
NEXTAUTH_SECRET=secret
オプション作る
NextAuthの設定的なもの。
nextAuthOptions.ts
import { NextAuthOptions } from "next-auth";
import GithubProvider from "next-auth/providers/github"
import CredentionsProvider from 'next-auth/providers/credentials'
const authOptions: NextAuthOptions = {
secret: process.env.NEXTAUTH_SECRET,
// 必要なプロバイダーは複数設定できる
// Credentialは普通のIDパスワード方式
providers: [
GithubProvider({
clientId: process.env.GITHUB_ID || '',
clientSecret: process.env.GITHUB_SECRET || '',
}),
CredentionsProvider({
name: 'Credentials',
credentials: {
username: {
label: 'Username',
type: 'text',
placeholder: 'username'
},
password: {
label: 'Password',
type: 'password'
}
},
async authorize(credentials, req) {
// ここでユーザー認証を行う?
// テスト用のユーザー
const user = { id: '1', name: 'Taro', email: 'test@example.com' }
if (user) {
return user
} else {
return null
}
}
})
],
// ログインページとかのURLを変えたい場合pagesを設定する
// pages: {
// signIn: '/auth/signin',
// signOut: '/auth/signout',
// error: '/auth/error', // Error code passed in query string as ?error=
// verifyRequest: '/auth/verify-request', // (used for check email message)
// newUser: '/auth/new-user'
// }
}
export default authOptions;
ハンドラー作る
AppRouter
を使う場合はRoute Handlerというやつを使うらしい。
src/app/api/auth/[...nextauth]/route.ts
import NextAuth from "next-auth";
import authOptions from "@/NextAuthConfig/Option"
const handler = NextAuth(authOptions);
export { handler as GET, handler as POST }
API入口
Response
ではなくNextResponse
で作成しないとエラーが出る。
api/api-test/route.ts
import { getServerSession } from 'next-auth/next';
import { NextApiRequest, NextApiResponse } from 'next'
import authOptions from '@/NextAuthConfig/Option'
export const GET = async (req: NextApiRequest, res: NextApiResponse) => {
const session = await getServerSession(authOptions)
console.log(session);
if (session) {
return NextResponse.json({ data: "Protected data" })
}
return NextResponse.json({ message: "Not authenticated" }, { status: 401 })
}
ログインページとか
signIn
には引数でプロバイダーを指定できる。
ExampleTopPage.tsx
'use client'
import React from 'react'
import { signIn, signOut } from 'next-auth/react'
function page(req, res) {
const onClickLogin = async () => {
signIn()
};
const onClickLogout = async () => {
signOut()
}
return (
<div>
<div>
<button onClick={onClickLogin}>ログイン</button>
</div>
<div>
<button onClick={onClickLogout}>ログアウト</button>
</div>
</div>
)
}
export default page