ALB と Entra ID で OIDC 認証を実装する
皆さんこんにちは、手嶋です。
今回は、AWS Application Load Balancer(ALB)と Microsoft Entra ID(旧 Azure AD)を使用して OIDC(OpenID Connect)認証を実装する手順について解説します。ALB の認証機能を活用することで、アプリケーション側で認証処理を実装することなく、ロードバランサーレベルで認証を行うことができます。
なぜ ALB + Entra ID による OIDC 認証なのか
技術的背景
従来の Web アプリケーション認証では、各アプリケーション内で認証ロジックを実装する必要がありました。しかし、マイクロサービス化やマルチクラウド環境の普及により、以下の課題が顕在化しています:
- 認証ロジックの重複実装: 各サービスで同様の認証処理を実装する必要性
- セキュリティリスクの分散: 認証処理がアプリケーション層に散在することによるリスク
- 運用負荷の増大: 複数のアプリケーションでの認証設定管理
他の認証方式との比較
| 認証方式 | 実装場所 | 開発工数 | セキュリティ | 運用性 | 適用範囲 |
|---|---|---|---|---|---|
| ALB OIDC 認証 | ロードバランサー | 低 | 高 | 高 | 複数アプリ |
| アプリケーション内認証 | アプリケーション | 高 | 中(実装次第) | 低 | 単一アプリ |
| API Gateway 認証 | API ゲートウェイ | 中 | 高 | 中 | API 中心 |
この構成が適用されるケース
推奨されるケース:
- 複数の内部アプリケーションで統一認証を実現したい場合
- レガシーアプリケーションに認証機能を後付けしたい場合
- 開発チームが認証実装に工数を割けない場合
- Microsoft 365 環境との統合が必要な場合
- 静的サイト(S3)やコンテナアプリケーションへの認証が必要な場合
注意が必要なケース:
- 細かい認証制御が必要な場合
- 非 HTTPS 通信での認証が必要な場合
- 認証時のリダイレクトによる数ミリ秒の遅延も許容できないような、超低遅延が求められる API など
概要
ALB の OIDC 認証機能を使用することで、以下のメリットがあります:
- アプリケーションの簡素化: 認証ロジックをアプリケーションから分離
- セキュリティの向上: 認証されていないリクエストはアプリケーションに到達しない
- 統一認証: 複数のアプリケーションで同一の認証基盤を利用可能
- 開発工数の削減: 各アプリケーションでの認証実装が不要
- 運用負荷の軽減: 認証設定の一元管理が可能
今回の構成
今回は以下のアーキテクチャで構築します。
クライアントから ALB、Interface 型の S3 エンドポイントを経由して S3 上の静的ソースファイルにアクセスします。 ALB アクセス時には、ALB のリスナーで設定した OIDC 認証を行い、S3 バケットへのアクセス可否を判断します。
テスト用に Entra ID 側に APP-A と APP-B それぞれに所属する User A と User B を作成し、実際にテストを行います。

前提条件
- VPC構築済み
- VPCのパブリックサブネットへALB構築済み(Azure側のエンドポイントがパブリックのため、ALBからインターネットに出られる必要があります。)
- ALBのリスナー設定が済みであること
- ルート (/) へのアクセス時に index.html を返すように、ALB のルールでパスを書き換える設定を追加しておいてください。
- S3へのInterface型VPCエンドポイントが構築済み
- Microsoft Entra ID テナントへの管理者権限があること
- 検証に利用するドメインの FQDN と同名の S3 バケットが作成済みであること
- APP-A 用:
app-a.example.comバケット(ドメインは一例です、各々で用意されたものに置き換えてください) - APP-B 用:
app-b.example.comバケット(ドメインは一例です、各々で用意されたものに置き換えてください) - 各 S3 バケット内に index.html を配置しておくこと
- APP-A 用:
- Route53にて検証用ドメインからALBへのAliasレコード作成済み
- 検証用ドメインのSSL証明書が準備されていること(ACMのもので問題ありません)
前提条件が多いですが、基本的には以下のブログ記事にある構成です。 ALB、S3、PrivateLinkによる内部HTTPS静的ウェブサイトのホスティング
Entra ID でのアプリケーション登録とユーザー作成
1. アプリケーション APP-A の登録
- Azure Portalにアクセスし、Entra ID を選択

