Cloudflare WorkersでAuth.jsを使うときのハマりポイント
TL;DR
- Auth.js v4はNode.js依存のため、Cloudflare Workers(Edge Runtime)では動作しない
- Auth.js v5はEdge Runtime対応だが、特定のバージョンで問題が発生
-
next-auth@5.0.0-beta.4以降でtrustHost: trueの設定が必須 - HTTPSモジュール依存からfetch API依存への根本的な設計変更が必要
はじめに:Edge環境での認証実装の落とし穴
Next.jsアプリケーションをCloudflare Workersにデプロイする際、最も厄介な問題の1つが認証の実装だと思います。
開発環境(Node.js): ✅ 完璧に動作
本番環境(Edge Runtime): ❌ 謎のエラーで動かない
この記事では、Auth.js v4からv5への移行で遭遇した具体的なエラーと、その解決方法を詳しく解説しようと思います。
環境と前提条件
プロジェクト環境:
- Next.js: 15.0.4
- デプロイ先: Cloudflare Workers
- ビルドツール: @opennextjs/cloudflare
- 認証プロバイダー: Okta
要件:
- SSO(シングルサインオン)必須
- Edge環境での高速レスポンス
- サーバーレスでのコスト最適化
問題1:Auth.js v4がEdge環境で動作しない
Node.js APIの不在
# Auth.js v4での実装
npm install next-auth@^4.24.0
(バージョンを指定しなければ、v4系がインスコされるはずです。)
開発環境では完璧に動作していたコードが、Cloudflare Workersにデプロイした際のエラー
[unenv] https.request is not implemented yet!
[unenv] buffer.Buffer() is not implemented yet!
Error: There was a problem with the server configuration.
Check the server logs for more information.
根本原因:Auth.js v4のアーキテクチャ
Auth.js v4の内部実装を調査すると、以下の問題が判明
// Auth.js v4の内部実装(簡略化)
const https = require('https');
const { Buffer } = require('buffer');
// OAuthプロバイダーとの通信
function makeOAuthRequest(url, options) {
return new Promise((resolve, reject) => {
const req = https.request(url, options, (res) => {
// Node.js固有のStream API使用
let data = Buffer.alloc(0);
res.on('data', (chunk) => {
data = Buffer.concat([data, chunk]);
});
});
});
}
問題点:
-
httpsモジュール:Node.js固有のAPI -
Buffer:Node.js固有のバイナリデータ処理 - Stream API:Edge Runtimeには存在しない
Cloudflare WorkersのランタイムとNode.jsの違い
| 機能 | Node.js | Cloudflare Workers |
|---|---|---|
| 実行環境 | V8 + Node.js APIs | V8 + Web APIs |
| HTTPクライアント |
http/https
|
fetch |
| バイナリ処理 | Buffer |
ArrayBuffer/Uint8Array
|
| ファイルシステム | fs |
❌ 利用不可 |
| データ処理 | Stream API | Web Streams API |
問題2:Auth.js v5の初期バージョンでの問題
v5への移行開始
# Auth.js v5(beta)へのアップグレード
npm uninstall next-auth
npm install next-auth@beta
新たなエラー:ホスト検証の問題
UntrustedHost: Host must be trusted. URL was: https://my-app.workers.dev/api/auth/session.
Read more at https://errors.authjs.dev#untrustedhost
バージョン別の動作検証
実際に検証したバージョンと結果:
| バージョン | Edge対応 | ホスト検証 | 結果 |
|---|---|---|---|
| v4.24.7 | ❌ | - | Node.js依存でエラー |
| v5.0.0-beta.3 | ✅ | 緩い | ✅ 動作(但し非推奨) |
| v5.0.0-beta.4以降 | ✅ | 厳格 | ❌ trustHost未設定でエラー |
| v5.0.0-beta.4以降 | ✅ | 厳格 | ✅ trustHost: trueで解決 |
技術的背景:なぜホスト検証が強化されたのか
// Auth.js v5.0.0-beta.4での変更
function assertOrigin(request: Request) {
const url = new URL(request.url);
const origin = request.headers.get("Origin");
// Edge環境でのセキュリティ強化
if (process.env.AUTH_TRUST_HOST !== "true") {
if (!origin || origin !== url.origin) {
throw new UntrustedHost(
`Host must be trusted. URL was: ${url}`
);
}
}
}
この変更により、CSRF攻撃に対するセキュリティは向上しましたが、Edge環境では予期しない問題が発生しました。
解決策:正しい設定と実装方法
ステップ1:適切なバージョンの選択
{
"dependencies": {
"next-auth": "5.0.0-beta.29" // 最新の安定版を使用
}
}
ステップ2:Edge環境対応の設定
// auth.config.ts
import type { NextAuthConfig } from "next-auth"
import Okta from "next-auth/providers/okta"
export const authConfig = {
providers: [
Okta({
clientId: process.env.OKTA_CLIENT_ID,
clientSecret: process.env.OKTA_CLIENT_SECRET,
issuer: process.env.OKTA_ISSUER,
}),
],
// Edge環境での必須設定
trustHost: true,
// Edge環境でのセッション戦略
session: {
strategy: "jwt", // 今回はDBレスで実装
},
// デバッグ情報(開発時のみ)
debug: process.env.NODE_ENV === "development",
} satisfies NextAuthConfig // パッケージ名はnext-authのまま
Edge環境特有の注意点とベストプラクティス
1. fetch APIの活用
// Edge環境対応
const response = await fetch('https://api.example.com', {
headers: {
'Authorization': `Bearer ${token}`
}
})
2. セッション管理の最適化
// Edge環境でのJWTカスタマイズ
callbacks: {
async jwt({ token, account, profile }) {
if (account && profile) {
// 最小限の情報のみ保存(JWTサイズ削減)
token.id = profile.sub
token.email = profile.email
// ❌ 大きなオブジェクトは避ける
// token.fullProfile = profile
}
return token
},
}
まとめ:Edge環境での認証実装のポイント
- 正しいバージョン選択:Auth.js v5.0.0-beta.4以降を使用
- trustHost設定:Edge環境では必須
- JWT戦略:データベース不要でEdge環境に最適
- fetch API活用:Node.js APIを避ける
今後の展望
Auth.jsは急速に進化しており、Edge環境のサポートも継続的に改善されているようなので、定期的なアップデートとリリースノートの確認が重要だと感じました。
参考リソース
追記
Auth.js(旧 NextAuth.js)は、今後 Better Auth チームによってメンテナンス・運営されることになったとのことです。新しいプロジェクトを始める場合は、 Better Auth を推奨します。
(データベースなしでステートレスなセッション管理も、Better Auth の機能として取り込む予定)
Auth js is now part of Better Auth. We recommend new projects to start with Better Auth unless there are some very specific feature gaps (most notably stateless session management without a database).
ref: https://github.com/nextauthjs/next-auth/blob/main/README.md
better-auth 側のページ
この記事で紹介したコードは、実際の本番環境で動作確認済みです。Edge環境での認証実装に悩んでいる方の参考になれば幸いです。
Discussion