Azure AD v2.0 endpoint の OAuth を使った Client 開発 (Azure AD と MSA への対応)


※ v2 endpoint に関する内容です。(Azure AD (v1) の場合は、こちら を参照してください。)

Azure AD v2.0 endpoint を使った Azure AD & MSA 対応アプリ開発

こんにちは。

Microsoft の組織アカウント (Azure Active Directory, Azure AD) と個人アカウント (Microsoft Account, MSA) の双方に対応した v2.0 endpoint (App Model v2) は、本投稿で紹介しているシナリオを含む一部機能 (一部シナリオ) が GA しました。(「Active Directory Team Blog : For Developers: The first use cases of the converged Microsoft account and Azure Active Directory programming model are now GA」を参照。)

そこで、Azure AD (v1) のとき (こちら 参照) と同様、今回から 何回かにわけて、v2 endpoint のアプリケーション開発におけるいくつかの開発シナリオを紹介し、その留意点や考え方などを解説します。(現時点での制限事項も解説します。いくつかのシナリオはまもなく登場予定なので、順次紹介します。。。)

概要 (今回のシナリオ)

例えば、Facebook と連携して動作するスマホ アプリでは、Facebook で認証をおこなって、認証後は Facebook の友達リストや投稿内容の参照など API とつながった形で動作します。(一般に、Mobile アプリと API は密接な関係にあります。) iOS、Android、Windows などの Native Application から Azure AD や Microsoft Account を使用するシナリオでも、ここで紹介する OAuth 2.0 を使って、認証をおこない、認証結果として他の API (Service) と連携して動作できます。

本投稿では、App Model v2.0 を使って、Microsoft のクラウド ID 基盤である Azure AD (組織アカウント) と Microsoft Account (個人アカウント) の双方に対応させます。

今回のサンプルでは、UI を持つ Client アプリケーション (TestApp01) が、Microsoft の ID 基盤 (Azure AD や Microsoft Account) にログインをおこなって、この基盤で保護された Microsoft Graph という API Service (Microsoft のサービス全体に対する API Service) と連携して動作します。

Application (Client) の追加

Client (上述の TestApp01) と API Service (今回の場合、Microsoft Graph) の双方は、あらかじめ、アイデンティティ基盤 (Azure AD, MSA) に登録 (追加) しておく必要があります。(ただし、今回、API Service は既存の Microsoft Graph を使うので登録不要です。)

追加方法は簡単です。まず、OAuth を使用した認証フローを実装するため、以下の URL にアクセスして、あらかじめ作成する Application を登録します。(Azure AD, Microsoft Account の双方で使えます ! 今回は、Microsoft Account を使用する想定で進めます。)

https://apps.dev.microsoft.com

以降、追加した Application の設定を続けます。

まず、皆さんが追加した Application の設定画面上部にある Application Id (App Id, Client Id) の値は重要ですので (このあと使いますので) おぼえておいてください。(メモなどしておきましょう。)

今回は、Web アプリの形式の Client だと仮定しましょう。(Mobile の Native Application については後述します。) そのため、[Add Platform] をクリックして、[Web] を選択します。(Azure AD v1 の頃は、Web アプリ、Mobile アプリなど Platform ごとに Application を複数登録する必要がありましたが、このように単一の Application で複数 Platform に対応しています。まあ、これが普通なんですが。。。)

また、Login (SignIn) 後に戻される Redirect URL を入力 (複数可能) します。

最後に、[Application Secrets] 欄の [Generate New Password] をクリックして、Client Secret を作成します。この情報もあとで使うのでメモしておきましょう。

HTTP Flow (Web の場合)

登録が完了したら、Authentication をおこなうための OAuth Flow を処理して動きを見ていきます。
まず最初に、Web Browser (Mobile の場合は Browser Component など) を使って以下の URL にアクセスします。(下記で v2.0 が使用されている点に注目してください。)

補足 : ここでは、サンプルを理解しやすくする目的で response_type=code としていますが、現実の開発では response_type=id_token+code として id token も取得し、渡された token が正しいか検証をおこなってください。(この場合、response_mode=query ではなく、response_mode=form_post として、Reponse Body で結果を受け取ります。)
この詳細については「v2.0 endpoint の OAuth Token の検証 (Verify)」に解説しましたので参照してください。(2016/03/08 追記)

https://login.microsoftonline.com/common/oauth2/v2.0/authorize
  ?response_type=code
  &response_mode=query
  &client_id=7822587c-fed4-4dd3-8e68-165334eb7c92
  &scope=https%3a%2f%2fgraph.microsoft.com%2fmail.read
  &redirect_uri=https%3a%2f%2flocalhost%2ftestapp01

