認証認可アーキテクチャの変遷(2)API Gatewayとマイクロサービス
本シリーズは5部構成である。
- 第1部: モノリスから認証基盤へ
- 第2部(本記事): API Gatewayによる統制とマイクロサービス対応
- 第3部: クライアント認証の高度化と段階的移行
- 第4部: 認可サーバーの内部構造と信頼性設計
- 第5部: 自作認可サーバーのデータモデルと運用設計
第1部で認証基盤(IdP)を導入し、ログインとユーザー管理は一元化された。しかしAPIの数が増え、モノリスが分割され始めると、今度はトークンを受け取る側(Resource Server)の統制が問題になる。第2部はここを扱う。
Stage 2の手前: 「各サービスが個別にトークン検証する」構成の破綻
IdP導入直後の自然な構成はこうだ。各APIサービスがJWTライブラリを組み込み、それぞれIdPのJWKSエンドポイントから公開鍵を取得して署名検証する。
サービスが3個ならこれで回る。しかし10個、30個と増えると次の問題が顕在化する。
- 実装のばらつき: あるサービスは
expしか見ておらずaudを検証していない、別のサービスはalg: noneを許すライブラリの古いバージョンを使っている——検証ロジックがサービス数だけ存在し、セキュリティ水準が最も弱い実装に律速される - 横断的ポリシーの適用不能: 「全APIにレート制限を入れたい」「特定のトークン発行元を緊急ブロックしたい」が、全チームへの依頼作業になる。インシデント対応の速度が組織のコミュニケーション速度に縛られる
- 言語・フレームワークごとの重複投資: Go/Java/Python/Nodeそれぞれで検証ミドルウェアを整備・保守する
- 監査の困難: 「どのAPIがどんな認可判断をしているか」の全体像を誰も持っていない状態になる
つまり課題の本質は技術ではなくガバナンスである。この認識が、API Gatewayを「便利なリバースプロキシ」ではなく「統制の実行点」として理解する鍵になると考えている。
Stage 2: API Gatewayによる認証の集約
Gatewayが全リクエストの入口に立ち、トークン検証・レート制限・監査ログ・TLS終端といった**横断的関心事(cross-cutting concerns)**をオフロードする。各サービスはビジネスロジックに集中できる。
なぜマイクロサービスの隆盛とセットで語られるのか
API Gatewayの必要性はマイクロサービスの隆盛と不可分だ。因果を分解するとこうなる:
- マイクロサービスは「チームごとに独立してデプロイできる」ことが価値であり、サービス数が組織のチーム数に比例して増える
- サービスが増えるほど、上記の「ばらつき・重複・監査不能」問題が指数的に悪化する
- 同時に、クライアントから見ると「エンドポイントがサービスごとに分かれていて呼びにくい」という別の問題も生じ、単一エントリポイントへの需要が生まれる
- この2つの需要(統制と集約)が合流した地点がAPI Gatewayである
逆に言えば、サービスが数個で単一チームならGatewayは過剰であることが多い。nginxとミドルウェア共通ライブラリで十分なことは多く、Gateway製品の導入・運用コスト(それ自体が一つの分散システムだ)を正当化できるかは冷静に見た方がよい。
認証と認可の分担パターン
「Gatewayで何をどこまでやるか」には設計の幅がある。ここがこの記事で一番伝えたい比較だ。
| パターン | Gatewayの責務 | サービスの責務 | 向いているケース |
|---|---|---|---|
| A. 認証のみ集約 | トークンの署名・有効期限・issuer検証。検証済み情報をヘッダでサービスに伝搬 | 認可のすべて(このユーザーがこのリソースを触れるか) | 認可ロジックがドメインに深く依存する場合。最も一般的 |
| B. 粗粒度認可も集約 | A + 「このAPIパスにはこのスコープ/ロールが必要」の宣言的チェック | 細粒度認可(リソース単位・行レベル) | APIの公開範囲を統制したい場合。B2B API公開など |
| C. 全認可を集約 | すべての認可判断 | なし(信頼して実行) | 認可ルールが単純で変化が少ない場合のみ。ドメイン知識がGatewayに漏れ出すのでスケールしない |
実務の均衡点はAかBだ。**認可は「粗粒度はエッジで、細粒度はドメインの近くで」**が原則だと考えている。「この注文を編集できるのは注文者本人か管理者」のような判断は注文ドメインの知識であり、Gatewayに置くとGatewayがドメインロジックの墓場になる。
もう一つ重要な原則がある。Gatewayで検証したからといって、内部サービスが検証を完全に省略してよいわけではない。Gatewayを迂回する内部経路(デバッグ用ポート、サービス間直接通信)が存在した瞬間に無防備になるからだ。これは境界防御の限界の話であり、ゼロトラストネットワークの発想——ネットワーク位置を信頼の根拠にしない——がマイクロサービス内部にも適用されるべき理由でもある。最低限、Gatewayが付与する署名付きヘッダやJWTをサービス側でも検証する「多層防御」を残すのが健全だ。
Phantom Tokenパターン
第1部で述べたJWT(失効できない・中身が見える)と参照トークン(AS往復が重い)のトレードオフを、Gatewayの存在を前提に両取りするのがPhantom Tokenパターンである。
- 外部には参照型(opaque)トークンだけを渡す → 中身が漏れない、即時失効できる
- 内部ではGatewayがJWTに交換して流す → 各サービスはローカル署名検証だけで済み、内部クレーム(社員区分、テナントIDなど)も安全に載せられる
失効の即時性・情報秘匿・検証性能を同時に満たせる代わりに、Gatewayとイントロスペクションが必須インフラになる。「外部にJWTを直接渡している構成」からの改善先として覚えておく価値が高いパターンだと思う。
GatewayとASの配置関係 — 依存の向きと経路の分離
Gatewayを導入するとき、意外と設計されないまま進むのが「ASをネットワーク上のどこに置くか」だ。素朴には「ASもAPIの一種だからGatewayの後ろに置けば統制できる」と考えたくなるが、これはアンチパターンだと考えている。一般形は「エッジ(WAF/LB/CDN)は共有してよいが、ASはGatewayの配下に置かない」で、auth.example.com(AS直行)と api.example.com(Gateway経由)のようにホスト名から経路を分ける。理由は3つある。
- 依存の向きを一方向に保つため。GatewayはASに依存している(JWKS取得、イントロスペクション)。ASをGateway配下に置くと循環依存になり、Gateway障害時にトークン発行まで巻き込まれる・デプロイや起動の順序が絡まる・障害の切り分けが困難になる。「GatewayはASなしでは機能しないが、ASはGatewayなしで完結する」という一方向の依存が健全な形だ
- 可用性等級が違うため。ASは全サービスのログインとトークン発行の前提であり、システム全体で最も高い可用性が要る。Gatewayと同じインフラ・同じデプロイパイプラインに載せると、Gatewayの変更リスクがASの可用性に直結してしまう
- トラフィックの性質が違うため。Gatewayのポリシー(トークン検証、スコープチェック)は「トークンを持ったAPIコール」向けだが、ASの認可エンドポイントに来るのはまだトークンを持っていないブラウザだ。ここで必要な防御はトークン検証ではなく、WAF・bot対策・ログイン試行のレート制限(クレデンシャルスタッフィング対策)であり、守り方がそもそも別物である
さらにAS自身の中でも、エンドポイントごとに露出を分ける設計が定石になる。「誰が呼ぶか」が違うものを同じ経路に出す理由はない、という最小権限の原則のネットワーク版だ。
| エンドポイント | 露出 | 理由 |
|---|---|---|
| /authorize, /token, /jwks, /.well-known | 公開(WAF越し) | クライアントやブラウザが直接叩く |
| introspection, Token Exchange | 内部ネットワークのみ | 呼ぶのはGatewayとRSだけ。外部に出す理由がない |
| 管理API(クライアント登録など) | 管理プレーンとして完全別系統 | 侵害されると全クライアントの信頼が崩れる |
保証レベルの高いドメインでは、署名鍵をHSM/KMSに置いて署名操作だけを切り出し、ASプロセス自体は秘密鍵の平文に触れない構成まで踏み込むこともある。「ASが漏れても鍵は漏れない」を作れるかどうかは、インシデント時の影響範囲を一段変える。
Gatewayを外部と内部で分ける
配置の話をもう一段進めると、「Gateway自体を外部向けと内部向けで分ける」構成もよく採られる。一見冗長に見えるが、「Gateway」と一口に呼ばれているものには実は3種類の需要が混ざっていて、分離はそれを解きほぐす行為だと考えると腑に落ちる。
| 外部Gateway | 内部Gateway | サービス間(east-west) | |
|---|---|---|---|
| クライアント | パートナー、公開API利用者、モバイルアプリ | 社内アプリ、社員向けツール、別部門 | サービス同士 |
| 脅威モデル | 厳しい。WAF、bot対策、審査済みクライアントのみ | 緩やか。社内IdP・ネットワーク制御と併用 | なりすまし・盗聴(Stage 3で扱う) |
| 変更頻度 | 低い。公開APIは互換性契約なのでうかつに触れない | 高い。社内APIは日々増える | — |
| トークン | opaque外部/JWT内部の変換点(Phantom Token) | JWTのまま | サービスメッシュ + ワークロードID |
| 統制スタイル | 審査・承認(門番型) | ガードレール型、速度優先 | プラットフォームで自動化 |
このうちeast-westは、そもそもGatewayに通すべきではない、というのが現在の主流の整理だ。全サービス間通信を中央の箱に通す構成はレイテンシと単一障害点の両面で筋が悪く、そこはメッシュ(あるいはトークン検証の共通ライブラリ)に任せて、Gatewayはnorth-south(外から中への流れ)に限定する。
残ったnorth-southを外部/内部で分ける価値は、直前のAS配置の議論と同型で、脅威モデル・変更頻度・所有権が違うものを同じ箱に入れないことにある。社内APIの日々の雑多な変更が外部公開インフラの変更リスクになる同居構成は、爆風半径の設計として悪い。外部Gatewayの障害や変更事故が社内業務を止めず、その逆もない、という独立性が手に入る。組織面でも、外部GatewayはセキュリティやAPIプロダクトのチーム、内部Gatewayはプラットフォームチーム、と所有を分けやすく、統制のスタイル(門番型とガードレール型)をそれぞれに合ったものにできる。
トレードオフは素直で、運用の二重化(製品・監視・ポリシー定義の重複)と、「このAPIはどちらに載せるのか」という判定の混乱だ。後者は判定基準を「クライアントが組織外か否か」の一点に絞って明文化しておけば大半は防げる。基準を「重要度」や「機密性」のような程度問題にすると、載せ替え論争が常態化する。
導入も段階論でよい。サービスが少ないうちは1つのGatewayにリスナー/仮想ホストを分けて論理分離しておき、外部公開が本格化した時点——外部クライアントの審査プロセスが回り始め、公開APIの変更管理が社内と別リズムになった時点——で物理分離する、が現実的な移行線だと思う。
Stage 3: マイクロサービス間の認証認可
Gatewayで入口は統制できた。次の問題は内部だ。サービスAがサービスBを呼ぶとき、Bは何を根拠に許可するのか。
課題1: ユーザーコンテキストの伝搬とConfused Deputy
サービスAがユーザーのトークンをそのままBに横流しすると、audienceが合わない(本来Aに向けて発行されたトークンをBが受け入れてしまう)。かといってAが自分の権限(強い権限を持ちがち)でBを呼ぶと、本来そのユーザーには許されない操作をAが代行してしまう——古典的なConfused Deputy問題である。呼び出しチェーンが深くなるほど「今この処理は誰の権限で動いているのか」が失われていく。
これに対する標準解が**Token Exchange(RFC 8693)**だ。サービスAは手元のトークンをASに提示し、「宛先をBに限定した(aud=B)、必要スコープだけの」新トークンに交換してから呼び出す。
ユーザーの同一性(sub)を保ったまま、権限を宛先ごとに絞り込める。最小権限の原則をサービス呼び出しチェーンに適用する仕組みと言える。代償はAS呼び出しの増加とレイテンシで、全ホップで律儀に交換するか、信頼境界をまたぐ時だけ交換するかは性能との相談になる。
課題2: サービス自身のアイデンティティ
ユーザーが介在しないバッチや非同期処理では、サービス自身が主体になる。選択肢は:
| 方式 | 仕組み | 特徴 |
|---|---|---|
| Client Credentialsフロー | サービスがOAuthクライアントとしてASからトークン取得 | OAuthの枠内で完結。クレデンシャル(secret/秘密鍵)の配布・ローテーションが課題 |
| mTLS | 相互TLS。証明書でサービスを識別 | 強固だが証明書ライフサイクル管理が重い |
| サービスメッシュ + SPIFFE/SPIRE | サイドカーが自動でワークロードID(SVID)を発行・ローテーション | mTLSの運用問題をプラットフォーム化で解決。導入自体が大仕事 |
実務ではこれらは排他ではなくレイヤーとして併用される。「メッシュのmTLSでサービスのなりすましを防ぎ(トランスポート層)、OAuthトークンでユーザーコンテキストと権限を運ぶ(アプリ層)」という組み合わせが、大規模構成の一つの到達点だと考えている。トランスポート層の認証はユーザーの権限を運べないし、トークンはネットワーク経路のなりすましを防げない。守っているものが違う。
課題3: 認可ポリシーの置き場所 — PDP/PEPモデル
認可判断が各サービスに散らばると再び統制問題が起きる。これに対してポリシー判断(PDP: Policy Decision Point)と実行(PEP: Policy Enforcement Point)を分離するアーキテクチャがある。OPA(Open Policy Agent)をサイドカーで置き、ポリシーをRegoで中央管理しつつ判断自体は各Podのローカルで行う、という構成が代表例だ。リソース間の関係性で認可を表現したい場合はGoogleのZanzibarに連なるReBAC系(SpiceDB, OpenFGA)が選択肢になる。
ただし正直なところ、中央集権的なポリシー管理が真に必要な組織は多くない気がする。「認可ロジックの散在」は、ポリシーエンジン導入よりも「共通ライブラリ + スコープ設計の規約化」で十分解決できるケースが大半で、PDP導入は監査要件が厳しい規制産業や、テナント越境が致命傷になるマルチテナントSaaSでこそ効く投資だと思う。
組織設計と統制のトレードオフ
このシリーズで一番書きたかった節かもしれない。Stage 2〜3の技術選択は、実はほぼ組織論である。
Conwayの法則の作用
API Gatewayと認証基盤は、組織図の上では「プラットフォームチーム」の持ち物になる。すると:
- 統制側のメリット: セキュリティポリシー・監査ログ・レート制限を一点で強制できる。コンプライアンス(SOC2、PCI DSS)の証跡が揃う。インシデント時に一点で遮断できる
- 自律側のコスト: 各サービスチームのデプロイ・変更がGatewayチームの作業待ちになる。「ルーティング1本追加に1週間」のような状態になると、マイクロサービスの本来の価値(チームの独立性)が殺される
つまりGatewayは技術的チョークポイントであると同時に、組織的チョークポイントになりうる。これを緩和する定石は:
- セルフサービス化: ルーティングやクライアント登録をGitOps化し、プラットフォームチームは「レビューとガードレール提供」に回る。宣言的設定 + CIでのポリシー検査(例: 「認証なしルートの追加はセキュリティチームの承認必須」を機械的に強制)
- ガードレール型統制: 「全部を承認制にする」のではなく「危険な変更だけ検知して止める」。統制を門番からレールに変える発想
- Gatewayの分割: 事業ドメインごとにGatewayを分け、中央は共通ポリシー(認証、監査)だけを共有モジュールとして配る。「単一の巨大Gateway」は単一障害点かつ政治的係争地になりやすい
中央集権と分散のどちらが正しいか
正しさは組織のフェーズに依存する、というのが私の考えだ。
- 規制が強い/インシデントの影響が大きいドメイン(金融、医療)→ 中央統制寄りに倒す。開発速度の犠牲は保険料として払う
- 競争環境で速度が生命線のドメイン → 分散寄りに倒し、統制は「観測(ログ・検知)」で担保する。事前統制から事後検知へ
- 危険なのは中間の無自覚、つまり「統制の建前だけあって実効性がない」状態。全チームがGateway申請を面倒がって回避経路(直接公開、トンネリング)を作り始めたら、統制は形骸化している。統制はそれに従うコストが回避するコストより低いときだけ機能する
Stage 2〜3 の難易度まとめ
| 移行 | 技術難易度 | 組織難易度 | 前提条件 |
|---|---|---|---|
| Gateway導入(認証集約) | 中 | 中 | IdPが安定稼働していること |
| Phantom Token | 中 | 低 | Gateway + introspection対応AS |
| Token Exchange | 中〜高 | 中 | ASの対応(対応製品がまだ限られる)、サービス側の改修 |
| サービスメッシュ + ワークロードID | 高 | 高 | K8s基盤とプラットフォームチームの成熟 |
| PDP/PEP分離(OPA等) | 高 | 高 | ポリシーを書き運用し続ける体制。中途半端な導入は負債化 |
Stage 3のフルセットが必要な組織は少数派で、多くの組織は「Gateway + パターンA/B + Client Credentials」で長く戦える。難易度の高いパターンを採用すること自体に価値はなく、課題が顕在化してから段階的に足すのが健全だと思う。
第3部(クライアント認証の高度化と段階的移行)では視点をクライアント側に移し、Bearerトークンの本質的弱点、PKCE、private_key_jwt、mTLS、DPoPによる送信者制約、BFFパターン、そしてシリーズ全体を通した段階的移行戦略を扱う。
