Uncategorized

Azure AD (Entra ID) のデバイス ログイン – Login UI が出せない Client のためのフロー

開発者にとっての Azure Active Directory (Microsoft Entra ID)

こんにちは。

以下、Azure AD v1 endpoint の話ですが、週末の Azure AD セミナー (in 札幌) で参加者の方からご質問をいただきましたので記載しておきます。(割と最近サポートされたフローですので、ご存じない方も多いかもしれないので。)

プリンター、デジタルカメラ、ロボットなどのデバイスや、Linux 上のコンソール アプリなど、利用する Client Application の環境によってログイン画面 (SignIn UI) を表示できない場合があります。このような場合は、「Azure AD : Backend Server-Side アプリの開発」で紹介した方法を組み合わせるか、本投稿で紹介する Device Login (Device Profile Flow) を使います。

補足 : なお、「Azure AD を使った API (Service) 連携の Client 開発 (OAuth 2.0 紹介)」で解説した grant_type=password の方式でもログイン画面を抑制できますが、解説した通りこの方法はお勧めしません。

仮に、このニーズに「Azure AD : Backend Server-Side アプリの開発」の方法で対処すると、ユーザーを特定するために、ログイン画面に代わる何某かの仕組み (カードによる認証、音声認証、など) を独自に実装する必要があります。また、private key (証明書) をデバイス側 (Client) に配るわけにはいかないので、デバイスと連携する専用のサービスを立てる必要もあるでしょう。つまり、さまざまなカスタマイズや作り込みができますが (自由度が高いですが)、その一方で、こうした用途向けのやや大袈裟な実装が必要になります。解説したように、「Azure AD : Backend Server-Side アプリの開発」は、本来、バックエンドでの情報同期など、Server-to-server での利用を想定しているためです。
一方、今回紹介するフロー (Device Login) を使うと、後述の通り、テキストの伝達さえできれば、こうした余計な実装は不要で、利用者が所有するスマートフォン (Phone) などの他デバイスを代用することで、ただちに User としてログインができます。
どちらが正解というわけではなく、用途 (ニーズ) に応じて適した方法を使ってください。

なお、今回、Azure Active Directory (Azure AD) v1 endpoint を使いますが、今後、このフローは v2 endpoint でも対応予定です。「Azure AD : Backend Server-Side アプリの開発」の方式では「組織単位で有効化する」という概念のため個人アカウント (Microsoft Account) を対象にすることは困難ですが、今回紹介する Device Login (Device Profile Flow) は User 単位の token が使えるため、今後、個人アカウント (Microsoft Account) でも使えるようになれば、Office 開発などにも さらに大きな広がり (可能性) が出てきます。(例えば、プリンターのような入力方法の制限されたデバイス上から個人を特定して、OneDrive のドキュメントにアクセスするなど。) 多くの場面で利用される可能性を秘めた方法ですので、今後の Update に期待してください。

Device Login の動作

実際、Linux などで、Azure CLI (Command Line Interface) など Azure AD によるログインが必要なコンソール アプリを使う際は、ここで述べる Device Login の方式が使われています。
Device Login がどのようなものか、今回はこの Azure CLI を例に、その動きを見てみましょう。

まず、コンソール上から Azure CLI へログインしてみてください。(Azure CLI がインストールされた環境から、az login コマンドを実行します。Windows 環境の方は、コマンドに --use-device-code オプションを指定してください。)
下図の通り https://microsoft.com/devicelogin (https://aka.ms/devicelogin) での認証を要求するメッセージが表示されます。

上記メッセージに従って、ブラウザーを起動して https://microsoft.com/devicelogin を表示し、表示される画面 (下図) に、上記で与えられたコード (今回の場合、B4Y7GS4SU) を入力します。
手持ちのスマートフォン、タブレットなど、ブラウザーが使えるデバイスなら何でも OK です。

コードの入力が完了すると、ブラウザーに、いつものログイン画面 (SignIn UI) が表示されるので、ここに ID、パスワードを入力してログインします。(必要に応じ、AD FS フェデレーション、二要素認証などが入っても構いません。)
ログインが完了したら、もうブラウザーは不要です。(閉じてしまって構いません。)

上記のログインが完了すると、コンソール上の Azure CLI にも通知され、ログインが完了します。

HTTP Flow