OAuth 2 の API 連携のフローにおいて、上記の scope で設定されている「https://graph.microsoft.com/mail.read」は重要です。ここでは、「Microosft Graph の Mail の読み込みが可能な token」を要求しています。処理の内容によっては空白 (スペース) 区切りで複数の scope を設定可能で、例えば、下記は、Outlook (Exchange Online または Outlook.com) に対するメールの読み込みと、予定の読み込みの双方を要求しています。

scope=https%3a%2f%2fgraph.microsoft.com%2fmail.read%20https%3a%2f%2fgraph.microsoft.com%2fcalendars.read

ログイン画面が表示されるので、お持ちの Microsoft の Id (Office 365 など Azure AD の組織アカウント、Microsoft Account の個人アカウントのどちらでも構いません) でログインをおこないます。(今回は Microsoft Account を使用します。)

なお、このアプリを初めて使う際は、ログイン後、下図のような Consent の UI が表示され、この画面に承諾することで、この Client が使用できます。(この承諾は一度おこなってしまえば、2 度と表示されることはありません。) つまり、作ったアプリケーションをマルチテナント (Office 365 の利用者の Directory など) に展開する際にも、利用者は上述のような Application の追加作業は不要であり、この Consent に同意するだけで利用を開始できます

なお、上図の通り、メールの読み込み権限を要求していることがわかりますが、例えば、別の処理で予定表の読み込みが必要になった場合には (つまり、追加で、別の scope を使用した場合には)、この Consent が再度表示されて、今度は予定表の読み込み権限のみを利用者に要求 (確認) します。

補足 : 信頼したアプリを外したい場合 (権限削除したい場合) は、Azure AD, Microsoft Account (MSA) ごとのアプリ管理画面で管理します。
Azure AD の場合 :
http://myapps.microsoft.com/
MSA の場合 :
https://account.live.com/consent/Manage

補足 : これは User Consent と呼ばれます。
Azure AD アカウントの場合、管理者 (Administrator) が承諾することで、組織内のすべてのユーザーに (同意不要で) 使わせることも可能であり、この方法を Administrator Consent (Admin Consent) と呼びます。Admin Consent の利用方法については「How to use Application Permission with v2 endpoint and Microsoft Graph」を参照してください。
Admin Consent されたアプリの権限削除は、Azure Portal (管理者のみ利用可能) からおこないます。

ログインが完了すると、下記の通り、「code」の query string が付与された形で、指定した Redirect URL に戻ってきます。(この Authorization Code の有効期限は 5 分です。) アプリケーションでは、この Authorization Code を取得して次の処理に進みます。

https://localhost/testapp01?code=Me9ba53c4...

つぎに、下記の HTTP POST 要求を投げて、もっとも重要な access token (このあと解説します) と呼ばれる token を要求します。下記の通り、この際、Application のパスワードに相当する Client Secret (上述の Application Secret) を渡すので、今回の例のような Web アプリの場合は、この処理は必ず Server-side など利用者が見えない場所で実施してください。

POST https://login.microsoftonline.com/common/oauth2/v2.0/token
Content-Type: application/x-www-form-urlencoded

grant_type=authorization_code
&code=Me9ba53c4...
&client_id=7822587c-fed4-4dd3-8e68-165334eb7c92
&client_secret=XpTof...
&scope=https%3A%2F%2Fgraph.microsoft.com%2Fmail.read
&redirect_uri=https%3A%2F%2Flocalhost%2Ftestapp01

補足 : 同じ Authorization Code を 2 回以上使用することはできません。

上記の POST 要求の結果 (Response Body) として、下記の通り、Access Token と呼ばれる token が返ってくるので、Application でこの値を取得します。(access token の有効期限は 1 時間です。)

{
  "token_type": "Bearer",
  "expires_in": "3600",
  "scope": "https://graph.microsoft.com/mail.read",
  "access_token": "EwCgAsl6BA..."
}

補足 : 通常、受け取った token の検証 (Claim の取得、改竄の確認、token の目的の確認等々) をおこないますが、現在、個人アカウント (Microsoft Account) の際に返される access token は compact tickets であり、検証できないので注意してください。
token の検証 (verify) 方法については、また別の回でまとめて解説します。

さいごに、上記で取得した access token を使って API を呼び出します。(下記の通り Authorization ヘッダーに受け取った access token を設定します。) 今回は、Microsoft Graph を使って自分の Mailbox にある Mail の一覧を取得します。(今回、Microsoft Account でログインしているので、Outlook.com からメールを取得します。)
下記では、OData を使って、受信日時順に上位 20 件のみを取得しています。

GET https://graph.microsoft.com/v1.0/me/messages?$orderby=receivedDateTime%20desc&$top=20&$select=subject,receivedDateTime,from
Accept: application/json
Authorization: Bearer EwCgAsl6BA...

