Cloud Intelligence™Cloud Intelligence™

Cloud Intelligence™

AWS Application Load BalancerのOIDCフロー — HTTP通信の流れ

By Devanshu KhannaAug 19, 20245 min read

このページはEnglishDeutschEspañolFrançaisItalianoPortuguêsでもご覧いただけます。

OpenID Connect(OIDC)は、OAuth 2.0プロトコル上に構築されたアイデンティティレイヤーで、アプリケーション側でユーザーの認証情報を管理・保管することなくユーザー認証を実現できます。AWS Application Load Balancer(ALB)は、主要なソーシャル系IdP(アイデンティティプロバイダー)、企業内アイデンティティ、そしてOIDCに準拠したあらゆるIdPと連携できます。これにより、ユーザーセッションや認証トークンの管理を信頼できるサードパーティに委ねられるため、認証の仕組みがシンプルになり、セキュリティも高まります。

サインイン体験はエンドユーザーから見ればスムーズですが、エンドユーザーとアクセス先アプリケーションの間にホップが増えるぶん、認証が失敗したときに原因を切り分けるのは簡単ではありません。

本記事では、認可コードフロー中のHTTP通信を複数の視点から可視化し、その挙動を追っていきます。

ALB側でユーザー認証を設定する手順については、公式のAWSドキュメントをご覧ください。AWSは認証機能を試せるデモサイトも公開しています。

**認証フローをステップごとに見ていきましょう —**

クラウドアプリケーションの健全性・セキュリティ・効率を保つうえで、ロギングは欠かせません。アプリケーションを監視・トラブルシュートするための手がかりを得られ、安定した安全な運用を支えてくれます。

認証フローを掘り下げるため、今回は次のログを収集しました。

  • ユーザーのWebブラウザで取得したHARファイル
  • IdPの各エンドポイント(Auth、Token、User-Info)、ALB、ターゲットアプリケーションのアクセスログ

HTTP通信を見ていく前に、まずはOIDCの各コンポーネントとその役割を押さえておくことをおすすめします。

前提条件 —

  • IdP側で、目的のスコープを指定した認可コードグラントフローが構成済みであること。Client IDとclient secretも発行済みであること。
  • ALB側で、HTTPパスが/auth*のときに「authenticate」アクションを発火させるリスナールールが設定されていること。Client ID、client secret、認可エンドポイント、トークンエンドポイント、ユーザー情報エンドポイントなどの認証リクエストパラメーターを定義します。これらはALBがIdPと通信する際に使われます。

ステップ1 — 認証を有効化したALBの背後にあるアプリへ、ユーザーがHTTPリクエストを送る

ブラウザがIdPのAuthエンドポイントへリダイレクトされます。

同じ通信に対応するALBのアクセスログ —

h2 2024–07–11T18:47:52.382721Z app/demo/25be909a3f190764 109.78.96.82:54871 - -1 -1 -1 302–359 657 "GET https://demo.aws.doit.com:443/auth.html HTTP/2.0" arn:aws:elasticloadbalancing:eu-west-1:21112316:targetgroup/TG/1a24c5faad770fb2 "Root=1–669028d8–653487fd74af592f498329f8" "authenticate"
  • ユーザーがALBへHTTP GETリクエストを送ると、認証アクションが発火します。
  • HTTPリクエストヘッダーに認証セッションCookieがない場合、ALBはHTTP 302レスポンスを返し、ユーザーをLocationヘッダーで指定されたURL(IdPの認可エンドポイント)へリダイレクトします。
  • redirect_uriは、IdPから認可コードが付与された後にブラウザがリダイレクトされる先のURLです。

ステップ2 — ユーザーがIdPの認可エンドポイントへリダイレクトされる

AuthエンドポイントへのHTTPリクエスト。

  • ユーザーがIdPの認可エンドポイントへHTTPリクエストを送信します。
  • IdPの認可エンドポイントは、ユーザーをIdPのログインエンドポイント(/login)へリダイレクトします。
  • ログインエンドポイントがユーザー認証を担います。

ステップ3 — ユーザーがログインエンドポイントへアクセスする

ログインエンドポイントへのHTTPリクエスト。

  • ユーザーがログインエンドポイントへHTTPリクエストを送ります。
  • ユーザー名とパスワードの入力欄を備えたログイン画面が表示されます。

ステップ4 — ユーザーが認証する

ユーザーがユーザー名とパスワードを入力します。

  • ユーザーがIdPのログインページで認証情報を入力します。
  • 認証に成功すると、ユーザーはIdPの認可エンドポイントへ戻されます。

POSTリクエストのペイロード例 —

csrf=izvsVKMB-GxnSvAK6McnPw6uNcZVCqqWxjeU&challenge=cbcab3062ca041399178171a4078d30b&email=user%40name.com&password=complex&submit=Log+in

ステップ5 — ユーザーがIdPから認可コードを受け取る

