Azure Application Gateway WAF を有効にした ASP.NET Core アプリで OpenID Connect ログインを行うと、IdP から戻るリダイレクトが 403 Forbidden で止まり、何度試してもログインできなくなることがあります。原因は「nonce クッキー名のランダム文字列」が WAF の攻撃シグネチャに偶然一致する誤検知です。本記事では、なぜ起きるのか、従来策の弱点、そして CRS 3.2 以降で実現できる“クッキー名だけを除外する”現実的な解決策まで整理します。
発生する現象:OpenID Connect のリダイレクトが 403 Forbidden でブロックされる
ASP.NET Core の Microsoft.AspNetCore.Authentication.OpenIdConnect を使った認証フローでは、認証チャレンジのタイミングで一時的な nonce を保持するためのクッキーが発行されます。ところが Azure Application Gateway の WAF(OWASP ルールセット)を有効にしていると、IdP からアプリに戻ってくるリダイレクト要求が WAF によりブロックされ、ログインが完了しないケースがあります。
典型的には、ブラウザ上では「403」「Access denied」「Request blocked」などの画面になり、アプリ側のログには認証完了イベントが残りません。WAF の診断ログ(Firewall ログ)を確認すると、特定のルールに一致したために Blocked になっていることが分かります。
| 観点 | 内容 |
|---|---|
| 起点 | OpenID Connect の認証チャレンジ開始時 |
| 発行されるクッキー | .AspNetCore.OpenIdConnect.Nonce.{ランダムな Base64 文字列}(値は N) |
| ブロックされるタイミング | IdP からアプリへ戻るリダイレクト要求(コールバック) |
| 結果 | WAF が 403 Forbidden を返し、認証フローが最後まで完了しない |
| 厄介な点 | nonce クッキーが残り続け、同じブラウザで再試行してもブロックが継続する |
原因:nonce クッキー名のランダム部分が WAF シグネチャに偶然一致する
この問題の本質は、アプリが悪いのでも IdP が悪いのでもなく、WAF のシグネチャ検知が「クッキー名」を検査対象に含めていることにあります。nonce クッキー名に含まれるランダムな Base64 文字列は、人間が読む前提ではなく、衝突や推測を避けるために十分にランダムです。
一方で WAF は SQL インジェクションや XSS などの攻撃パターンを文字列として検知します。ランダム文字列が、たまたまシグネチャに含まれる部分文字列(例:select、union、or 1=1、不審なエンコード断片など)に一致してしまうと、WAF は「攻撃の可能性がある」と判断してブロックします。これは誤検知(false positive)の典型例です。
nonce クッキーが「クッキー名」にランダムを含める理由
OpenID Connect の nonce は、リプレイ攻撃や CSRF に類する攻撃を防ぐために、認証要求と応答を結びつける重要な要素です。ミドルウェアは、nonce を(サーバー側セッションではなく)クッキーとして一時保存する実装を採ることがあります。その際、単一の固定名にすると衝突管理が難しいため、クッキー名をプレフィックス+ランダムにして、同時並行のログイン試行や複数タブでも安全に扱えるようにしています。
「値は N なのに、なぜ止まるのか」
誤検知を招くのはクッキーの値ではなく、クッキーの名前です。値が固定であっても、クッキー名の末尾に付くランダム文字列がシグネチャに一致すれば、WAF はブロックします。つまり、アプリが出しているデータが危険というより、「検査対象の範囲」が広すぎることが引き金になっています。
なぜ厄介か:一度当たると“クッキー削除まで直らない”ことがある
通常の OpenID Connect フローでは、認証が完了すると nonce クッキーは削除されます。しかし WAF によってコールバック要求が 403 で止められると、アプリ側のハンドラーが最後まで到達できず、nonce クッキーのクリーンアップ処理も実行されません。
その結果、ブラウザには問題の nonce クッキーが残り続けます。同じユーザーが同じブラウザで再試行すると、同じ nonce クッキーが再送される→同じ誤検知が再現→永続的にログインできないというループに入りがちです。サポート対応では「ブラウザのクッキーを消してください」で一時的に解決してしまうため、根本原因が見過ごされやすい点にも注意が必要です。
従来の対処:ルール無効化か、WAF v2 のカスタムルールで Allow
この問題が注目され始めた当初は、アプリ側(OpenID Connect)で特別な回避をするより、WAF 側で誤検知を抑えるしかない、という整理が一般的でした。実際、WAF は HTTP/HTTPS のリクエストを検査する仕組みなので、OpenID Connect プロトコルを理解して「ここは正当な nonce だから許可」といった判断はしません。
そのため、提示されがちな選択肢は次の 2 つです。
| 対処案 | 何をするか | メリット | デメリット |
|---|---|---|---|
| 誤検知している WAF ルールを除外(無効化) | 該当のルール ID/シグネチャを無効にする | 仕組みが単純。WAF v1/v2 どちらでも取りやすい | 同じルールが本来検知すべき攻撃も見逃しやすくなる |
| WAF v2 のカスタムルールで許可 | クッキー名が .AspNetCore.OpenIdConnect.Nonce* の要求を Allow | ログインが止まらなくなる | その要求に対して WAF の検査が丸ごと弱くなる(後述) |
カスタムルール Allow の落とし穴:WAF の検査が“そのリクエスト全体”でスキップされる
実運用で問題になりやすいのが、カスタムルールで「該当リクエストを Allow」した場合の副作用です。Allow は便利ですが、条件に一致したリクエストは以後の評価(マネージドルール)を通らず、SQL インジェクションや XSS などの検査も実施されなくなる構成になりがちです。
ログインのコールバック URL は、アプリにとっては“認証の入口”であり、一般にインターネットから到達可能です。ここを広くバイパスすると、もし別の脆弱性(例:リダイレクト先のパラメータ処理、セッション周り、ライブラリの既知脆弱性)があった場合に、WAF の防波堤が薄くなります。
「SQLi ルールだけ無効化」も現実的ではない理由
誤検知の原因が SQLi 系のシグネチャに偏っていると、「じゃあ SQLi のルール群を切ろう」という判断に流れがちです。しかし SQLi のルールはカバー範囲が広く、既知の攻撃パターンも多い領域です。ログイン周りのリクエストはクエリやフォームを伴うこともあり、むしろ攻撃者に狙われやすい面もあるため、ルール群の丸ごと無効化は推奨しにくい選択です。
2025 年時点の改善:除外リストで「Cookie 名だけ」検査対象から外せる
そこで現場が求めていたのが、「リクエスト全体を許可する」のではなく、誤検知の原因になっている“クッキー名”という属性だけを検査対象から外したいというアプローチです。2025 年時点のコメントでは、Azure Application Gateway WAF の除外リスト(Exclusion)機能が改善され、CRS 3.2 以降のルールセット利用時に、リクエスト属性としてクッキー名(request cookie name)を指定して除外設定できるようになった、とされています。
この方式のポイントは次のとおりです。
- 除外するのは「クッキー名」という狭い範囲で、URL・ヘッダー・ボディ・他のクッキーなどは通常どおり WAF が検査する
- Allow とは違い、リクエスト全体が“フリーパス”にならない
- OpenID Connect の仕様や ASP.NET Core 側の実装を変更せず、WAF の運用で吸収できる
| 観点 | カスタムルール Allow | 除外リスト(Cookie 名除外) |
|---|---|---|
| ログイン成功 | しやすい | しやすい |
| WAF の検査範囲 | 条件一致した要求は大きく減ることがある | 指定した属性(クッキー名)のみ除外。他の部分は検査される |
| 運用の安全性 | 条件の作り方次第でリスクが増える | 最小範囲の例外にでき、リスクを局所化しやすい |
| 依存条件 | WAF v2 前提になりがち | CRS 3.2 以降のルールセットが前提(環境差あり) |
設定の考え方:例外は“狭く・短く・観測可能に”
WAF の例外設定は、いわば「検査しない場所」を作る行為です。だからこそ、次の 3 つの方針で設計すると事故を防ぎやすくなります。
- 狭く:今回なら「Cookie 名」に限定し、さらに
.AspNetCore.OpenIdConnect.Nonceで始まるものだけ - 短く:問題が解消したら、より安全な代替(ルール微調整・ライブラリ更新)に戻せるよう棚卸しする
- 観測可能に:例外を入れた後も WAF ログで検知状況を追えるようにする
実務的な設定例:Application Gateway WAF で nonce クッキー名だけを除外する
ポータルの画面名は変更されることがありますが、概念としては「WAF ポリシーに対して、除外(Exclusions)を追加する」流れです。重要なのは、ルールセット(CRS)バージョンと、除外対象の属性を正しく選ぶことです。
手順の全体像
- 対象の Application Gateway に紐づく WAF ポリシーを特定する
- ルールセット(OWASP CRS)のバージョンを確認し、可能なら 3.2 以上にする
- 除外(Exclusion)で「Request cookie name」を選び、nonce のプレフィックスで前方一致させる
- ログインフローで 403 が解消すること、かつ他の検査が動き続けることをログで確認する
設定値の例
| 項目 | 推奨例 | 意図 |
|---|---|---|
| ルールセット(CRS) | 3.2 以上 | Cookie 名をリクエスト属性として指定できる前提を満たす |
| 除外の対象属性 | Request cookie name(同等の意味の項目) | “値”ではなく“名前”の誤検知を抑える |
| 比較方法 | Starts with(前方一致) | 末尾がランダムでも、プレフィックスで確実にマッチさせる |
| 値 | .AspNetCore.OpenIdConnect.Nonce | ASP.NET Core の nonce クッキーをピンポイントで除外する |
| 適用範囲 | 可能なら特定のルールグループではなく、属性除外で最小化 | SQLi/XSS などの検査を残す |
ポイントは、「.AspNetCore.OpenIdConnect.Nonce」までを前方一致にし、末尾のランダム文字列は条件に含めないことです。末尾はログインのたびに変わる可能性があるため、完全一致にしてしまうと再発時に追従できません。
確認の仕方:WAF ログとアプリログをセットで見る
例外設定を入れたら、次の観点で必ず確認します。
- IdP → アプリのコールバックが 200/302 で通るようになったか(ブラウザの開発者ツールやアクセスログ)
- WAF の Firewall ログで、該当リクエストが Blocked になっていないか
- 同じコールバック URL で、他の典型的な攻撃パターン(SQLi/XSS)を含むテストリクエストが検知されること
「ログインできるようになった」だけで終わらせず、“他の検査が生きている”ことまで確認しておくと、カスタムルール Allow 由来の過剰な穴を避けられます。
うっかり広げがちな例外と、そのリスク
誤検知対応は焦っていると例外を広げがちです。ありがちな設定とリスクを先に知っておくと、判断が速くなります。
| やりがちな設定 | なぜ危ないか | 代替案 |
|---|---|---|
| 「ログイン URL を全部 Allow」 | 認証入口が無防備になり、別経路の攻撃も通しやすい | Allow ではなく、誤検知している属性(Cookie 名)だけ除外する |
| 「全クッキーを除外」 | 攻撃者がクッキーにペイロードを隠しても検知できない | nonce のプレフィックスに限定した Cookie 名除外に留める |
| 「SQLi ルール群を無効化」 | SQLi の検知範囲が大きく下がる。誤検知は直っても防御が下がる | まずは属性除外。どうしても必要なら“単一ルール”単位で最小化 |
同じ構造で起きやすい関連トラブル
nonce クッキー以外にも、ASP.NET Core の外部認証では似た構造の“ランダム付きクッキー名”が使われることがあります。環境によっては、.AspNetCore.Correlation など別のプレフィックスで同様の誤検知が起きる可能性があります。
もし別のクッキーで同種のブロックが発生した場合も、基本方針は同じです。
- WAF ログで「どの属性・どの文字列が」一致したのかを特定する
- できるだけ“属性”を限定して除外する(Cookie 値ではなく Cookie 名、特定ヘッダー名など)
- リクエスト全体を Allow しない
よくある質問
CRS 3.2 以上に上げられない場合はどうする?
やむを得ず古いルールセットのまま運用する場合は、現実的には「誤検知しているルール ID を限定して無効化する」か、「WAF v2 のカスタムルールで例外を作る」になります。どちらも防御低下の可能性があるため、影響範囲を見える化し、最小化することが重要です。具体的には、ブロックに関与しているルール ID をログから洗い出し、無効化は単一ルールに留め、期間限定で運用するなどの工夫が有効です。
アプリ側で nonce クッキーの形式を変えれば解決する?
理屈の上では、クッキー名のランダム部分を別形式に変えられれば衝突確率を下げられます。ただし、OpenID Connect の実装はセキュリティと互換性を優先して設計されており、ミドルウェア内部の挙動を無理に変えると、将来の更新で破綻したり、検証の抜けが発生したりします。誤検知の吸収は、まず WAF 側で“検査対象の粒度”を調整するほうが運用として筋が良いケースが多いでしょう。
「Cookie 名だけ除外」でも安全性は落ちない?
ゼロリスクではありません。WAF がクッキー名を検査しなくなるため、理論上は攻撃者がクッキー名に攻撃パターンを埋め込んでも検知できません。ただし、一般的にアプリが参照するのはクッキーの値であり、クッキー名はアプリ側で固定のプレフィックスで探す程度です。今回のように「アプリが生成するランダム名が誤検知を起こす」ケースでは、クッキー名除外は影響範囲が小さく、Allow より安全寄りの落とし所になりやすい、というのが実務的な判断です。
再発防止のためにやっておくべきことは?
- WAF ログを Log Analytics 等に集約し、
Blockedの増加をアラート化する - 認証コールバック URL の成功率(HTTP 200/302 率)を監視する
- 例外設定を入れたら「いつ・なぜ入れたか」を運用ドキュメントに残し、棚卸し対象にする
まとめ:nonce クッキー誤検知は“Cookie 名のピンポイント除外”で被害を局所化できる
Azure Application Gateway WAF と ASP.NET Core の OpenID Connect を組み合わせると、nonce クッキー名に含まれるランダム文字列が WAF のシグネチャに偶然一致し、IdP からのリダイレクトが 403 Forbidden で止まることがあります。しかも認証完了まで到達できないためクッキーが残り、同じブラウザでは失敗が継続する点が厄介です。
従来は、該当ルールを無効化するか、WAF v2 のカスタムルールでリクエストを Allow するしかない場面がありました。しかし Allow は検査の丸ごとバイパスにつながりやすく、防御力の低下が課題でした。
2025 年時点では、CRS 3.2 以降の環境であれば、除外リスト機能により「Request cookie name」を指定して .AspNetCore.OpenIdConnect.Nonce プレフィックスだけを検査対象から外す運用が可能になり、ログインの安定性と WAF の防御を両立しやすくなっています。誤検知対応は“最小限の例外”が鉄則です。まずはクッキー名単位の除外で、問題をピンポイントに解消するところから始めてみてください。

コメント