上記の結果として、Microsoft Graph から以下の Response Body が返ります。(20 件返ってきますが、省略して記載しています。)

{
  "@odata.context": "https://graph.microsoft.com/v1.0/$metadata#users('appdev14%40outlook.com')/messages(subject,receivedDateTime,from)",
  "value": [
    {
      "@odata.etag": "W/\"CQAAABYAAAA/ywOhHYtLTIFtKce5fzrrAACaPeCP\"",
      "id": "AQMkADAwAT...",
      "receivedDateTime": "2016-01-12T20:10:17Z",
      "subject": "Hello World",
      "from": {
        "emailAddress": {
          "name": "Tsuyoshi Matsuzaki",
          "address": "tsuyoshi.matsuzaki@ezweb.ne.jp"
        }
      }
    },
    {
      ...
    },
    {
      ...
    },
    ...

  ]
}

補足 : Outlook REST API に対応した新 Outlook.com は、先日 GA したばかりで、現在、利用者の環境に順次展開中です。(もうしばらくかかります。)
もし、"REST API is not yet supported for this mailbox." (MailboxNotEnabledForRESTAPI) のエラーが返される場合は、まだ展開されていないということですので、もうしばらくお待ちください。(または、開発者用のアカウントを新規に取得してください。)

こんなときには、Access Token の再取得

Access Token には、接続先のサービス (どの API に接続するか) の情報が入っています。つまり、同じ Client から別の API Service (scope) に接続する際には、別の Access Token を取得しなおす必要があります

Access Token を再度取得する際は、わざわざ上記のログイン フローを再度実装する必要はなく、以降の通り実装します。

まず、初回の Request の scope に下記の通り offline_access を追加することで、Response として下記の通り Refresh Token と呼ばれるものを取得できます。(省略していますが、最初の Authorization Code 取得の際も、同様に、scope に offline_access を追加してください。)

POST https://login.microsoftonline.com/common/oauth2/v2.0/token
Content-Type: application/x-www-form-urlencoded

grant_type=authorization_code
&code=Me9ba53c4...
&client_id=7822587c-fed4-4dd3-8e68-165334eb7c92
&client_secret=XpTof...
&scope=https%3A%2F%2Fgraph.microsoft.com%2Fmail.read%20offline_access
&redirect_uri=https%3A%2F%2Flocalhost%2Ftestapp01
{
  "token_type": "Bearer",
  "expires_in": "3600",
  "scope": "https://graph.microsoft.com/mail.read",
  "access_token": "EwCgAsl6BA...",
  "refresh_token": "MCadUMfvHs..."
}

あとは、この Refresh Token を使用して下記の通り Request をおこなうと、別の Access Token の取り直しができます。(scope には、新規に利用する API 用の scope を設定します。) このように、ログイン画面の再表示は不要です。

POST https://login.microsoftonline.com/common/oauth2/v2.0/token HTTP/1.1
Content-Type: application/x-www-form-urlencoded

grant_type=refresh_token
&refresh_token=MCVK%2A%2A...
&client_id=7822587c-fed4-4dd3-8e68-165334eb7c92
&client_secret=XpTofZ9ZimyDCXXRc7qtXhh
&scope=https%3A%2F%2Fgraph.microsoft.com%2Fmail.read%20offline_access
&redirect_uri=https%3A%2F%2Flocalhost%2Ftestapp01

また、Access Token の有効期限は 1 時間です。Access Token が期限切れになった場合にも、上記の通り Refresh Token を使って Access Token を取得しなおします。

現実の開発では、この refresh token による access token の取り直しの処理は必ず必要になると思ってください。

補足 : refresh token は、組織アカウント (Azure AD) の場合、最大 14 日使用可能で、再取得することで、さらに 14 日間使用できます。(最大で 90 日まで延長できます。)
また、個人アカウント (Microsoft Account) の場合は、1 年使用可能です。
ただし、password 変更時など、いくつかのタイミングで refresh token は無効になるので、現実の Application 開発では refresh token が無効になった場合の再取得の処理も実装しておいてください。

Web と Mobile (Confidential Client と Public Client)

上記で Web か Mobile か Platform の種類を選択しましたが、選択した内容に応じてフローや考え方も変わってくるので注意してください。

まず、Mobile Application の場合、一般にサーバー側のホストは不要なので、Redirect Uri も上述のような実際に立てている Web サーバーの URI は使用せず、「urn:ietf:wg:oauth:2.0:oob」という固定の値を使用します。(後述しますが、Mobile Application では Confidential な情報を使わない独自のフローで処理するので、ここに実際の Web のアドレスを設定することは Application を危険にさらすことになります。)

