BFF(Backend For Frontend)とは
フロントエンド専用のバックエンドを用意し、ブラウザと API ドメインサーバの間に薄い層を挟む構成です。Next.js の App Router と ASP.NET Core を組み合わせる場合、BFF は Next.js 側の Route Handler が担うのが最も素直です。
構成の全体像
[Browser] ─(Cookie)─> [Next.js BFF] ─(JWT)─> [ASP.NET Core API] ─> [DB/Service]
ブラウザは BFF としか話さず、認証 Cookie もドメイン内で完結します。API ドメインサーバは JWT 経由のマシン間通信に集中でき、CORS を緩める必要がありません。
認証: OIDC を BFF に寄せる
OpenID Connect のトークン交換は BFF で完結させ、ブラウザにはHttpOnly / SameSite=Lax の短命 Cookie のみを返します。
// app/api/auth/[...nextauth]/route.ts
export const { GET, POST } = NextAuth({
providers: [EntraID({ clientId, clientSecret, tenantId })],
session: { strategy: "jwt" },
callbacks: {
async jwt({ token, account }) {
if (account) token.apiAccessToken = account.access_token;
return token;
},
},
});
データ取得: Server Components からの呼び出し
Server Component 内で BFF → API を呼び、Next.js のキャッシュ層でレスポンスをメモ化します。頻繁に更新される画面では revalidate を短く、静的ページは force-cache で。
export default async function ProductsPage() {
const res = await fetch("https://api.internal/products", {
headers: { Authorization: `Bearer ${await getApiToken()}` },
next: { revalidate: 60, tags: ["products"] },
});
const products = await res.json();
return <ProductList items={products} />;
}
ASP.NET Core 側のポイント
- JWT バリデーションは
AddJwtBearer1 行で済ませる。発行元は BFF(IdP)。 - CORS は閉じたままで OK。BFF 経由しかアクセスされないため。
- Output Caching を API 側でも併用。BFF とマルチレイヤで効かせる。
運用で気をつけること
- BFF の障害 = フロント全断なので、BFF は読み取り専用キャッシュのフォールバックを持っておく。
- トークン有効期限はログ・メトリクスに載せ、リフレッシュ失敗時にユーザーへ明示的に再ログインを促す。
- API が増えるほど BFF は肥大化しやすい。ドメインごとの BFF 分割を早めに検討する。
まとめ
Next.js の Server Components と ASP.NET Core の Minimal API は驚くほど相性が良く、BFF レイヤを一枚挟むだけで認証・キャッシュ・SSR の要件が素直に片付きます。既存の SPA + API 構成の刷新を検討中なら、まず BFF パターンへのリファクタから始めるのが費用対効果で優れています。
