OpenID Connect で保護したAPIをAzure API Managementで公開する

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

シナリオ・ユースケース

先日のエントリはOAuth 2.0を使っていたが、これをOpenID Connectに置き換えた場合を検討する。ユースケースは前回のエントリと同様。先日のエントリは以下。

OAuth 2.0 (Authorization code grant) で保護したAPIをAzure API Managementで公開する
https://logico-jp.io/2019/09/30/protecting-apis-with-oauth2-authorization-code-grant-in-azure-api-management/

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

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

OpenID Connectを使ったWebアプリケーションの保護は、以下のドキュメントに記載がある。APIも基本的な設定は同じ。

OpenID Connect と Azure Active Directory を使用する Web アプリケーションへのアクセスの承認 / Authorize access to web applications using OpenID Connect and Azure Active Directory
https://docs.microsoft.com/azure/active-directory/develop/v1-protocols-openid-connect-code

まずは…

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

APIMインスタンスを作成する。SKUは問わない。インスタンス作成完了までに時間がかかるのはお約束。

Azure ADでの設定

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

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

Azure AD > 管理 > アプリの登録 で [新規登録] をクリックし、名前、サポートされているアカウントの種類を指定。リダイレクトURLは不要。

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

アプリケーションを登録後、クライアントシークレットを取得する。管理 > 証明書とシークレット をクリック、 [新しいクライアント シークレットの追加] をクリックして、説明と有効期限を指定する(説明はオプション)。今回は無期限にしておく。画面が戻ると、値の場所にランダムな文字が入っている。これがクライアントシークレットである。この値は後から取得できないので、この時点でメモしておく。

アプリケーション ID の URI の作成

このタイミングで、アプリケーション IDのURIを作成しておく。値自体はapi://{client id}ではあるが、明示的に作成が必要である。作成したアプリケーションの概要で、[アプリケーション ID URI の追加]クリック、もしくは 管理 > APIの公開 をクリックする。

開いた画面で、[アプリケーション ID の URI]の右にある[設定]をクリックして、URIを取得する。OAuth2とは異なり、スコープの作成は不要。

OpenID Connect認可サーバー構成に関係するエンドポイント

続いて、OpenID Connectに関係するエンドポイントを確認するため、登録したアプリケーションの概要で[エンドポイント]をクリックする。

右から出てくる画面でOpenID Connectメタデータ ドキュメントのURLをメモしておく。

このURLは以下のような構造になっている。

 URL
OpenID Connectメタデータ ドキュメントhttps://login.microsoftonline.com/{tenantid}/v2.0/.well-known/openid-configuration

APIを表すアプリケーションに対する設定はこれで終了。

APIMでの設定

APIMでOpenID Connect認可サーバーを構成

OpenID Connect認可サーバーをAPIMに追加する。セキュリティ > OpenID Connect を選択し、 [+追加] をクリックして必要事項を入力する。

設定項目は以下の通り。記載されていない設定項目はデフォルトでよい。指定後、[作成]をクリック。

設定項目
表示名任意
名前任意(表示名に従って自動的に入力)
説明任意
メタデータ エンドポイント URL先ほどメモした値
クライアントの資格情報API Clientを表すアプリケーション作成時に取得したクライアントIDとクライアントシークレット

作成完了すると、承認コードタイプ(Authorization code type、正しくは認可コード)、暗黙付与タイプ(Implicit grant type)のコールバックURLが生成されるので、それらをAzure AD > アプリの登録 > API Clientを表すアプリケーション を選択し、生成されたリダイレクトURIと、Developer PortalのURLと併せて、3個のリダイレクトURIに設定しておく。種類はWebでOK。

OpenID Connect認証を使うようにAPIを構成する

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

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

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

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

JWT を検証する / Validate JWT
https://docs.microsoft.com/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)
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)

以上で完了。

試してみる

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

続いてAccess tokenを取得し、Bearer tokenとして取得したtokenをつけて呼び出してみる。AuthorizationでAuthorization Codeを選択、同意画面で同意した上で、Tokenを取得する。

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

注意

今回、Implicit Grantの構成は実施していないため、Developer PortalでImplicitを選択すると、401が返る。Implicitに対応する仕組みは将来まとめる予定。

コメントを残す

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

WordPress.com ロゴ

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

Facebook の写真

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

%s と連携中