Azure ADに登録されているAPI用のアクセストークンをJWTで取得するには


Office 365 Rest APIに対してJWT Bearer Tokenフローで利用するアプリケーションを作るにあたって、まずは、ADAL(Active Directory Authentication Library)を利用したチュートリアルAuthenticating to Azure AD in daemon apps with certificatesを試してみました。

このチュートリアルは、Azure ADの認証シナリオのうち、「クライアント資格情報を使用したサービス間の呼び出し」を実装しています。
このシナリオでは、Azure ADは、OAuthの以下の仕様をサポートします。

ADALを利用すると、設定と秘密鍵を指定するだけで、JWT(Json Web Token)を使ってAPIのアクセストークンを取得するリクエストの実装はライブラリにおまかせできますが、ライブラリが内部でやっていることを図にしてみると以下のようになります。
authenticating-to-azure-ad-with-certificates
(クライアント資格情報を使用したサービス間の呼び出しの図と同じです)

以下は、チュートリアルを試してみた内容になります。

クライアント・アプリケーション TodoListDaemonWithCertの追加

Azure AD ディレクトリの[アプリケーション]タブを開き、フッターの[追加]をクリックし、アプリケーションの作成をはじめます。

azure-ad-daemon-apps-with-create-add-an-application-my-organization-is-developing
[組織で開発中のアプリケーションを追加]をクリック

azure-ad-daemon-apps-with-certificate-create-todolistdaemonwithcert-app
名前に”TodoListDaemonWithCert”と入力し、右下の[->]アイコンをクリック

azure-ad-daemon-apps-with-certificate-create-todolistdaemonwithcert-app-2
[サインオンURL]および[アプリケーション ID / URI]は、どちらもhttp://TodoListDaemonWithCertを入力します。
ユーザーにログインを要求しないクライアントアプリなので、値はURI形式であればなんでも良いようです。

右下のチェックアイコン(完了)をクリックするとアプリケーションが追加されます。

APIサービス TodoListServiceの追加

再度、ディレクトリの[アプリケーション]タブで、フッターの[追加]をクリックしてアプリケーションの作成をはじめます。

azure-ad-daemon-apps-with-create-add-an-application-my-organization-is-developing
同じく[組織で開発中のアプリケーションを追加]をクリック

-todolistservice-app-1
名前は”TodoListService”と入力し、右下の[->]アイコンをクリック

azure-ad-daemon-apps-with-create-todolistservice-app-2

[サインオンURL]に”https://localhost:44321″を、[アプリケーション ID / URI]には、”https://<テナント名>/TodoListService”を入力します。
右下のチェックアイコン(完了)をクリックして、アプリケーションの作成を完了します

自己署名証明書を作成

クライアント・アプリケーションTodoListDaemonWithCertを認証するためにAzure ADに登録する証明書を作成します。

makecertコマンドを使って自己証明書を作成します。

makecertの使い方については、Makecert.exe (証明書作成ツール)を参照ください。

makecertコマンドは、Visual Studio 2015をインストールすると追加される開発者コマンドプロンプト for 2015を開くとパスが通っているので、それを使います。

[スタート] > [すべてのプログラム] > [Visual Studio 2015] > [開発者コマンドプロンプト for 2015]で開き以下のコマンドを実行します

> makecert -r -pe -n "CN=TodoListDaemonWithCert" -ss My -len 2048 TodoListDaemonWithCert.cer
Succeeded

-peオプションを指定すると、実行したPCに秘密キーを持った証明書がインストールされます。

インストールされた証明書はcertmgr.mscで確認できます。

azure-ad-daemon-apps-with-certificates-confirm-a-certificate-installed
参考: 証明書を表示または管理する

Azure ADに証明書を追加する

作成した証明書を、Azure ADのクライアント アプリケーションに登録していきます。

証明書から証明書データとフィンガープリントを取り出しBase64エンコードした値と、GUIDのキーIDを生成します。
PowerShellを開き以下のコマンドを実行します

> $cer = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2
> $cer.Import("TodoListDaemonWithCert.cer")
> $bin = $cer.GetRawCertData()
> $base64Value = [System.Convert]::ToBase64String($bin)
> $bin = $cer.GetCertHash()
> $base64Thumbprint = [System.Convert]::ToBase64String($bin)
> $keyid = [System.Guid]::NewGuid().ToString()

実際に実行したPowerShellウィンドウのスクリーンショットです

azure-ad-daemon-apps-with-certificate-extract-a-few-informations-from-certificate
各値はclipコマンドを利用してコピーしています。

Azure ADのアプリケーション[TodoListDaemonWithCert]の[構成]を開き、フッターの[マニフェストの管理] > [マニフェストのダウンロード]をクリックします。

active-directory-dotnet-daemon-certificate-credential-manage-manifest

[マニフェストのダウンロード]をクリックすると、マニフェストファイル<クライアントID>.jsonがダウンロードされます。

active-directory-dotnet-daemon-certificate-credential-download-manifest

マニフェストのkeyCredentialsに、PowerShellで証明書からとりだした値をセットします。

  "keyCredentials": [
      {
          "customKeyIdentifier": "<$base64Thumbprintの値>",
          "keyId": "<$keyidの値>",
          "type": "AsymmetricX509Cert",
          "usage": "Verify",
          "value":  "<$base64Valueの値>"
      }
  ],

