Next.jsのunauthorized/forbiddenを使った認証・認可エラー処理
こんにちは、エンジニアの堤です。
最近はNext.jsを使った開発をしています。
Next.jsは多種多様な機能を提供しており、公式の機能で大抵のケースは対応できるのですが、それでも対応できないケースは生じてしまいます。
その中の一つとして認証・認可のエラー処理が挙げられます 。そんな認証・認可のエラー処理が容易になるのが今後リリース予定のunauthorzed
/forbidden
APIです。本記事ではこれらの機能を試してみたいと思います。
※ これらは本稿執筆時点(Next.js 15.3.5)では実験的機能であり、以降の内容は正式リリースの際には変更になる可能性があります
既存のエラー処理
これまでNext.jsではnotFound
APIが提供されており、所謂404エラーについてはnotFound
関数とnot-found.tsx
を用いて容易に対応することができました。
ただ、認証・認可エラー処理については機能が提供されておらず、自前で対応する必要がありました。unauthorized
/forbidden
APIを使えば認証・認可エラーを404エラーと似たように処理できるようになります。
事前準備
それでは早速unauthorized
/forbidden
APIを試していきたいところですが、前述した通り現時点では実験的機能であるため、以下のようにnext.config.ts
でexperimental.authInterrupts
設定オプションを有効化する必要があります。
// next.config.ts
import type { NextConfig } from "next";
const nextConfig: NextConfig = {
experimental: {
authInterrupts: true
}
};
export default nextConfig;
unauthorized
まずはunauthorized
から試してみます。とはいえ、notFound
を使ったことがある方ならほぼ同じ感覚で利用できます。
まず以下のようにapp/unauthorized.tsx
を作成します。
// app/unauthorized.tsx
import Link from "next/link";
export default function UnauthorizedPage() {
return (
<main className="pt-10 text-center space-y-2">
<h1>401</h1>
<p>この画面にアクセスするにはログインしてください。</p>
<Link href="/sign-in" className="border border-black rounded-xs p-1">
ログイン画面へ
</Link>
</main>
);
}
あとは、認証エラーとしたい箇所でunauthorized
関数を呼び出すだけです。
// app/page.tsx
import { auth } from "@/auth";
import { unauthorized } from "next/navigation";
export default async function Dashboard() {
const session = await auth();
if (!session) {
unauthorized();
}
return (
<main className="space-y-2 pt-10 text-center">
<h1>ダッシュボード</h1>
<p>{session.user?.email}としてログインしています</p>
</main>
);
}
上記のように実装し、未ログインの状態で対象の画面にアクセスするとapp/unauthorized.tsx
の内容が表示されます。
forbidden
続いてforbidden
を試してみます。といっても、unauthorized
と使い方はほぼ同じです。
以下のようにapp/forbidden.tsx
を作成し
// app/forbidden.tsx
export default function ForbiddenPage() {
return (
<main className="pt-10 text-center space-y-2">
<h1>403</h1>
<p>この画面にアクセスする権限がありません。</p>
</main>
);
}
認可エラーとしたい箇所でforbidden
関数を呼び出すだけです。
// app/admin/page.tsx
import { auth } from "@/auth";
import { forbidden, unauthorized } from "next/navigation";
export default async function AdminPage() {
const session = await auth();
if (!session) {
unauthorized();
}
if (session.user?.role !== "admin") {
forbidden();
}
return (
<main className="space-y-2 pt-10 text-center">
<h1>管理画面</h1>
<p>{session.user?.email}としてログインしています</p>
</main>
);
}
上記のように実装し、権限のないユーザーで対象の画面にアクセスするとapp/forbidden.tsx
の内容が表示されます。
いかがでしたでしょうか。
unauthorized
/forbidden
APIにより、これまで独自で実装する必要があった認証・認可エラーについて容易に対応することが可能となります。
まだ実験的機能のため本番環境で使うのは時期尚早ですが、正式にリリースされたら積極的に活用していきたいところです。