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のやり取りとログ情報を取り上げています。
さらに詳しく知りたい方や、当社のサービスにご関心をお持ちの方は、お気軽にお問い合わせください。ご連絡はこちらから。