はじめに
こんにちは、インダストリーワン エンジニアの松崎です。
Auth.jsを使用して、どのように認証認可を実装できるのか調査します。
Auth.js
を使用することによって、簡単に認証機能の実装が可能になります。
現時点では、認証認可としてはまだまだ不十分ですが、Auth.js
の導入から簡単なカスタマイズまで対応しています。
成果物
セットアップ
とりあえず動くところまでを目指します。
1. Auth.js
をインストール
Auth.js
ですが、ライブラリ名はnext-auth
ですね。
現時点ではpackage.json
に"next-auth": "^5.0.0-beta.19"
が追加されました。
npm install next-auth@beta
2. シークレットを設定
Env
ファイルにAuth.js
で使用するシークレットを設定します。
シークレットの用途はこちら
.env.local
を修正(.env.local
がない場合は新規作成してください)
# 追記 AUTH_SECRET="your secret" # openssl rand -base64 33 or npx auth secret
3. Config
を作成
src/auth/config.ts
を作成
GitHub
, Google
のclientId
/clientSecret
は各自でセットしてください。
ここでは仮の値をセットしています。
import NextAuth from "next-auth" import GitHub from "next-auth/providers/github" import Google from "next-auth/providers/google" export const { auth, handlers, signIn, signOut } = NextAuth({ providers: [ GitHub({ clientId: 'GITHUB_ID', clientSecret: 'GITHUB_SECRET'}), Google({ clientId: 'GOOGLE_ID', clientSecret: 'GOOGLE_SECRET'}), ], })
4. API Route
を作成
src/app/api/[...nextauth]/route.ts
を作成
import { handlers } from "@/auth/config" export const { GET, POST } = handlers
5. Page
を作成
src/app/authjs/page.tsx
を作成
'use client' import { signIn } from "next-auth/react"; export default function AuthjsPage() { return ( <div> <button onClick={() => signIn()}>サインイン</button> </div> ); }
6. http://localhost:3000/authjs
にアクセス
サインイン
ボタンが表示されることを確認
7. サインイン
ボタンをクリック
GitHub
とGoogle
を利用したサインイン
ボタンが表示されるページに遷移することを確認
EmailとPasswordでの認証
ここからは上記をベースに、実験的に動かしてみます。
1. Email
とPassword
のフォームを作成
1-1. src/auth/config.ts
を修正し、Email
とPassword
のフォームを作成
import NextAuth from "next-auth" import Credentials from "next-auth/providers/credentials" import GitHub from "next-auth/providers/github" import Google from "next-auth/providers/google" export const { auth, handlers, signIn, signOut } = NextAuth({ providers: [ GitHub({ clientId: 'GITHUB_ID', clientSecret: 'GITHUB_SECRET'}), Google({ clientId: 'GOOGLE_ID', clientSecret: 'GOOGLE_SECRET'}), Credentials({ credentials: { email: { label: 'Email', type: 'email' }, password: { label: 'Password', type: 'password' }, }, }) ], })
1-2. Email
とPassword
のフォームを確認
ここで、フォームに入力してSign in with Credentials
ボタンをクリックしてもエラーになるので認証ロジックを作成します。
2. 認証ロジックの作成
2-1. src/auth/config.ts
を修正し、認証ロジックを作成
import NextAuth from "next-auth" import Credentials from "next-auth/providers/credentials" import GitHub from "next-auth/providers/github" import Google from "next-auth/providers/google" export const { auth, handlers, signIn, signOut } = NextAuth({ providers: [ GitHub({ clientId: 'GITHUB_ID', clientSecret: 'GITHUB_SECRET' }), Google({ clientId: 'GOOGLE_ID', clientSecret: 'GOOGLE_SECRET' }), Credentials({ credentials: { email: { label: 'Email', type: 'email' }, password: { label: 'Password', type: 'password' }, }, async authorize(credentials) { // ここに認証ロジックを作成する // とりあえずconsole.logでcredentialsを表示してみる console.log(credentials) // nullを返すと失敗 return null } }) ], })
console.log
の出力結果
csrfToken
, email
, password
が取得できました。
2-2. 簡易なバリデーションを作成し、認証を成功させてみる
authorize
メソッドの中でZod
を利用したバリデーションの実装や、バックエンドなどでの認証を実装するべきであるが、今回は省略し、ハードコーディングで値を返します。
成功した場合は、session
の中にuser
としてデータが保存されます。
import NextAuth from "next-auth" import Credentials from "next-auth/providers/credentials" import GitHub from "next-auth/providers/github" import Google from "next-auth/providers/google" export const { auth, handlers, signIn, signOut } = NextAuth({ providers: [ GitHub({ clientId: 'GITHUB_ID', clientSecret: 'GITHUB_SECRET' }), Google({ clientId: 'GOOGLE_ID', clientSecret: 'GOOGLE_SECRET' }), Credentials({ credentials: { email: { label: 'Email', type: 'email' }, password: { label: 'Password', type: 'password' }, }, async authorize(credentials) { // ここに認証ロジックを作成する // credentialsには{ csrfToken: string, email: string, password: string }が入っている // 簡易的なバリデーション(Zodなどを使うと良い) if (!credentials) return null; if (typeof credentials.email !== 'string') return null; if (typeof credentials.password !== 'string') return null; // 認証成功時はユーザ情報を返す return { id: "test-test-test", email: credentials.email, name: "テストユーザ", } } }) ], })
2-3. Layout
を作成
src/app/authjs/layout.tsx
を作成し、Client Component
でsession
を扱えるようにします。
import { SessionProvider } from "next-auth/react"; export default function AuthjsLayout({ children }: { children: React.ReactNode }) { return ( <SessionProvider> {children} </SessionProvider> ) }
2-4. Page
を修正
src/app/authjs/page.tsx
を修正し、状態によって表示を分けています。
認証されている場合はsession
の中に格納されているuser
情報を表示します。
'use client' import { signIn, signOut, useSession } from "next-auth/react"; export default function AuthjsPage() { const session = useSession() if (session.status === 'loading') { return <p>loading...</p> } return ( <div> {session.status === 'authenticated' ? <div> <p>EMAIL: {session.data.user?.email}</p> <p>NAME: {session.data.user?.name}</p> <button onClick={() => signOut()}>サインアウト</button> </div> : <button onClick={() => signIn()}>サインイン</button> } </div> ); }
認証に成功した場合の表示を確認
3. サインイン
ボタンの文字列を変更
Sign in with Credentials
ではなんかダサいので、src/auth/config.ts
を修正し、文字列をIndustry One
に変更します。
# 省略 Credentials({ name: 'Industry One', # この行を追加 credentials: { email: { label: 'Email', type: 'email' }, password: { label: 'Password', type: 'password' }, }, async authorize(credentials) { # 省略
文字列がCredentials
からIndustry One
に変更されていることを確認
まとめ
今回はNext.jsでAuth.jsを使用してどのように認証認可を実装できるのか調査しました。
現時点では最低限(とりあえず動く程度)の実装となっているため、今後はバックエンドやDBを介しての認証などにトライしていきたいと考えております。
callbackの実装など、まだまだやることはありますね。
おわりに
IOでは常にエンジニアを積極採用中です!
少しでも興味を持っていただける方がいましたら、是非カジュアル面談からでも!
よろしくお願いします!