- アプリの登録 → 新規登録をクリック

- 以下の情報を入力:
- 名前:
APP-A - サポートされているアカウントの種類: この組織ディレクトリのみのアカウント
- リダイレクト URI:
Webhttps://app-a.example.com/oauth2/idpresponse
- 名前:
2. アプリケーション APP-B の登録
同様の手順で APP-B を登録します。リダイレクト URI は https://app-b.example.com/oauth2/idpresponse を設定してください。
3. クライアントシークレットの作成
各アプリケーション(APP-A、APP-B)に対して:
- 証明書とシークレットを選択

- 新しいクライアントシークレットをクリック

- 説明(例:
ALB-OIDC-Secret)と有効期限を設定
- 値をコピーして安全な場所に保存

4. テスト用ユーザーの作成
- ホームに戻りユーザー → すべてのユーザー → 新しいユーザー→新しいユーザーを作成をクリック


- User A を作成:
- ユーザー プリンシパル名:
usera@yourdomain.onmicrosoft.com - 表示名:
User A - パスワード: 一時パスワードを設定

- ユーザー プリンシパル名:
- 同様に User B を作成:
- ユーザー プリンシパル名:
userb@yourdomain.onmicrosoft.com - 表示名:
User B - パスワード: 一時パスワードを設定

- ユーザー プリンシパル名:
5. アプリケーションへのユーザー割り当て
各アプリケーションに特定のユーザーのみがアクセスできるよう設定します。
APP-A へのユーザー割り当て
- Entra ID → アプリの登録を選択

- すべてのアプリケーションを選択

- APP-A を選択します

- 概要画面にある「ローカル ディレクトリでのマネージド アプリケーション」の項目から、アプリケーション名(この場合は APP-A)のリンクを選択します

- プロパティを選択し、ユーザーの割り当てが必要ですか?をはいに設定

- 保存をクリック

- ユーザーとグループ → ユーザーまたはグループの追加をクリック

- User A を選択して割り当てをクリック

