OAuth2.0 (Authorization code grantとImplicit grant) で保護したAPIをAzure API Managementで公開する (Azure AD B2C)

このエントリは2019/10/02現在の情報に基づいています。将来の機能追加・変更に伴い、記載内容との乖離が発生する可能性があります。

シナリオ

以前書いたAuthorization Code grantの例を踏まえ、Azure AD B2Cを使った場合にどうなるかを確認する。ユースケースは以前と同じだが、Social Mediaのアカウントで認証できるようにする。

  • アプリがOAuth 2.0の認可コードフローに従い、OAuth 2.0プロバイダーであるAzure ADにOAuth2 tokenを取得しにいく
  • 取得したOAuth 2.0 tokenを使ってAPIを呼び出す
  • APIをホストしているGatewayは、API呼び出し時に送信されたOAuth 2.0 tokenを検証する
  • 検証の結果問題なければ、バックエンドサービスへリクエストを流し、アプリはレスポンスを受け取る

なお、バックエンドサービス自体はOAuth 2.0 tokenを受け付けないものとする。

検証目的のため、今回はAPIを呼び出すアプリ(API Client)としてDeveloper Portalを、APIはAPIMにデフォルトで存在するEcho APIを使う。

まずは…

Azure API Management (以下APIM) インスタンスの作成

APIMインスタンスを作成する。SKUは問わない。インスタンス作成完了までに時間がかかるのはいつも通り。

Azure AD B2Cテナントの作成からFacebookをIdPとして追加するまで

流れを確認するために、チュートリアルを全てやっておく。実際には、Azure AD B2Cテナント作成、ユーザーフロー作成、IDプロバイダー追加だけやれば準備はできる。

チュートリアル:Azure Active Directory B2C テナントの作成
https://docs.microsoft.com/ja-jp/azure/active-directory-b2c/tutorial-create-tenant
Tutorial: Create an Azure Active Directory B2C tenant
https://docs.microsoft.com/en-us/azure/active-directory-b2c/tutorial-create-tenant
チュートリアル:Azure Active Directory B2C にアプリケーションを登録する
https://docs.microsoft.com/ja-jp/azure/active-directory-b2c/tutorial-register-applications
Tutorial: Register an application in Azure Active Directory B2C
https://docs.microsoft.com/en-us/azure/active-directory-b2c/tutorial-register-applications
チュートリアル:Azure Active Directory B2C 内にユーザー フローを作成する
https://docs.microsoft.com/ja-jp/azure/active-directory-b2c/tutorial-create-user-flows
Tutorial: Create user flows in Azure Active Directory B2C
https://docs.microsoft.com/en-us/azure/active-directory-b2c/tutorial-create-user-flows
チュートリアル:Azure Active Directory B2C でアプリケーションに ID プロバイダーを追加する
https://docs.microsoft.com/ja-jp/azure/active-directory-b2c/tutorial-add-identity-providers
Tutorial: Add identity providers to your applications in Azure Active Directory B2C
https://docs.microsoft.com/en-us/azure/active-directory-b2c/tutorial-add-identity-providers

Azure AD B2Cでの設定

API を表すアプリケーションを Azure AD B2Cに登録

インスタンス生成後、APIMでホストするAPIをアプリケーションとしてAzure AD B2Cに登録する(サービスプリンシパルを作成する)。Azure CLIなどでも作成できるが、今回はAzure Portalを使って作成する。

Azure AD B2C > 管理 > アプリケーション で [+追加] をクリック。

