はじめに
この記事は、Azure Advent Calendar 2021 の 15日目の記事になります。
本題
Azure のサービスで API を公開したい場合、API Management (以降 APIM) を使用すると、API の管理、保護などがサービスとして提供される為、 開発者は、API の開発に集中することが出来ます。
そんな中、昨今のセキュリティ意識の高まりから、よりセキュアな API の提供が求められていますが、高度なセキュリティを実装するとなると、かなりの労力や、実装ミスによるトラブル等 厄介な問題が付きまといます。
ということで今回は、Azure AD が提供する機能を使用して、APIM へのアクセスを保護する方法を説明します。
やってみる
前提条件
今回は、次の前提条件の下で作業するので、事前に準備をお願いします。
- AAD にユーザを作る
- APIM を作る
- APIM で呼び出せるエンドポイントを1つ設定する
使用するツール
- Postman (API 呼出しのチェック用)
Azure AD の設定
まずはじめに、Azure AD に新しくアプリケーションを登録します。
AAD > App registrations > New registration
です。
今回、アプリケーションの種別は、Public client / native (mobile & desktop)
を選択します
Redirect URL は、https://oauth.pstmn.io/v1/callback
を入力します。(Postman が提供する OAuth 2.0 用の Redirect URI です)
アプリケーションが登録出来たら次は、Client Secret を生成します。
AAD のアプリケーション管理画面から、Certificates & secrets > New client secret
を選択します。
Secret が生成されたら、コピーします。(後で確認できなくなるので必ずコピーしてください)
次に、アプリケーションにスコープを割り当てます
アプリケーション管理画面 > Expose an API > Add a scope
を選択します。
スコープを作成すると、用途などを聞かれるので、入力します。
Scope name の下に出ている URI は、コピーしておいてください。
スコープが出来たら、スコープ名のテキストもコピーしておいてください。
ここまで出来たら、残りの必要な情報をポータルから取得します。
まず Client Id です。
アプリケーション管理画面 > Overview > Application (Client) ID
をコピーします。
次に、テナント Id です
アプリケーション管理画面 > Overview > Directory (tenant) ID
をコピーします。
Azure AD の認証エンドポイント
アプリケーション管理画面 > Overview > Endpoints > OAuth 2.0 authorization endpoint (v2)
Azure AD のトークンエンドポイント
アプリケーション管理画面 > Overview > Endpoints > OAuth 2.0 token endpoint (v2)
OpenID Connect の well-known エンドポイント
アプリケーション管理画面 > Overview > Endpoints > OpenID Connect metadata document
Postman でアクセストークンを取得する
アクセストークンを取得する為の情報が揃ったので、アクセストークンを取得します。
Postman の Authorization タブ
にて、下記の設定を行います。
項目 | 設定値 |
---|---|
Type | OAuth 2.0 |
Grant Type | Authorization_Code |
Authorize using browser | チェックする |
Auth URL | 先ほどの認証エンドポイント |
Access Token URL | 先ほどのトークンエンドポイント |
Client ID | クライアント Id |
Client Secret | 生成した Secret |
Scope | openid offline_access 先ほど作ったスコープ |
設定がセット出来たら、Get New Access Token
ボタンを押します。
Azure AD の認証が入るので、作業をしていたディレクトリのアクセス情報でログインします。
ログインに成功すると、次の様な画面になります。
また、コールバック URL が
https://oauth.pstmn.io/v1/callback?code={authorization_code}&session_state={セッションステート}
となっており、code の値をコピーします。
この authorization_code を次のフローでアクセストークンに引き換えます。
※ authorization_code は、10分で切れるので、切れた場合は再取得します
設定しているスコープについて
今回は、openid と offline_access を許可しています。
これらはそれぞれ、
openid : OpenID Connect を使用してサインインする場合に必須なスコープです。このアクセス許可があると、アプリは、ユーザの一意識別子を取得できます。
offline_access : アプリがユーザの代わりに長期間アクセス権を得ることが出来るようになるスコープです。このアクセス許可を指定することで、アクセストークン取得時に、refresh_token を合わせて取得できるようになります。
また、自身が保護したいアプリの要求するスコープを適宜追加することも可能です。(APIM の API を read のみ出来るカスタムスコープなど)
authorization_code をアクセストークンに引き換える
先ほど取得した authorization_code から、 先ほど取得したトークンエンドポイントに対して、次のパラメータで POST リクエストを送ります
項目 | 設定値 |
---|---|
Content-Type | application/x-www-form-urlencoded |
code | authorization_code |
client_id | クライアント Id |
grant_type | authorization_code |
scope | openid offline_access 先ほど作ったスコープ |
redirect_uri | https://oauth.pstmn.io/v1/callback(最初に登録した Redirect URL) |
成功すると、次の様な json が返ってきます。
{ "token_type": "Bearer", "scope": "指定したスコープ", "expires_in": アクセストークンの有効期限(秒), "ext_expires_in": Azure AD のセキュリティトークンサービスが停止していた場合のトークンの最大延長期限, "access_token": "アクセストークン", "refresh_token": "リフレッシュトークン", "id_token": "id トークン" }
これにより、アクセストークン、リフレッシュトークンが取得できました。
これ以降、API 呼出しは、access_token の値を Authorize ヘッダに Bearer トークンとしてセットして使用します。
また、アクセストークンの有効期限は非常に短い為、リフレッシュトークンを使用して、常にアクセストークンを新しくしていく必要があります。
リフレッシュトークンでトークンを更新する
トークンエンドポイントに対して、次のパラメータで POST リクエストを送ります。
項目 | 設定値 |
---|---|
Content-Type | application/x-www-form-urlencoded |
refresh_token | リフレッシュトークン |
client_id | クライアント Id |
grant_type | refresh_token |
scope | openid offline_access 先ほど作ったスコープ |
これにより、新しいアクセストークン、リフレッシュトークンが返されます
リフレッシュトークンの有効期限も、デフォルトで90日なので、トークン更新のタイミングで一緒に交換する等を検討する必要があります。
{ "token_type": "Bearer", "scope": "指定したスコープ", "expires_in": アクセストークンの有効期限(秒), "ext_expires_in": Azure AD のセキュリティトークンサービスが停止していた場合のトークンの最大延長期限, "access_token": "アクセストークン", "refresh_token": "リフレッシュトークン", "id_token": "id トークン" }
APIM を構成する
アクセストークンを取得できましたが、APIM は、デフォルトで Authorization ヘッダを検証しない為、トークンを使わなかったり、適当なトークンを投げられた場合も素通りします。
そこで、Azure AD で取得したアクセストークンを APIM で解析する設定を追加します。
アクセストークンは、jwt なので、APIM で事前に Authorization ヘッダの jwt を検証する仕組みを追加します。
早速 APIM の設定を行いましょう
APIM の管理画面 > APIs > 設定したい API > All APIs(それぞれの API でも可) > Inbound processing
に進みます。
Add Policy を選択すると、その中に Validate JWT
の項目があるので選択します
次の画像の様にフォームを埋めて保存します。
Basic だと、Issuer を埋められないので、Full を選択します。
これで APIM の基本構成が出来ました。
Postman にて、Authorize ヘッダに Bearer トークンとしてアクセストークンをセットすれば、正しくアクセスできるはずです。
まとめ
これにて、Azure AD を使って APIM を保護できるようになりました。
手順はたくさんありますが、一度設定してしまえば、後は API を呼び出すだけなので、セキュリティを強化するという意味で是非やってみましょう。
今回は、かなり説明を割愛した部分があるので、次回以降それぞれの項目を深堀していく記事を書いていく予定です。