Vercelでproduction以外の環境を外部公開したくないならVercel Authentication
Vercelを使っていて、production環境は全世界に公開するけど、stagingなど他の環境は社内のメンバーのみアクセスできるようにしたいという当たり前なことをやりたくなったのでメモ。
※全部公式ドキュメントに載ってるし管理画面見ればわかる内容です
外部からアクセスできないようにする設定
プロジェクトの設定ページにて、Deploy Protection内にあるVercel AuthenticationをONにするだけです。
これをONにすると、Redeployなしで即座にproduction以外の環境にVercelの認証がかかるようになります。
認証を通過できるのはVercelにログインしていて、該当のプロジェクトにアクセスできるメンバーのみ。
staging環境にアクセスすると認証中の表示になり、Vercelにログインしていないとログイン画面へ飛ばされます。
自前の実装なしで簡単に認証できてさすがVercel様々と言いたいところですが、このままだと問題が発生します。
当然っちゃ当然なんですがVercel Authenticationはクライアントへのアクセスのみではなく、すべてのエンドポイントに対して認証をかけるため、APIへのリクエストがすべてブロックされるようになります。
外部からのWebhook受信もブロックされるし、プロジェクト間のAPIリクエストもブロックされるし、同一プロジェクトの内部APIリクエストもブロックされるので、コンテンツベタ書きの完全にStaticなサイト以外は正常に利用できないことでしょう。
APIにリクエストできるようにする
以前はこれを通過する方法がなさそうだったため、泣き寝入りしてVercel Authenticationを使わずに自前でmiddlewareでBasic認証を実装していました。
しかし、2024年6月にProtection Bypass for Automationという機能が正式リリースされました。
VERCEL_AUTOMATION_BYPASS_SECRETを発行し、APIへのリクエストヘッダーに
'x-vercel-protection-bypass': process.env.VERCEL_AUTOMATION_BYPASS_SECRET
をつけてあげるだけで、リクエストがVercel AuthenticationをBypassできるようになります。
外部からAPIにリクエストを受ける場合はリクエストヘッダーはいじれないので、代わりにリクエストのクエリパラメータにx-vercel-protection-bypassをセットします。
自分はStripeからのイベント送信先URLの末尾に?x-vercel-protection-bypass=xxxxxxxxxxxx
をつけることで、staging環境でもWebhookを受信することができています。
プリフライトリクエストも通るようにする
APIにリクエストが通るようになって一件落着となる人も多いですが、クライアントからAPIへリクエストしている箇所がある場合はまだ問題が残ります。
プリフライトリクエストにはヘッダーもクエリもなくすべてブロックされるため、この状態だとクライアントのOPTIONSリクエストを判定できずCORSエラーになってしまいます。
これに対応するにはOPTIONS Allowlistという機能をつかいます。
OPTIONS AllowlistをONにして、対象となるエンドポイントのpathを設定すると、許可したエンドポイントでのみOPTIONSのリクエストを受け入れられるようになり、CORSを正しく判定できるようになります。
Protection Bypass for Automationの説明文にはE2Eテストなどのために用意した〜的なことしか書かかれておらずAPIのAの字もでてきませんが、API疎通しないとテストもへったくれもないですしこんな感じで使ってしまってます。これ以外の方法があるなら教えてほしい。
Discussion