SvelteKit + GitHub OAuthをCloudflare Workersにデプロイした話(躓きポイントまとめ)
ローカルで動作確認済みのGitHub OAuth認証をCloudflare Workersにデプロイする際、環境変数まわりで複数の躓きポイントがありました。 同じ構成(SvelteKit + adapter-cloudflare + wrangler deploy)を使う場合の参考になるようにまとめます。
構成
- SvelteKit +
@sveltejs/adapter-cloudflare - Cloudflare Pages(GitHub連携)経由で
npx wrangler deployでデプロイ - 環境変数:
GITHUB_CLIENT_ID・GITHUB_CLIENT_SECRET
躓き① $env/static/private はビルド時にしか読めない
症状
[MISSING_EXPORT] Error: "GITHUB_CLIENT_ID" is not exported by "\0virtual:env/static/private".
原因
SvelteKitの $env/static/private はビルド時に値を読み込みます。Cloudflare Pagesのビルド環境では、ダッシュボードの「変数とシークレット」はランタイム(Worker実行時)にしか使えないため、ビルド時には見つからずエラーになります。
// ❌ ビルド時に値が必要なためCloudflareのランタイム変数では使えない
import { GITHUB_CLIENT_ID, GITHUB_CLIENT_SECRET } from '$env/static/private';
解決策
platform.env を使ってランタイムに値を読み込みます。
// ✅ ランタイムにCloudflare WorkerのenvからアクセスするためOK
export const GET: RequestHandler = async ({ platform }) => {
const clientId = platform!.env.GITHUB_CLIENT_ID;
const clientSecret = platform!.env.GITHUB_CLIENT_SECRET;
};
app.d.ts の Platform インターフェースに型定義を追加します。
// src/app.d.ts
interface Platform {
env: {
DB: D1Database;
GITHUB_CLIENT_ID: string;
GITHUB_CLIENT_SECRET: string;
};
}
躓き② コールバックURLをハードコードしていた
症状
src/lib/auth.ts にローカル用のURLがハードコードされていた。
// ❌ 本番では異なるURLになるためハードコードはNG
export const github = new GitHub(
GITHUB_CLIENT_ID,
GITHUB_CLIENT_SECRET,
'http://localhost:8787/login/github/callback'
);
解決策
url.origin からコールバックURLを動的に生成します。ローカルでは http://localhost:8787、本番では https://本番ドメイン に自動的になります。
// src/lib/auth.ts
export function createGitHubClient(clientId: string, clientSecret: string, callbackUrl: string) {
return new GitHub(clientId, clientSecret, callbackUrl);
}
// src/routes/login/github/+server.ts
export const GET: RequestHandler = async ({ url, cookies, platform }) => {
const callbackUrl = `${url.origin}/login/github/callback`;
const github = createGitHubClient(
platform!.env.GITHUB_CLIENT_ID,
platform!.env.GITHUB_CLIENT_SECRET,
callbackUrl
);
// ...
};
躓き③ Cloudflareダッシュボードの変数が wrangler deploy に反映されない
症状
Cloudflareダッシュボードの「変数とシークレット」に GITHUB_CLIENT_ID を登録したのに、platform.env.GITHUB_CLIENT_ID が undefined になる。
GitHubの認証URLを見ると client_id=undefined になっていた。
https://github.com/login/oauth/authorize?client_id=undefined&...
原因
Cloudflareダッシュボードの「変数とシークレット」は、npx wrangler deploy で作成されたWorkerには自動では反映されません。
デプロイ時のバインディング一覧にも GITHUB_CLIENT_ID が含まれていませんでした。
Your Worker has access to the following bindings:
env.DB (sveltekit-blog-db) D1 Database ← D1は反映される
env.ASSETS Assets
# GITHUB_CLIENT_ID は含まれていない
解決策
wrangler secret put コマンドで直接Workerにシークレットを登録します。
npx wrangler secret put GITHUB_CLIENT_ID
npx wrangler secret put GITHUB_CLIENT_SECRET
実行するとそれぞれ値の入力を求められます。再デプロイ不要で即座にWorkerから参照できるようになります。
登録後はダッシュボードにも反映されて表示されます。ダッシュボード上の表示と wrangler secret put で登録した値は同じものです。ダッシュボードから削除すると参照できなくなるので削除しないでください。
ローカル開発での注意点
platform.env を使うようにした場合、ローカル開発では .env ではなく .dev.vars ファイルにシークレットを書きます。wranglerがこのファイルを読み込んで platform.env に渡します。
# .dev.vars(gitignoreに追加すること)
GITHUB_CLIENT_ID=ローカル用OAuthアプリのClient ID
GITHUB_CLIENT_SECRET=ローカル用OAuthアプリのClient Secret
ローカル用と本番用でOAuthアプリを分けることで、GitHubのOAuth Appsの設定を切り替えなくても両環境でそれぞれ動きます。
まとめ
| 躓きポイント | 原因 | 解決策 |
|---|---|---|
$env/static/private でビルドエラー |
ビルド時に変数が必要だがCloudflareはランタイムのみ | platform.env を使う |
| コールバックURLのハードコード | 環境ごとにURLが変わる | url.origin から動的生成 |
| ダッシュボード変数が反映されない | wrangler deploy Workerにはダッシュボード変数が反映されない |
wrangler secret put を使う |
Cloudflare WorkersとSvelteKitの組み合わせでは、環境変数を platform.env 経由で読む設計にして、シークレットは wrangler secret put で管理するのが正解です。