🔐
Python × Microsoft Entra ID で学ぶ OAuth 2.0 OBO フロー [最小実装サンプル付き]
はじめに
マイクロサービスやBFF構成で「ユーザーの代わりに下流APIを呼びたい」という要件はよくあります。
Microsoft Entra ID(旧Azure AD)では、OAuth 2.0の On-Behalf-Of(OBO)フローを使うことで、ユーザーの認証情報を安全に引き継ぎながらAPI連携が可能です。
本記事では以下を解説します:
- OBOフローの仕組み
- Python(Flask + MSAL)による最小実装
- 処理シーケンス図(Mermaid対応)
- 誤りやすいパターンと対策
- セキュリティベストプラクティス
OBOフローとは?
OBOフローは、「あるサービス(バックエンド)が、ユーザーの代わりに別のサービス(下流API)を呼び出す」 ための仕組みです。
典型的なシナリオ:
- フロントエンド(SPAやWebアプリ) がユーザーを認証し、バックエンドAPIにアクセス
- バックエンドAPIは受け取った ユーザーのアクセストークン を使って Microsoft Graphや社内API を呼び出す(実際にはOBOで新しい下流API用ATを発行して使用)
Pythonでの最小実装(概要)
-
frontend_app(Flask)
認可コードフローでサインイン →api://<BACKEND>/access_as_user
のATを取得 → バックエンドAPIへ -
api_app(Flask)
msal.ConfidentialClientApplication.acquire_token_on_behalf_of(...)
で Graphの委任スコープ(例:User.Read) を要求 →/v1.0/me
を呼ぶ
実装コードは GitHubリポジトリ(https://github.com/naokky-tech/sample-oboflow) を参照。
サンプル実装
OBOフローの処理シーケンス
✅ Azure Portal 設定手順
目的
- フロントエンド用アプリ(public / SPA 可)
- バックエンド API 用アプリ(confidential)を 1 テナント内に登録し、OBO に必要なカスタムスコープ
access_as_user
を発行します。
1-1. バックエンド API アプリを登録する
-
同様に アプリの登録 で作成
-
アプリケーション (クライアント) ID と ディレクトリ (テナント) ID をメモ
1-2. バックエンド API の公開 → カスタムスコープを作成
- カスタムスコープの設定
- API の公開 → 「Scope の追加」
- Scope 名を
access_as_user
に設定 - 同意の表示名・説明は「ユーザーのアクセス権限による検索」など任意
- 保存して続行
1-3. バックエンド API が利用して良いGraphAPIの権限(スコープ)を追加する
- GraphAPI権限設定
- API のアクセス許可 → アクセス許可の追加
- 利用したいGraphAPIの権限 をチェック(サンプル実装ではUser.Readのみ利用)
- アクセス許可の追加 をクリック
- (組織テナントなら)管理者の同意 を与えておく
1-4. バックエンド API用のクライアント シークレットを作成
- クライアントシークレット
- 証明書とシークレット → 新しいクライアント シークレット
- 説明と有効期限を設定し 追加
- 生成直後に表示される 値 をメモ(再表示不可)
メモを忘れた場合は 新しくシークレットを作り直してください。
.env
のBACKEND_CLIENT_SECRET=
に貼り付けます。
2-1. 新しいアプリを登録する(フロントエンド)
- フロントエンドのアプリ登録
- アプリの登録 → 新規登録
- 任意の名前を入力
- 「この組織…シングルテナント」を選択
- リダイレクト URI は空で OK(後で追加可能) ※demoではローカル端末でフロントエンドのアプリを実行するため "http://localhost:5000/auth/redirect" として登録(実装に合わせる)
- 登録をクリック
2-2. フロントエンドにスコープを付与
- バックエンドAPIのスコープ付与
- API のアクセス許可 → アクセス許可の追加
- 「<APIアプリ名>」→ access_as_user をチェック
- アクセス許可の追加 をクリック
- (組織テナントなら)管理者の同意 を与えておく
✅ pythonでサンプルアプリ実装
gitからクローンしてお試しください。
1. リポジトリをクローン
git clone https://github.com/naokky-tech/sample-oboflow.git
cd sample-oboflow
2. 手順に従い実行
詳細な手順はgitを参照ください。
- 仮想環境を作成して有効化
- 依存パッケージをインストール
- .env ファイルの設定
- 起動と動作確認
動作させると以下のようにUser.Readの権限に基づいた情報が取得できていることが確認できます。
OBOフローのはまりポイント
OBOで使えないケース
- カスタム署名キーを使うアプリ
- ワイルドカードReply URL + id_token
- App-onlyトークンをassertionに使用(OBOはユーザー主体のみ)
よくある落とし穴と対策
誤り | 症状 | 対処 |
---|---|---|
IDトークンを渡す | invalid_grant |
アクセス トークン(aud=バックエンド) を渡す |
フロントでGraphスコープ要求 | aud不一致 | フロントは access_as_user 、Graphはバックエンドで要求 |
バックエンドにGraph権限なし | insufficient privileges |
バックエンドに User.Read を付与+管理者同意 |
SPAでOBO実行 | 認証エラー | 機密クライアント(バックエンド)で実行 |
OBOトークンをクライアントに返却 | セキュリティリスク | データのみ返却 |
セキュリティベストプラクティス
- トークンを中継しない(バックエンドでデータのみ返却)
-
条件付きアクセスやMFA対応 →
interaction_required
エラーを処理 -
aud不一致を防ぐ → スコープは完全修飾名(
api://<client-id>/<scope>
)で指定
まとめ
- OBOは、ユーザー主体の安全なAPI委任を実現する中核パターン
- Python + MSAL で手早く実装できる
- IDトークン誤用/スコープ設定ミス/権限・同意不足が典型的なハマりどころ
- 設計時は 「誰がどのスコープでどのトークンを取得するか」 を明確に
参考リンク
- Microsoft identity platform と OAuth 2.0 OBO フロー(公式ドキュメント) (Microsoft Learn)
- MSAL for Python ドキュメント (Microsoft Learn)
- MSAL Python OBO サンプル(GitHub) (GitHub)
- Microsoft Graph 権限リファレンス (Microsoft Learn)
Discussion