🌩️
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環境のサポートも継続的に改善されているようなので、定期的なアップデートとリリースノートの確認が重要だと感じました。
参考リソース
この記事で紹介したコードは、実際の本番環境で動作確認済みです。Edge環境での認証実装に悩んでいる方の参考になれば幸いです。
Discussion