今更ながら Next.js の middleware を Auth.js から学ぶ
こんにちは、Gaji-Labo のフロントエンドエンジニア上條(mk-0A0)です。
先日 Auth.js を使用した認証機能の実装をしている際に Next.js の middleware に触れる機会がありました。middleware という名前はなんとなく知っていたのですが、具体的にどういう処理を担っているものなのかは分かっていなかったため調べたことをまとめてみたいと思います。
middleware とは
単語としての middleware は「中間」という意味です。そして Next.js における middleware とは、Next.js がリクエストの処理を行う前にリクエストのチェックをする役割を持っています。単語の意味を踏まえると、ユーザーからのリクエストと Next.js のリクエスト処理の間で処理を行うイメージです。このように中間で行われる処理を挟むことで、送られてきたリクエストに対してレスポンスを変えることができます。
middleware の用途
公式には以下6つの用途が挙げられています。
Routing: Middleware | Next.js
- 認証認可
- サーバーサイドリダイレクト
- パスの書き換え
- ボット検出
- ロギングと分析
- 機能フラグ
middleware は全ページに対して呼び出されますが、matcher
を使って特定のパスに対して実行することも可能です。リクエストのあったパスが matcher にマッチした場合は middleware を実行し、マッチしなかった場合は middleware を実行せず Next.js に処理が渡されます。
以下は Next.js のドキュメントにある matcher のサンプルコードです。
// middleware.ts
export const config = {
matcher: '/about/:path*',
}
/about
配下すべてのページに対して middleware を実行します。実際に middleware が実行されているかが確認できるコードが Example に書かれているものです。
// middleware.ts
import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'
export function middleware(request: NextRequest) {
return NextResponse.redirect(new URL('/home', request.url))
}
export const config = {
matcher: '/about/:path*',
}
新しく追加された middleware 関数はアクセスしたページが matcher にマッチする場合に実行されます。 /about
配下のページにアクセスすると /home
にリダイレクトし、matcher とマッチしないページ(/about
配下以外のページ)にアクセスした場合はそのままアクセス先のページが表示されます。
Auth.js での使い方
冒頭で少し触れましたが、Auth.js という認証ライブラリを使う際にも middleware が登場します。
Auth.js | Protecting
使い方としては Auth.js の設定ファイルである auth.ts
から Auth.js が提供する auth メソッドを export する方法が記載されていますが、これだけでは何も機能していない状態です。
// middleware.ts
export { auth as middleware } from "./auth"
// auth.ts
import NextAuth from "next-auth"
export const { auth, handlers } = NextAuth({
callbacks: {
authorized: async ({ auth }) => {
// Logged in users are authenticated, otherwise redirect to login page
return !!auth
},
},
})
middleware の用途で先述したようにリダイレクトなどの処理を実行する場合には以下のようなサンプルコードが紹介されています。
// middleware.ts
import { auth } from "@/auth"
export default auth((req) => {
if (!req.auth && req.nextUrl.pathname !== "/login") {
const newUrl = new URL("/login", req.nextUrl.origin)
return Response.redirect(newUrl)
}
})
1点注意点として、ドキュメントにも記載がある通り認可の実装は middleware だけに頼るべきではないとのことなので使い所をうまく見極める必要がありそうだなと思いました。
You should not rely on middleware exclusively for authorization. Always ensure that the session is verified as close to your data fetching as possible.
認可をミドルウェアだけに頼るべきではありません。 常に、データ取得のできるだけ近くでセッションが検証されるようにしてください。
まとめ
Auth.js を使う過程で初めて middleware を触ったため最初は全く分からない状態でしたが、ちゃんと middleware の役割から見ていくと何のために必要なのかが分かり、実装に納得感を持てました。Auth.js に関しては実装中にハマったところがあったので、もう少し調査をしつついずれ記事にしたいと思っています。
参考記事
- Routing: Middleware | Next.js
- Next.jsでの初心者向け Middleware.ts入門 (v13.1.0) + 公式マニュアル 解説 + 複数のMiddlewareの実装方法 #middleware – Qiita
Gaji-Labo フロントエンドエンジニア向けご案内資料
Gaji-Labo は Next.js 開発の実績と知見があります
フロントエンド開発の専門家である私たちが御社の開発チームに入ることで、バックエンドも含めた全体の開発効率が上がります。
「既存のサイトを Next.js に移行したい」
「人手が足りず信頼できるエンジニアを探している」
「自分たちで手を付けてみたがいまいち上手くいかない」
フロントエンド開発に関わるお困りごとがあれば、まずは一度お気軽に Gaji-Labo にご相談ください。
オンラインでのヒアリングとフルリモートでのプロセス支援にも対応しています。
フロントエンドの相談をする!