認可コードが付与されます。

  • IdPの認可エンドポイントは、認可コードを付けてユーザーをクライアントアプリケーションへリダイレクトします。
  • stateパラメーターの元の値はそのまま保持され、リクエストとコールバックの1対1の対応が維持されます。

ステップ6 — 認可コードを携えてユーザーがALBに戻る

認証Cookieとともに/authへリダイレクトされます。

同じ通信に対応するALBのアクセスログ —

h2 2024-07-11T18:48:27.805659Z app/demo/25be909a3f190764 109.78.96.82:54871 - -1 -1 -1 302 - 423 847 "GET https://demo.aws.doit.com:443/oauth2/idpresponse?code=ory_ac_9j6SCghDyFOexN03pTRP_GSJ5RHduhCLE-L74D2IlSs.zMsOhvXLbIrs0WQLtb43tkUnRZm0lWoI5T0IlNjnoO0&scope=openid&state=Y06EN0RLaODTpBbHGEpfK29AZJcLIpftyWwbyQN8EeiFyOtbN07H2nTXTGUa3DDYX5UgeMDsqP9psViZhPy41Y%2FVkNoJc5%2B6jb8po%2BLXQtcgxRgk9s5T0LgWt53mOEOjxL4nBVQ9Z9X1Sm%2BcZNO%2BFAIlh%2B6t99WKKj3vz1bekHiwdLWp18GUo9cp3eUkPWXbSBXprXOUHk2QlPK9xd7sG3AHyj4urRv3lc97AR4DRrVIECUMOsNP5BlYW6%2FGAg%3D%3D HTTP/2.0" "Root=1-669028fb-6e750f6c5c7fdde45853b7f6" "authenticate"
  • ユーザーがALBに認可コードを提示します。
  • ALBはHTTP 302レスポンスを返し、ユーザーを元のURI(https://demo.aws.doit.com/auth.html)へリダイレクトします。
  • このレスポンスを返す前に、ALBは次のエンドポイントへバックチャネルでリクエストを行います。

IdPのトークンエンドポイントで認可コードをIDトークンと交換する

トークンエンドポイントへのPOSTリクエスト。

UserInfoエンドポイントでアクセストークンをユーザークレームと交換する

UserInfoエンドポイントへのリクエスト。

ユーザークレーム、アクセストークン、リフレッシュトークンはbase64でエンコードされたうえで暗号化され、AWSELBAuthSessionCookieというCookieに格納されます。

ステップ7 — AWSELBAuthSessionCookieを付けて、ユーザーが元のURIへリクエストする

ユーザーはALBで認証され、リクエストはバックエンドへ届きます。

同じ通信に対応するALBのアクセスログ —

h2 2024-07-11T18:48:27.824183Z app/demo/25be909a3f190764 109.78.96.82:54871 172.31.11.119:80 0.007 0.001 0.000 200 200 596 3307 "GET https://demo.aws.doit.com:443/auth.html HTTP/2.0" "arn:aws:elasticloadbalancing:eu-west-1:211125377316:targetgroup/healthyTG/1a24c5faad770fb2 "Root=1-669028fb-156c503c2fe1fcdb60e4a5ad" 2024-07-11T18:48:27.815000Z "authenticate,forward" "172.31.11.119:80" "200"
  • ALB側の「authenticate」アクションのルール条件が満たされ、認証Cookieも揃っています。
  • ALBはCookieを検証し、ユーザー情報をX-AMZN-OIDC-*HTTPヘッダーに載せてターゲットへ転送します。

ターゲット側で確認できるX-AMZN_OIDC*ヘッダー —

X-AMZN_OIDC*ヘッダー。

x-amzn-oidc-accesstoken — トークンエンドポイントから取得したアクセストークン。

x-amzn-oidc-identity — ユーザー情報エンドポイントから取得したsubjectフィールド(sub)。

x-amzn-oidc-data — JSON Web Token(JWT)形式のユーザークレーム。

JWT形式のユーザークレームは、ヘッダー、ペイロード、署名で構成され、いずれもbase64 URLエンコードされています。ALBはJWTの署名生成にES256(P-256とSHA256によるECDSA)を用います。

デコード後のJWT —

JWTのヘッダーは、発行者、署名者の情報、キーIDを含むJSONオブジェクトです。ペイロードは、IdPのUserInfoエンドポイントから取得したユーザークレームを格納したJSONオブジェクトです。

ターゲット(Apache)はクレームに基づいてユーザーを認可し、ALB経由でHTTP 200 OKレスポンスをユーザーへ返します。

まとめ —

本記事では、AWS Application Load Balancer(ALB)を使ったOIDC認可コードフローで実際にどのようなHTTP通信が行われるのかを掘り下げて解説しました。ユーザーの最初のHTTPリクエストから最終的な認証・認可までを段階的に追い、トラブルシュートやフロー理解に役立つ主要なHTTPのやり取りとログ情報を取り上げています。

さらに詳しく知りたい方や、当社のサービスにご関心をお持ちの方は、お気軽にお問い合わせください。ご連絡はこちらから。