APP-B へのユーザー割り当て
APP-A へのユーザー割り当てと同様の手順で APP-B に User B を割り当てます
6. 必要な情報の取得
各アプリケーション(APP-A、APP-B)について以下の情報をメモ:
アプリケーション(クライアント)ID
エンタープライズアプリケーションの概要画面から確認できます。
ディレクトリ(テナント)ID
Microsoft Entra ID の概要画面から確認できます。
クライアントシークレット
シークレット作成時に控えていただいた値です。
ALB での OIDC 認証設定
1. APP-A 用のルール作成(ホストベースルーティング)
ALB のリスナーに対してルールを設定します。
以下の CLI コマンドでも作成可能です。値は適宜入れ替えてください。
# APP-A用のルール作成(app-a.example.com)
aws elbv2 create-rule \
--listener-arn arn:aws:elasticloadbalancing:region:account:listener/app/my-oidc-alb/xxxxxxxxx/xxxxxxxxx \
--conditions Field=host-header,Values=app-a.example.com \
--priority 100 \
--actions '[
{
"Type": "authenticate-oidc",
"Order": 1,
"AuthenticateOidcConfig": {
"Issuer": "https://login.microsoftonline.com/{tenant-id}/v2.0",
"AuthorizationEndpoint": "https://login.microsoftonline.com/{tenant-id}/oauth2/v2.0/authorize",
"TokenEndpoint": "https://login.microsoftonline.com/{tenant-id}/oauth2/v2.0/token",
"UserInfoEndpoint": "https://graph.microsoft.com/oidc/userinfo",
"ClientId": "{app-a-client-id}",
"ClientSecret": "{app-a-client-secret}",
"Scope": "openid profile email",
"SessionCookieName": "AWSELBAuthSessionCookie-AppA",
"SessionTimeout": 604800
}
},
{
"Type": "forward",
"Order": 2,
"TargetGroupArn": "arn:aws:elasticloadbalancing:region:account:targetgroup/s3-endpoint-targets/xxxxxxxxx"
}
]'
2. APP-B 用のルール作成(ホストベースルーティング)
ALB のリスナーに対してルールを設定します。
以下の CLI コマンドでも作成可能です。値は適宜入れ替えてください。
# APP-B用のルール作成(app-b.example.com)
aws elbv2 create-rule \
--listener-arn arn:aws:elasticloadbalancing:region:account:listener/app/my-oidc-alb/xxxxxxxxx/xxxxxxxxx \
--conditions Field=host-header,Values=app-b.example.com \
--priority 200 \
--actions '[
{
"Type": "authenticate-oidc",
"Order": 1,
"AuthenticateOidcConfig": {
"Issuer": "https://login.microsoftonline.com/{tenant-id}/v2.0",
"AuthorizationEndpoint": "https://login.microsoftonline.com/{tenant-id}/oauth2/v2.0/authorize",
"TokenEndpoint": "https://login.microsoftonline.com/{tenant-id}/oauth2/v2.0/token",
"UserInfoEndpoint": "https://graph.microsoft.com/oidc/userinfo",
"ClientId": "{app-b-client-id}",
"ClientSecret": "{app-b-client-secret}",
"Scope": "openid profile email",
"SessionCookieName": "AWSELBAuthSessionCookie-AppB",
"SessionTimeout": 604800
}
},
{
"Type": "forward",
"Order": 2,
"TargetGroupArn": "arn:aws:elasticloadbalancing:region:account:targetgroup/s3-endpoint-targets/xxxxxxxxx"
}
]'
ちなみに
ALB に対して設定する発行者、トークンエンドポイント、ユーザー情報エンドポイント、認証エンドポイントなどの情報は https://login.microsoftonline.com/<テナントID>/v2.0/.well-known/openid-configuration にアクセスすることで確認できます。
JSONが整形されずに表示され、非常に見にくいので Chrome に JSON Formatter などの拡張機能を導入した状態で見ると良いと思います。
S3 バケットポリシーの設定
S3 バケットへのアクセスを許可するため、各バケットにポリシーを設定します。
以下の CLI コマンドでも作成可能です。値は適宜入れ替えてください。
1. APP-A 用バケットポリシー
{ "Version": "2012-10-17", "Statement": [ { "Sid": "AllowVPCEndpointAccess", "Effect": "Allow", "Principal": "*", "Action": ["s3:GetObject", "s3:ListBucket"], "Resource": [ "arn:aws:s3:::app-a.example.com", "arn:aws:s3:::app-a.example.com/*" ], "Condition": { "StringEquals": { "aws:sourceVpce": "vpce-xxxxxxxxx" } } } ] }
2. APP-B 用バケットポリシー
{ "Version": "2012-10-17", "Statement": [ { "Sid": "AllowVPCEndpointAccess", "Effect": "Allow", "Principal": "*", "Action": ["s3:GetObject", "s3:ListBucket"], "Resource": [ "arn:aws:s3:::app-b.example.com", "arn:aws:s3:::app-b.example.com/*" ], "Condition": { "StringEquals": { "aws:sourceVpce": "vpce-xxxxxxxxx" } } } ] }
VPC エンドポイントポリシーの設定
VPC エンドポイント側でも S3 バケットへのアクセスを許可するポリシーを設定します。
以下の CLI コマンドでも作成可能です。値は適宜入れ替えてください。
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": "*", "Action": ["s3:GetObject", "s3:ListBucket"], "Resource": [ "arn:aws:s3:::app-a.example.com", "arn:aws:s3:::app-a.example.com/*", "arn:aws:s3:::app-b.example.com", "arn:aws:s3:::app-b.example.com/*" ] } ] }
VPC エンドポイントのターゲット登録
Interface 型 VPC エンドポイントの IP アドレスをターゲットグループに登録します。
以下の CLI コマンドでも作成可能です。値は適宜入れ替えてください。
# IPアドレスをターゲットとして登録
aws elbv2 register-targets \
--target-group-arn arn:aws:elasticloadbalancing:region:account:targetgroup/s3-endpoint-targets/xxxxxxxxx \
--targets Id=10.0.1.100,Port=443 Id=10.0.2.100,Port=443
動作確認とテスト
1. APP-A での認証テスト
User A でのアクセステスト:
- ブラウザで
https://app-a.example.com/にアクセス - Entra ID のログイン画面にリダイレクトされることを確認
- User A の認証情報を入力してログイン
- S3 の静的コンテンツが表示されることを確認

2. APP-B での認証テスト
User B でのアクセステスト:
- ブラウザで
https://app-b.example.com/にアクセス - Entra ID のログイン画面にリダイレクトされることを確認
- User B の認証情報を入力してログイン
- S3 の静的コンテンツが表示されることを確認

3. クロスアプリケーションアクセステスト
User A で APP-B へのアクセステスト:
- User A でログイン後、
https://app-b.example.com/にアクセス - アクセス拒否エラーが表示されることを確認(User A は APP-B に割り当てられていないため)

User B で APP-A へのアクセステスト:
- User B でログイン後、
https://app-a.example.com/にアクセス - アクセス拒否エラーが表示されることを確認(User B は APP-A に割り当てられていないため)

4. ユーザー割り当ての動作確認
正常なアクセスパターン:
- User A → APP-A:アクセス成功
- User B → APP-B:アクセス成功
拒否されるアクセスパターン:
- User A → APP-B:「AADSTS50105: Your administrator has configured the application APP-B to block users unless they are specifically granted ('assigned') access to the application.」エラー
- User B → APP-A:同様のエラーメッセージ
トラブルシューティング
よくある問題と対処法
1. リダイレクト URI の不一致
- Entra ID のアプリケーション設定で、正確なリダイレクト URI が設定されているか確認
- ALB のドメイン名が正しく設定されているか確認
2. 認証後にエラーが発生する
- クライアントシークレットの有効期限を確認
- スコープの設定が正しいか確認
Microsoft Entra admin center で認証のログを確認することが可能です。
確認手順
Microsoft Entra 管理センターへのサインイン
Microsoft Entra 管理センターに管理者権限を持つアカウントでサインインします。
- サインインログへの移動
左側のナビゲーションメニューから [ID] > [監視と正常性] > [サインイン ログ] の順に選択します。 - 非対話型サインインログの表示
表示されたサインインログのページで、[非対話型のユーザー サインイン] タブをクリックします。 - ログの絞り込みと確認
必要に応じて、画面上部のフィルター機能を利用し、「日付」や「アプリケーション名」などでログを絞り込みます。
一覧から対象のログを選択すると、認証時刻、IPアドレス、リソース、認証の状態(成功/失敗)などの詳細情報を確認できます。
3. セッションが維持されない
- セッションクッキーの設定を確認
- HTTPS が正しく設定されているか確認
4. ユーザーがアプリケーションにアクセスできない
- Entra ID でユーザーがアプリケーションに正しく割り当てられているか確認
- アプリケーションの「ユーザーの割り当てが必要ですか?」設定が「はい」になっているか確認
- ユーザーが適切なロールまたは権限を持っているか確認
ログの確認方法
ALB のアクセスログを有効化して、認証関連のエラーを確認できます:
# ALBアクセスログの有効化
aws elbv2 modify-load-balancer-attributes \
--load-balancer-arn arn:aws:elasticloadbalancing:region:account:loadbalancer/app/my-alb/xxxxxxxxx \
--attributes Key=access_logs.s3.enabled,Value=true \
Key=access_logs.s3.bucket,Value=my-alb-logs-bucket
セキュリティ考慮事項
1. セッション管理
- セッションタイムアウトを適切に設定
- 必要に応じてセッションの無効化機能を実装
2. スコープの最小化
必要最小限のスコープのみを要求するようにしてください。
まとめ
ALB と Entra ID を使用した OIDC 認証の実装により、以下を実現できました:
- 認証の一元化: Entra ID による統一認証
- アプリケーションの簡素化: 認証処理を ALB に委譲
- セキュリティの向上: 認証されていないリクエストの遮断
この構成により、複数のアプリケーションで統一された認証基盤を構築できます。また、Entra ID の豊富な認証機能(多要素認証、条件付きアクセスなど)も活用できるため、セキュリティレベルの向上も期待できるでしょう。
以上です。
参考資料
- Application Load Balancer でのユーザー認証 - AWS Documentation
- Microsoft Entra ID でのアプリケーション登録 - Microsoft Documentation
- OpenID Connect プロトコル - OpenID Foundation
- Microsoft Entra ID のサインインログ - Microsoft Entra ID
- Microsoft ID プラットフォームでの OpenID Connect (OIDC) - Microsoft identity platform
- ALB、S3、PrivateLinkによる内部HTTPS静的ウェブサイトのホスティング