実際に値をセットした場合以下のようになります

  "keyCredentials": [
      {
          "customKeyIdentifier": "esfAIInO5Hg4wIMiEnZ5a2N/CeI=",
          "keyId": "ac28c92a-1001-4384-ad90-2dcb0056e923",
          "type": "AsymmetricX509Cert",
          "usage": "Verify",
          "value": "MIIDBTCCAfGgAwIBAgIQ9/XgQ2766JdP ...省略... 4HcoQvvVkfEZQKtK"
      }
  ],

マニフェストファイルを保存したら、[マニフェストの管理] > [マニフェストのアップロード]からアップロードします。

Azure ADの情報をプロジェクトに設定

クローンまたはzipダウンロードしたソリューションをVisual Studio 2015で開ます。

TodoListDaemonWitCert/App.configを開きappSettingsの各項目を以下のように設定します。

// TodoListDaemonWitCert/App.config
  <appSettings>
    <add key="ida:AADInstance" value="https://login.microsoftonline.com/{0}" />
    <add key="ida:Tenant" value="trial365.onmicrosoft.com" />
    <add key="ida:ClientId" value="80ff11d6-e7f0-4c8c-beff-ff0ca1f8093d" />
    <add key="ida:CertName" value="CN=TodoListDaemonWithCert" />
    <add key="todo:TodoListResourceId" value="https://trial365.onmicrosoft.com/TodoListService" />
    <add key="todo:TodoListBaseAddress" value="https://localhost:44321" />
  </appSettings>
  • ida:AADInstance: https://login.microsoftonline.com/{0}のまま
  • ida:Tenant: ディレクトリのドメイン、Office 365のドメインの場合は、<テナントID>.onmicrosoft.com
  • ida:ClientId: 作成したアプリケーションのクライアントID
  • ida:CertName: 作成した証明書のコモンネーム、makecertコマンドの-nオプションに指定した値
  • todo:TodoListResourceId: Web APIのアプリケーション ID / URI。https://<ディレクトリのドメイン>/TodoListService

TodoListService/Web.confgを開きappSettingsの各項目を以下のように設定します。

//TodoListService/Web.confg
  <appSettings>
    <add key="webpages:Version" value="3.0.0.0" />
    <add key="webpages:Enabled" value="false" />
    <add key="ClientValidationEnabled" value="true" />
    <add key="UnobtrusiveJavaScriptEnabled" value="true" />
    <add key="ida:Tenant" value="trial365.onmicrosoft.com" />
    <add key="ida:Audience" value="https://trial365.onmicrosoft.com/TodoListService" />
  </appSettings>
  • ida:Tenant: ディレクトリのドメイン、Office 365のドメインの場合は、<テナントID>.onmicrosoft.com
  • ida:Audience: Web APIのアプリケーション ID / URI。https://<ディレクトリのドメイン>/TodoListService

IISに証明書を追加

クライアント・アプリケーションからIISに自己証明書でSSL通信するためには、CN=localhostの証明書を信頼された証明書としてIISに登録する必要があります。

管理者でPSを開きます

以下のコマンドで証明書のThumbprintを確認します

> dir Cert:\LocalMachine\My


    Directory: Microsoft.PowerShell.Security\Certificate::LocalMachine\My


Thumbprint                                Subject
----------                                -------
C24798908DA71693C1053F42A462327543B38042  CN=localhost

証明書をRootに追加します

> $cert = (get-item cert:\LocalMachine\My\C24798908DA71693C1053F42A462327543B38042)
> $store = (get-item cert:\Localmachine\Root)
> $store.Open("ReadWrite")
> $store.Add($cert)
> $store.Close()

以下のコマンドでCN=localhostが追加されたことを確認できます

> dir Cert:\LocalMachine\Root

以下は実際にコマンドを実行したスクリーンショットです

azure-ad-daemon-apps-with-certificate-trust-the-iis-express-ssl-certificate

動作確認

以上で、クライアントアプリケーションTodoListDaemonWithCertを実行して、Web API TodoListServiceへのアクセスを確認する準備が整いました。

Visual Studioでソリューションを実行し、APIアプリが正常に動作しているかブラウザで確認しておきます。
azure-ad-todo-list-service
このとき、エラー「Runtime error: Could not load file or assembly ‘System.Web.WebPages.Razor, Version=3.0.0.0」が表示される場合は、プロジェクトに含まれるパッケージのバージョンが古いので更新する必要があります。
パッケージの更新は、Visual Studioの[ツール] > [NuGet パッケージ マネージャー] > [ソリューションの NuGet パッケージの管理]を開くと[更新プログラム]タブで新しいバージョンがあるパッケージを確認、インストールできます。

参考: Runtime error: Could not load file or assembly ‘System.Web.WebPages.Razor, Version=3.0.0.0

クライアントアプリを起動すると、以下のようにTodoの追加と一覧が交互に実行されていることが確認できます。

azure-ad-run-todo-list-daemon-with-cert-app

以上で、チュートリアルの確認は完了です。
Azure ADの認証シナリオ「クライアント資格情報を使用したサービス間の呼び出し」について、利用方法が確認できたことになります。

その他参考

Windows Azure Authentication Libraryを使ってみた ブチザッキ

,