※ Azure AD v1 endpoint に関する内容です (v2 endpoint の場合は、こちら を参照してください)
開発者にとっての Azure Active Directory (Microsoft Entra ID)
- Azure Active Directory とは (事前準備)
- Web SSO 開発 – .NET 編 (WS-Fed)
- Web SSO 開発 – PHP, Node.js 編 (SAML) ※英語
- SaaS 連携 : Google Apps (SAML)
- SaaS 連携 : kintone (SAML)
- OpenID Connect サポート (OpenID)
- OAuth による Client の開発 (OAuth)
- OAuth による Service の開発 (OAuth)
- Common Consent Framework – Client 側 (OAuth)
- Common Consent Framework – Service 側 (OAuth)
- Application Role の使用 (OAuth)
- Backend Server-Side アプリの開発 (OAuth)
- Federated Credentials (OAuth) ※英語
- Login UI が表示できない場合のフロー (OAuth)
- JavaScript Application の開発 (OAuth)
- Windows 10 との SSO 開発 (Web Account Manager API)
- Active Directory (企業内 Windows 環境) との Federation と同期
- Multi-Factor Authentication
- Graph API
こんにちは。
Daemon, Batch, Windows Service などのバックエンド アプリケーションでは、「Azure AD を使った API 連携の Client 開発 (OAuth)」のフローで Login 画面 (SignIn UI) を表示することはできません。
また、こうしたバッチなどのバックエンド アプリケーションでは、ある特定のユーザーとして処理をおこなうのではなく、組織内のあらゆるオブジェクトを対象に処理するケースが一般的です。(もし、ある特定のユーザーとしてオフラインで接続したいなら、「Azure AD を使った API 連携の Client 開発 (OAuth)」のフローで、いったんユーザーによる SignIn をおこない、以降は refresh token を使用してバックエンドで resource と連携できます。)
今回は、こうした Backend で Azure AD の resource と連携する際のフローと、この技術と関連する Application スコープの Role (Application Role) について紹介します。
後述するように、Azure AD Graph, Exchange Online, OneDrive for Business, SharePoint Online, Skype for Business Online (Preview) が、この方式に対応しています。
App-Only Token の取得
以前も紹介しましたが、「Azure AD を使った API 連携の Client 開発 (OAuth)」の HTTP フローで access token を取得した場合、その token には App Context と User Context が含まれます。平たく書くと、「どのアプリを使って、どのユーザーが使用しているか」といった情報が含まれています。
しかし、今回紹介する Login (SignIn) UI を表示しない HTTP フローで処理することで、App Context のみの access token を取得できます。(この方法で取得した access token は、後述の通り、テナント全体に対する強い権限を有しています。)
以降では、この HTTP フローを 3 パターンご紹介します。
Pattern 1. Symmetric Key を使う Flow (非推奨)
App Only の Access Token を取得する方法の 1 つ目として、Symmetric Key を使用する方法があります。
「Azure Active Directory とは」で解説した Azure AD の PowerShell を使って、下記の通り ServicePrincipal の Symmetric Key を作成できます。
$objId = (New-AzureADApplication -DisplayName "TestApp3").ObjectId$key = New-AzureADApplicationKeyCredential -ObjectId $objId ` -CustomKeyIdentifier "Test" ` -StartDate "9/1/2012" ` -Type "Symmetric" ` -Usage "Sign"[Convert]::ToBase64String($key.Value)
C3w8/oGRSg...
この Symmetric Key から SHA256 アルゴリズムを使用した HMAC の署名を作成して client assertion を生成し、この client assertion を使って App-Only の access token を取得できます。
この処理は、ADAL (Active Directory Authentication Library) v1 を使って以下の通り記述できます。(v2 以降では、この方法は使えません。)
using Microsoft.IdentityModel.Clients.ActiveDirectory;...AuthenticationContext context = new AuthenticationContext( // https://accounts.accesscontrol.windows.net/{tenant realm} "https://accounts.accesscontrol.windows.net/sampledir.onmicrosoft.com");SymmetricKeyCredential credential = new SymmetricKeyCredential( // {AppPrincipalId}@{tenant realm} "0cbc5463-60c5-4907-8025-f5ea0caf4f8b@sampledir.onmicrosoft.com", // {Base64 encoded symmetric Key} Convert.FromBase64String("yjIPua1dae..."));AuthenticationResult assertion = context.AcquireToken( // {graph api AppPrincipalId}/directory.windows.net@{tenant realm} @"00000002-0000-0000-c000-000000000000/graph.windows.net@sampledir.onmicrosoft.com", credential);string authHeader = assertion.CreateAuthorizationHeader();. . .
補足 : 実際に Graph API にアクセスする際には、Azure AD の Windows PowerShell を使って、Service Support Administrator ロールを Service Principal (Application) に付与しておいてください。(下記では、Service Principal の Object Id を 25e7dbb2-74c8-46b1-9a7e-c40b80894770 と仮定します。)
Add-MsolRoleMember -RoleMemberType ServicePrincipal -RoleName “Service Support Administrator” -RoleMemberObjectId 25e7dbb2-74c8-46b1-9a7e-c40b80894770
なお、紹介しておきながらアレですが、現在、この方法は推奨されていないと思われますので、後述の client_secret による方法か、証明書 (Asymmetric Certificate) による方法を使用してください。(ADAL v2 では、この SymmetricKeyCredential を使った処理は提供されなくなりました。)
Pattern 2. Client Id, Client Secret を使う Flow
「Azure AD を使った API 連携の Client 開発 (OAuth)」で説明した client secret を使って、App Only の Access Token を取得できます。
まず、作成する Application は Web App / API として Azure AD に登録してください。(Native Client Application は不可です。)
あとは、下記の HTTP Request を使って、client id, client secret のみから access token (app only の access token) を取得できます。(なお下記の通り、テナント固有のエンドポイントを使用する必要があり、https://login.microsoftonline.com/common は使えないので注意してください。)
Fiddler などを使って、是非試してみてください。
POST https://login.microsoftonline.com/sampledir.onmicrosoft.com/oauth2/tokenContent-Type: application/x-www-form-urlencodedgrant_type=client_credentials&resource=http%3a%2f%2flocalhost%2ftestapp2&client_id=5bbe4005-5e99-4a51-9846-f0dd9a02549a&client_secret=GZOT2mNo%2F9%2B...
Pattern 3. 証明書 (Cert) を使う Flow
Asymmetric の証明書 (Certificate) を使って client assertion を作成し、この client assertion を使って access token を取得できます。
少し手続きが面倒なので、以下に、この手順を詳しく解説します。
まず、前述の 2 と同様に、作成する Backend Application を Web Client Application として Azure AD に登録してください。(Native Client Application は不可です。)
つぎに、X.509 証明書 (private key 含む) を作成します。今回は、Visual Studio ツールに付属している makecert を使用して、下記の通り 自己署名 (self-signed) の証明書を作成してみます。
以降、public key の入った cer ファイル (server.cer) は Azure AD 側に登録し、private key を含む pfx ファイル (server.pfx) はプログラム (Backend Application) が使います。
rem -- なんちゃって CA の作成makecert -r -pe -n "CN=My Root Authority" -ss CA -sr CurrentUser -a sha1 -sky signature -cy authority -sv CA.pvk CA.cerrem -- なんちゃって server 証明書の作成makecert -pe -n "CN=DemoApp" -a sha1 -sky Exchange -eku 1.3.6.1.5.5.7.3.1 -ic CA.cer -iv CA.pvk -sp "Microsoft RSA SChannel Cryptographic Provider" -sy 12 -sv server.pvk server.cerpvk2pfx -pvk server.pvk -spc server.cer -pfx server.pfx -pi {password}
public key の入った server.cer を、以降の手順で Azure AD 上の Application (上記で登録した Application) に設定します。
まず準備として、Windows PowerShell を使って、証明書の Raw と Thumbprint (拇印) の情報を下記の通り取得しておいてください。(下記では、それぞれ raw.txt, thumbprint.txt に出力しています。)
$cer = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2$cer.Import("C:\Demo\test\server.cer")$raw = $cer.GetRawCertData()$rawtxt = [System.Convert]::ToBase64String($raw)echo $rawtxt > raw.txt$hash = $cer.GetCertHash()$thumbprint = [System.Convert]::ToBase64String($hash)echo $thumbprint > thumbprint.txt
取得した証明書の情報を、Manifest (設定の記述されたテキスト ファイル) を使って Azure AD の Application に設定するため、上記で登録した Application の [Manifest] ボタンをクリックしてマニフェストを編集します。
表示されるマニフェストのエディター上で、keyCredentials に下記の通り追記します。
customKeyIdentifier には上記で取得した thumbprint, value には raw (の Base64 エンコード文字列), keyId には GUID を新規作成して設定します。
{ "allowActAsForAllClients": null, "appId": "aecbe375-503b-4acb-8211-97927fa60365", "appMetadata": {"version": 0,"data": [] }, . . . "keyCredentials": [{ "customKeyIdentifier": "MgBsvZT0Gp...", "keyId": "9de40fd2-9559-4b52-b075-04ab17227411", "type": "AsymmetricX509Cert", "usage": "Verify", "value": "MIIDFjCCAg..."} ], . . .}
以上で Azure AD 側の設定は完了です。つぎに、Application (Backend Application) 側の設定をおこないます。
まず、上記で作成した private key (今回は、上記の server.pfx ファイルを使用) を使って「Azure AD : Service 開発 (access token の validation check)」で解説した dot (.) 区切りの署名 (digital signature) 付きの token を作成します。
なお、sign (署名作成) の際の元となる payload には、下記を使用してください。(iss, sub には Application の client id, jti には reply attack 防止のための GUID を新規作成して設定します。x5t については「Azure AD : Service 開発 (access token の validation check)」を参照してください。)
なお、実際のプログラム サンプルは省略しますが、この RS256 による sign (署名作成) の処理は、JavaScript の場合は jsjws、PHP の場合は openssl_sign などが使えるでしょう。(.NET (C# など) については後述します。)
{ "alg": "RS256", "x5t": "MgBsvZT0Gp6OGykFGY2b5JacOXc"}{ "aud": "https://login.microsoftonline.com/sampledir.onmicrosoft.com/oauth2/token", "iss": "aecbe375-503b-4acb-8211-97927fa60365", "sub": "aecbe375-503b-4acb-8211-97927fa60365" "jti": "75655218-1661-4a2d-a121-2e80b0004564", "nbf": 1427863434, "exp": 1427864034,}
最後に、下記の通り、client_assertion にこの token (dot 区切りの token) を設定して HTTP Request をおこないます。(ただし、下記で、client_assertion は URL Encode をおこなってください。また上記の通り、この場合も https://login.microsoftonline.com/common は使用できないので注意してください。)
この Request の結果として、access token が取得できます。
POST https://login.microsoftonline.com/sampledir.onmicrosoft.com/oauth2/token HTTP/1.1Content-Type: application/x-www-form-urlencodedresource=https%3A%2F%2Ftsmatsuz-sv01.azurewebsites.net%2F&client_id=aecbe375-503b-4acb-8211-97927fa60365&client_assertion_type=urn%3Aietf%3Aparams%3Aoauth%3Aclient-assertion-type%3Ajwt-bearer&client_assertion=eyJhbGciOiJSUzI...&grant_type=client_credentials
.NET (C# など) の場合は、sign (署名作成) に HashAlgorithm クラスを使って実装できますが、ご存じの通り、ADAL (Active Directory Authentication Library) が提供されているので、このライブラリーを使うと以下の通り数ステップでプログラミングできます。(ADAL v2 を使用しています。)
注意 : 今後は ADAL ではなく MSAL (Microsoft Authentication Library) を使用してください。(ADAL は今後サポートされません。)
. . .using Microsoft.IdentityModel.Clients.ActiveDirectory;using System.Security.Cryptography.X509Certificates;. . .AuthenticationContext ctx = new AuthenticationContext( "https://login.microsoftonline.com/sampledir.onmicrosoft.com/oauth2/authorize", false);X509Certificate2 cert = new X509Certificate2( @"C:\Demo\test\server.pfx", "P@ssw0rd", // password of private key X509KeyStorageFlags.MachineKeySet);ClientAssertionCertificate ast = new ClientAssertionCertificate( "aecbe375-503b-4acb-8211-97927fa60365", // client id cert);var res = await ctx.AcquireTokenAsync( "https://tsmatsuz-sv01.azurewebsites.net/", // resource id ast);MessageBox.Show(res.AccessToken);. . .
Application Permission の使用
上記の 2 (client_secret による方法), 3 (certificate による方法) では、「Azure AD : Role の使用」で解説した Application Role を扱うことが可能です。
例えば、管理 (Admin) Role、表示 (View) Role といった Application Role を resource 側に定義し、アクセスする Application (今回の場合、backend application) の性質 (種類) にあわせて Application スコープの Role を設定できます。
例えば、呼び出す先の resource application 側の Manifest に下記太字の通り追記して、Service01Manage という Role を定義しておきます。(上記の呼び出す側の Manifest ではないので注意してください !)
なお、allowedMemberTypes が Application になっている点に注目してください。上述の通り、このスタイルのフローでは User Context は含まれないので、Application スコープの Role を定義します。
{ "allowActAsForAllClients": null, "appId": "97cff508-1b4a-40a0-8fc1-7882ffac57b1", "appMetadata": {"version": 0,"data": [] }, "appRoles": [{ "allowedMemberTypes": ["Application" ], "description": "Manage Service01 App (Sample App Role)", "displayName": "Service01Manage", "id": "a4a6c767-53f6-432b-a314-137598e4d119", "isEnabled": true, "value": "service01manage"} ], . . .}
この resource に接続する Client Application 側 (上述の Backend Application) では、Application Permissions (アプリケーションのアクセス許可) として、下図の通り Service01Manage が選択できるようになります。
Client Application にこの Permission (Application Role) を付与して、上述の 2, 3 のいずれかの方法で access token を取得してみてください。
補足 : このアクセス許可は、Azure Portal 以外に、「Azure AD : Application Role の使用」で解説したように Graph API (api-version 1.5 以上) を使って (プログラムから) 付与することも可能です。
取得した access token をデコードすると (デコード方法は「Azure AD : Service 開発 (access token の validation check)」を参照)、下記 roles の通り Role が付与されているのが確認できます。resource 側ではこの内容を見て権限に応じた動きを実装できます。
{ "aud": "https://tsmatsuz-sv01.azurewebsites.net/", "iss": "https://sts.windows.net/7698d4ed-6610-4807-977c-b19ab9e111b5/", "iat": 1427867255, "nbf": 1427867255, "exp": 1427871155, "ver": "1.0", "tid": "7698d4ed-6610-4807-977c-b19ab9e111b5", "roles": ["service01manage" ], "oid": "c4552233-bd36-4b04-8871-738c279bf683", "sub": "c4552233-bd36-4b04-8871-738c279bf683", "idp": "https://sts.windows.net/7698d4ed-6610-4807-977c-b19ab9e111b5/", "appid": "aecbe375-503b-4acb-8211-97927fa60365", "appidacr": "2"}
なお、Microsoft が提供しているサービスでは、現在、Azure Active Directory (Graph API), Exchange Online, OneDrive for Business, SharePoint Online, Skype for Business Online (Preview) が この Application スコープの Role (Application Permissions) に対応しています。(2016/07 変更 : Skype for Business Online も追加しました。)
これらの権限を使用すると、テナント内の全ユーザーのメールの Inbox にアクセスしたり、全ユーザーの予定表にアクセスすることが可能で、特定のユーザーではなく、テナント全体に対する強い権限を有しています。例えば、組織内のすべてのユーザー情報を同期する定期稼働のバッチや (Azure AD Graph)、夜間に全ユーザーの予定表を更新するバッチ (Exchange Online) のような処理を構築できます。
Consent の使用 (Multi-Tenant への対応)
このタイプのアプリケーションにおいても、「Azure Active Directory の Common Consent Framework」で紹介した Consent 画面を使って、簡単にマルチテナント対応にできます。(個別の利用組織ごとに、client secret や証明書のセットアップをおこなう必要はありません。)
このタイプのアプリケーションのコンセントをおこなう際は、必ず 全体管理者 (Administrator) のロールを持つユーザーでログインしてください。全体管理者 (Administrator) のロールでログインすることで、必ず Admin consent が使用され、利用組織全体でこのアプリケーションが使用できます。(Administrator Consent については「Azure Active Directory の Common Consent Framework」を参照してください。)
補足 : 逆に、この Application 用の Permission が設定されている場合、User Consent を使用することはできません。(このため、User Consent の機能とこのタイプの機能を併用したい場合は、それぞれ Application をわける必要があります。)
補足 : 上述の通り、”common” のエンドポイントは使用できないため、マルチテナント対応にする際は注意してください。(ログイン後に Tenant id を取得して Uri を組み立てます。)
※ 変更履歴 :
2017/05/26 画面を新ポータル (https://portal.azure.com) に変更
2017/09/26 OneDrive も app-only token に対応
Categories: Uncategorized
弊社で「Pattern 3. 証明書 (Cert) を使う Flow」にて検証を行った際に、判明した内容を共有いたします。
>keyId には GUID を新規作成して設定します。
keyIdには証明書から取得したGUIDを指定する必要がありました。
>x5t については「Azure AD : Service 開発 (access token の validation check)」を参照してください。)
上記リンク先には記載がありませんでしたが、x5tには証明書から取得した拇印を指定する必要がありました。
取得方法は下記URLに書いてありました。
参考URL:msdn.microsoft.com/…/building-service-apps-in-office-365.aspx
ご参考になれば幸いです。
LikeLike
フィードバックありがとうございます!
こうした情報は、大変参考に(特に、これから構築を予定されている方にとって。。。)なります。
LikeLike
お世話になっております。
すみません、弊社での検証結果に誤りがありましたのでご連絡いたします。
>keyIdには証明書から取得したGUIDを指定する必要がありました。
こちら誤りで、「keyId には GUID を新規作成して設定します。」の記載で間違いありませんでした。
確認不足で申し訳ありません。本文の再修正をよろしくお願いいたします。
LikeLike