補足 : 以降のサンプルでは Outlook REST API (以降の https://outlook.office.com または https://outlook.office365.com) を使用しますが、Outlook REST API は 2022/11/30 に終了予定です。今後は Microsoft Graph (統一エンドポイント) を使用してください。

このフローを使った基本的な Application 開発の流れは「Azure AD を使った API (Service) 連携の Client 開発 (OAuth 2.0 紹介)」と同じで、Application を Azure AD に登録し、そこで得られる client id, redirect uri などを使って HTTP Flow の処理をプログラミングします。以下、この HTTP Flow を紹介します。
なお、このフローを使用するには、あらかじめ Web Application Client ではなく、Native Application Client として Azure AD に登録してください。

まず、Application は、今回のログインで必要になる Code (User Code) を取得するため、以下の HTTP Request をおこないます。(下記の client id や resource は、適宜、登録した Application に応じて変更してください。)

GET https://login.microsoftonline.com/common/oauth2/devicecode?resource=https%3A%2F%2Foutlook.office365.com%2F&client_id=17ec406b-265a-4c2e-a10c-a91902c5dfbdAccept: application/json

上記の Request の結果 (HTTP Response) として、Azure AD は下記の通り、User Code、Device Code、および利用者に表示するメッセージの内容を返します。利用者が入力するのは User Code であり、Device Code は利用者に見えませんが、このあとの Application と Azure AD の連携において内部で使用される識別子です。

HTTP/1.1 200 OKContent-Type: application/json; charset=utf-8{  "user_code": "GXGPCE4CC",  "device_code": "GAAABAAEAiL9Kn2Z27Uu...",  "verification_url": "https://aka.ms/devicelogin",  "expires_in": "900",  "interval": "5",  "message": "To sign in, use a web browser to open the page https://aka.ms/devicelogin. Enter the code GXGPCE4CC to authenticate."}

Console Application などでは、下図のように、この受け取った Message を利用者に表示すると良いでしょう。もちろん、Device の性質にあわせて、User Code を音声で知らせたり、別のデバイスに送信するなど、さまざまな実装が考えられます。(テキストが伝達できれば方法は問いません。)
なお、この User Code の入力の受付は、上記結果の通り、900 秒間 (15 分間) 有効です。(900 秒を過ぎると無効になります。)

以降、Application 側では、上記の Device Code を使って下記の Request をおこない、利用者がログインしたかどうか確認できます。

POST https://login.microsoftonline.com/common/oauth2/tokenContent-Type: application/x-www-form-urlencodedAccept: application/jsonresource=https%3A%2F%2Foutlook.office365.com%2F&client_id=17ec406b-265a-4c2e-a10c-a91902c5dfbd&grant_type=device_code&code=GAAABAAEAiL9Kn2Z27Uu...

もし、利用者がまだログインをしていない場合は、下記の通り authorization_pending の Error が返ります。利用者がログインを完了するまで、アプリケーションはこの確認を何度もおこないます。

HTTP/1.1 400 Bad RequestContent-Type: application/json; charset=utf-8{  "error": "authorization_pending",  "error_description": "AADSTS70016: Pending end-user authorization.rnTrace ID: 14613dff-d719-4b49-a937-b623263415a9rnCorrelation ID: f4e1c3a8-15a8-4ae4-8389-19a5a0ce2e06rnTimestamp: 2016-03-12 01:18:44Z",  "error_codes": [70016  ],  "timestamp": "2016-03-12 01:18:44Z",  "trace_id": "14613dff-d719-4b49-a937-b623263415a9",  "correlation_id": "f4e1c3a8-15a8-4ae4-8389-19a5a0ce2e06"}

利用者がログインを完了した場合は、上記の HTTP Request の結果として、下記の通り、access token, refresh token が返ります。
以降は、「Azure AD を使った API (Service) 連携の Client 開発 (OAuth 2.0 紹介)」で解説したように、これらの token を使って、検証や API 呼び出しをおこないます。

HTTP/1.1 200 OKContent-Type: application/json; charset=utf-8{  "token_type": "Bearer",  "expires_in": "3599",  "scope": "Mail.Read",  "expires_on": "1457749187",  "not_before": "1457745287",  "resource": "https://outlook.office365.com/",  "access_token": "eyJ0eXAiOi...",  "refresh_token": "AAABAAAAiL...",  "id_token": "eyJ0eXAiOi..."}

ADAL (Active Directory Authentication Library) の利用

注意 (追記) : 今後は ADAL ではなく MSAL (Microsoft Authentication Library) を使用してください。(ADAL は 2020 年 6 月にサポート終了予定です。)

ADAL (Active Directory Authentication Library) を使用する場合は、現在 Prelease 版として出ている ADAL 3 を使用してください。
下記の通り、AcquireDeviceCodeAsync、AcquireTokenByDeviceCodeAsync のメソッドを使って簡単に実装できます。

using Microsoft.IdentityModel.Clients.ActiveDirectory;...static void Main(string[] args){  var ctx = new AuthenticationContext("https://login.microsoftonline.com/common");  // Get user code, device code, and user message  DeviceCodeResult codeResult = ctx.AcquireDeviceCodeAsync("https://outlook.office365.com/", "17ec406b-265a-4c2e-a10c-a91902c5dfbd").Result;  // Display message to user  Console.WriteLine(codeResult.Message);  // Wait and get token  var result = ctx.AcquireTokenByDeviceCodeAsync(codeResult).Result;  // Display token result  Console.WriteLine("Access Token : {0}", result.AccessToken);  Console.ReadLine();}

 

※ 参考資料

Invoking an API protected by Azure AD from a text-only device (Vittorio Bertocci)
https://azure.microsoft.com/en-us/documentation/samples/active-directory-dotnet-deviceprofile/

Categories: Uncategorized

Tagged as: , ,

2 replies»

  1. Love your articles mate..but do we need a sign in card when working with MS teams…Can we bypass the sign in process to access graoh resources. as I have already signed into MS teams?

    Like

Leave a Reply