名前、Web アプリ/Web API を含め、暗黙的フローを許可して、応答URLにはDeveloper PortalのURL(https://{APIM Instance Name}.portal.azure-api.net)を指定しておく。アプリID URIには識別できるよう一意の値を設定しておく(今回の場合はechoapi)。アプリIDのURIはメモしておく。

この設定をすると、公開済みスコープにuser_impersonationが現れるので、完全なスコープ値をメモしておく。APIを表すアプリケーションに対する設定はこれで終了。

API Clientを表すアプリケーションを Azure AD B2Cに登録

API Client(ここではDeveloper Portal)をOAuth2クライアントとしてアプリケーションを登録する。アプリケーションの登録自体はAPIの場合と同じ。応答URLはのちほどAPIMで認可サーバーを作成した時点で生成されるコールバックURLで置き換えるため、ダミーでよいが、httpsではじめる必要がある。アプリID URIも識別のために一意の値を設定しておく(今回はechoclientを指定)。

クライアントシークレットの作成

クライアントシークレットは、API Clientを表すアプリケーションとして登録したアプリで 全般 > キー をクリック、 [+キーの生成] をクリックして、[保存]をクリックする(Portalのイメージだと非常にわかりづらい)。[保存]を押した後、アプリキー(Client Secret)が表示されるのでメモしておく。後から確認できないので注意。

APIアクセスの設定

API Client(を表すアプリケーション)からAPI(を表すアプリケーション)へのアクセス許可を設定する。API Clientを表すアプリケーションを開き、 API アクセス > API アクセス で[+追加]をクリックし、開いた画面でAPI(を表すアプリケーション)とスコープを選択し、[OK]をクリックする。

エンドポイントの確認

認可URL、トークンエンドポイント、OpenID Connect メタデータ ドキュメントのエンドポイントを確認するには、チュートリアルで作成したサインアップとサインインのユーザーフロー(ポリシー)を開き、概要 > ユーザー フローを実行します をクリックする。すると右から画面が出てくるので、この画面内で、黄色でマークしたURLをそれぞれコピーする。

コピーしたURLは以下のような構成になっている。

https://{tenant}.b2clogin.com/{tenant}.onmicrosoft.com/v2.0/.well-known/openid-configuration?p={User flow name}
https://{tenant}.b2clogin.com/{tenant}.onmicrosoft.com/oauth2/v2.0/authorize?p={User flow name}&client_id=...

前者はOpenID Connect メタデータ ドキュメントのURLで、そのまま利用できる。認可URL、トークンエンドポイントは、後者のURLを少々編集して作成する。編集ルールは下表の通り。

 URL
認可URL
Authorization URL
https://{tenant}.b2clogin.com/{tenant}.onmicrosoft.com/oauth2/v2.0/authorize?p={User flow name}
トークンエンドポイント
Token endpoint
https://{tenant}.b2clogin.com/{tenant}.onmicrosoft.com/oauth2/v2.0/token?p={User flow name}
OpenID Connect メタデータ ドキュメントhttps://{tenant}.b2clogin.com/{tenant}.onmicrosoft.com/v2.0/.well-known/openid-configuration?p={User flow name}

ここまででAzure AD B2Cでの設定はひとまず完了(実はあと1個だけ設定しなければならない)。

APIMでの設定

APIMでOAuth 2.0認可サーバーを構成

これはAzure ADで構成した場合と同じ。設定項目は以下の通り。記載されていない設定項目はデフォルトでよい。指定後、[作成]をクリック。なお、2019/10/02現在Azure AD B2CでClient credentials grantはサポートされていない点に注意。

設定項目
承認許可の種類承認コード(Authorization Code)
暗黙(Implicit)
承認エンドポイントのURL先ほどメモした値
承認要求方法POSTも選択
トークンエンドポイントのURL先ほどメモした値
アクセストークンの送信方法
>既定のスコープ
先ほどメモした完全なスコープ値
(今回の場合、https://{tenant}.onmicrosoft.com/echoapi/user_impersonation)
クライアントの資格情報API Clientを表すアプリケーション作成時に取得したクライアントIDとクライアントシークレット

作成完了すると、OAuth 2.0の認可フローで使われるリダイレクトURIが生成されるので、再度Azure AD B2C > アプリケーション > API Clientを表すアプリケーション を選択し、応答URLで設定していたダミーURLを生成されたリダイレクトURIで置き換え、[保存]をクリックする。

OAuth 2.0認可を使うようにAPIを構成する

今回は既存のEcho APIを使う。簡単のために、APIはサブスクライブしていなくても呼び出せるようにしておく(もちろんAPI Keyを有効化しておいてもかまわない)。

APIMの画面でAPI Management > API で構成したいAPI(今回の例ではEcho API)を選択し、Settingsタブをクリックする。下にスクロールするとSecurityの項目があるので、そこでOAuth 2.0を選択し、OAuth 2.0 Serverを先ほど作成したもの(今回の例ではoauth2-b2c)を選択して [Save] をクリックし、設定を保存する。

validate-jwt ポリシーをAPIに追加する

続いて、validate-jwt ポリシーをAPIのInbound側に設定する。validate-jwt ポリシーの詳細は以下のドキュメントを参照。

JWT を検証する
https://docs.microsoft.com/ja-jp/azure/api-management/api-management-access-restriction-policies#ValidateJWT
Validate JWT
https://docs.microsoft.com/en-us/azure/api-management/api-management-access-restriction-policies#ValidateJWT

Designタブに移動し、All operationsを選択して、Inbound processingで[+Add policy]をクリックし、Validate JWTをクリックする。フォーム形式の画面が現れるので、Fullをクリックして構成していく。

設定内容は以下の通り。なお、記載のないものはデフォルト設定のまま。

設定項目
Header nameAuthorization
Failed validation error message認証が失敗しました。アクセストークンがないか、適切ではありません。
Required claims > Nameaud
Required claims > Valuesアプリケーション ID(APIを表すアプリケーションのクライアントID。アプリIDの URI ではないことに注意)
Open ID URLs先ほどメモしたOpen ID Connect メタデータ ドキュメントのURL

なお、コード表示すると、以下のようなXML形式で確認できる(表示上、XML attributeごとに改行しているが、実際には1行)。

上記設定は以下の要素、属性に反映されている。

XML Element/Attribute
validate-jwt@header-nameAuthorization
validate-jwt@failed-validation-error-message認証が失敗しました。アクセストークンがないか、適切ではありません。
validate-jwt/openid-config@urlメモしたOpenID Connectメタデータ ドキュメントのURL。
validate-jwt/required-claims/claim@nameaud
validate-jwt/required-claims/claim/valueアプリケーション ID(APIを表すアプリケーションのクライアントID。アプリIDの URI ではないことに注意)

以上で完了。

試してみる

まずは、Developer Portalで、何も考えずにAPIを呼び出す。Access tokenをつけていないので、当然401が返ってくる。

では、続いてAccess tokenを取得し、Bearer tokenとして取得したtokenをつけて呼び出してみる。AuthorizationでAuthorization CodeもしくはImplicitを選択すると、認証の画面が出てくる。

今回はFacebookのユーザーで認証したいのでFacebookを選択する。以下の画面が出てくるので、Facebookユーザーとしてログインする。

その後、チュートリアル時に指定した取得したい情報を入力する画面が出てくるので入力(今回の場合、国、表示名、郵便番号)し、Continueをクリック。すると、OAuth 2.0 tokenを取得できる。

ブラウザ・ウィンドウが閉じて、Developer Portalに戻ると、Authorization HeaderにBearer tokenが設定されていることがわかる。

このtokenを使って呼び出すと、問題なく200が返ってくることがわかる。

送信したBearer tokenを見ると、追加で登録した名前、郵便番号、国の情報も含まれていることがわかる。

{
  "typ": "JWT",
  "alg": "RS256",
  "kid": "......"
}.{
  "iss": "https://{tenant}.b2clogin.com/....../v2.0/",
  "exp": 1569998388,
  "nbf": 1569994788,
  "aud": "1da7827c-................-d5c5daa7954a",
  "name": "Logico",
  "idp": "facebook.com",
  "sub": "bd5f9b75-............-e336eb940d96",
  "country": "Japan",
  "postalCode": "108-0075",
  "tfp": "B2C_1_signup-signin",
  "scp": "user_impersonation",
  "azp": "87d9................300a31",
  "ver": "1.0",
  "iat": 1569994788
}.[Signature]

暗黙(Implicit grant)を使った場合のtokenは以下の通り(ほぼ同じ)。

{
  "typ": "JWT",
  "alg": "RS256",
  "kid": "......"
}.{
  "iss": "https://{tenant}.b2clogin.com/....../v2.0/",
  "exp": 1569997919,
  "nbf": 1569994319,
  "aud": "1da7827c-................-d5c5daa7954a",
  "name": "Logico",
  "idp": "facebook.com",
  "sub": "bd5f9b75-............-e336eb940d96",
  "country": "Japan",
  "postalCode": "108-0075",
  "tfp": "B2C_1_signup-signin",
  "scp": "user_impersonation",
  "azp": "87d9................300a31",
  "ver": "1.0",
  "iat": 1569994319
}.[Signature]

Azure AD B2Cを確認すると、Facebookユーザーとしてログインしたユーザーが新たなオブジェクトとして追加されていることがわかる。

プロファイルを確認すると、地域や郵便番号が登録されていることがわかる。

コメントを残す

以下に詳細を記入するか、アイコンをクリックしてログインしてください。

WordPress.com ロゴ

WordPress.com アカウントを使ってコメントしています。 ログアウト /  変更 )

Google フォト

Google アカウントを使ってコメントしています。 ログアウト /  変更 )

Twitter 画像

Twitter アカウントを使ってコメントしています。 ログアウト /  変更 )

Facebook の写真

Facebook アカウントを使ってコメントしています。 ログアウト /  変更 )

%s と連携中