また、例えば、あなたが登録した Application の client id を使って、偽のアプリを作ること (つまり、なりすまし) を仮定しましょう。Application Id (Client Id) や Redirect Uri がわかれば上記のフローを真似できるので、信頼されているあなたの Application の真似をして、利用者から重要な情報の搾取 (例えば、ユーザーが入力するクレジットカード番号の搾取など) が簡単におこなえます。

Web Application の場合は、こうしたことを防ぐ目的で、上記の Client Secret (Application Secret) が使われます。Web アプリケーションの場合、上述の通り、Client Secret を Server-side で扱って処理するので、この Secret はあなたの構築したアプリケーションしか知り得ません。そして、この Client Secret がなければ、最終的な認証結果である access token の取得に失敗します。URL リンクなどを利用して簡単になりすませる Web アプリケーションの場合は、このようにして、なりすましから Client を保護しています。

補足 : Client Secret (Application の Password) の代わりに、証明書 (Certificate) を使って保護することも可能です。証明書を使う際は、上記手順で [Generate New Password] をクリックせずに、[Generate New Key Pair] のほうをクリックして証明書 (private key を含む pfx ファイル) をダウンロードし、この証明書を使ってデジタル署名の添付された JWT を作成して、OAuth の Request Body (POST の Body) に設定します。Azure AD もしくは MSA 側では、public key を使ってこの署名の妥当性を検証します。(この手順やコードの詳細は省略します。この JWT については「v2.0 endpoint の OAuth Token の検証 (Verify)」を参照してください。)

一方、Mobile Application の場合、Application は利用者のデバイス上に配置されるので、重要な Secret 情報などをアプリに埋め込まないよう注意してください。Mobile Application の場合は、上記のフローと異なり、Client Secret を使わない下記のフローで処理します。(client secret がないだけで、基本的なフローは同じです。)

https://login.microsoftonline.com/common/oauth2/v2.0/authorize
  ?response_type=code
  &response_mode=query
  &client_id=7822587c-fed4-4dd3-8e68-165334eb7c92
  &scope=https%3a%2f%2fgraph.microsoft.com%2fmail.read%20offline_access
  &redirect_uri=urn%3aietf%3awg%3aoauth%3a2.0%3aoob
urn:ietf:wg:oauth:2.0:oob?code=M70aabedc...
POST https://login.microsoftonline.com/common/oauth2/v2.0/token
Content-Type: application/x-www-form-urlencoded

grant_type=authorization_code
&code=M70aabedc...
&client_id=7822587c-fed4-4dd3-8e68-165334eb7c92
&scope=https%3A%2F%2Fgraph.microsoft.com%2Fmail.read%20offline_access
&redirect_uri=urn%3Aietf%3Awg%3Aoauth%3A2.0%3Aoob
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8

{
  "token_type": "Bearer",
  "expires_in": "3600",
  "scope": "https://graph.microsoft.com/mail.read",
  "access_token": "EwCgAsl6BA...",
  "refresh_token": "MCT8l7kY72..."
}

通常、API と連携したスマホ アプリでは、起動するたびにログインをおこなうのではなく、受け取った refresh token を使って access token を取得し続けます (上述の refresh token を使った access token の取り直し方法を参照)。
Mobile Application では、むしろ、refresh token を使わずに access token を取得しようとすると、毎回、上記の Consent UI が表示されるようになっています。(一方、Web の場合は、上述の通り、Client 利用開始時の最初の 1 回しか表示されませんでした。)

2016/03/08 追記 : Mobile Application も、Consent UI の表示がおこなわれると、以降は Web Application 同様、Consent 情報が記録されるようになりました。この仕様変更については「Azure AD Graph team blog : Azure AD will now record consent for mobile client apps」を参照してください。

このように、Web のフローの Mobile Application への転用などは、Application を危険にさらす結果となるため、(よほど背景を理解している場合などを除き) 基本的に避けてください。目的に応じた Platform とフローを使うようにしましょう。(「動けば良い」というものではありません。)

いくつかの制限

Microsoft の Consumer サービスにおける Outlook.com 以外の呼び出し、on_behalf_of を使った Application 間をまたがった token の受け渡し (v1 endpoint の「OAuth on_behalf_of の利用 (Azure AD)」を参照)、独自の scope を持った web api の登録 (v1 endpoint の「Azure Active Directory の Common Consent Framework (Service 側)」、「Azure AD を使った API 開発」を参照) などは現在未対応です。
現時点の制限事項は「Should I use the v2.0 endpoint?」を参照してください。

なお、Microsoft Account (MSA) にはあくまでも「管理者」や「テナント」の概念はない(今後も入らない)ので、その点は理解して使い分けてください。

 

次回は、v2.0 endpoint を使った JavaScript (SPA) アプリケーション開発 (OAuth Implicit Grant Flow) について、留意事項も含めて解説します。

Comments (0)

Skip to main content