本投稿は古い情報です。最新の Azure App Service の Client-directed Login については「Azure App Service の Authentication 徹底解説」の投稿を参照してください。
Azure Mobile App のあれこれ
- Visual Studio 2013 を使用した Azure Mobile App のアプリケーション開発
- Azure Mobile App で別の Server Script を参照 (Refer) する
- Azure Mobile App の Client-directed Login
こんにちは。
今回は「Build Insider : 第4回 Windows Azure の認証におけるその他サービス ~ Windows Azureモバイル・サービス、多要素認証」の補足の2つ目です。
ここで紹介する方法を使うと、Facebook SDK、Office 365 API など、既存のクライアント側のフェデレーションとの組み合わせが容易になります。
例えば、Gunosy、Flipboard、RSS リーダーの Feedly などでは、ソーシャルのアカウントをそのままアプリの認証として使いながら、共有 (Share)、いいね (Like) の呼び出しや、投稿内容との連携 (分析) など、ソーシャルとの仮想的な SSO (シングル・サインオン) が実装されています。
こうした実装を Azure Mobile App (旧 Azure Mobile Service) でおこなう場合は、「Build Insider : 第4回 Windows Azure の認証におけるその他サービス ~ Windows Azureモバイル・サービス、多要素認証」で触れた Client-directed Login という方式を使用します。
Azure Mobile App を使用した通常の認証 (Service-directed Login) では、サービス側でフェデレーションをおこない、モバイル・アプリ (クライアント側) では Azure Mobile App との間の認証チケットのみを管理します。一方、ここで紹介する Client-directed Login は、モバイル・アプリそのものがフェデレーションをおこない、その結果取得したトークン (Access token) を使って Azure Mobile App と連携します。(この方法により、Facebook SDK など、既存のライブラリーとの組み合わせも容易になります。)
補足 : Azure Mobile App の Client-directed login はプロバイダーによって使える Backend (JavaScript バックエンド、.NET バックエンド) が決まっている場合があるので注意してください。使用できない Backend の場合、”POST of <Provider> token is not supported” の error が発生します。
補足 : Azure Active Directory (Azure AD) で Client-directed login を使用する手順については、「Microsoft Azure : Authenticate your app with Active Directory Authentication Library Single Sign-On」を参照してください。(Azure AD の場合、.NET バックエンドを使用してください。)
事前準備
モバイル全盛の今日では、「Build Insider : 第3回 カスタム・アプリケーションによる認証フローとプログラミング」で紹介した server-to-server (S2S) 方式のように、ネイティブ・アプリが access token を取得するための専用のフロー (OAuth 2.0 フロー) が、ほとんどのプロバイダー (Facebook, Google など) でサポートされています。(むしろ、モバイルの世界では、Web の Cookie ベースの SSO は影が薄くなっている感じです。)
まずは、プロバイダー側 (Facebook, Google, Microsoft Account など) で、こうしたモバイル連携のための準備 (設定) をおこなっておきましょう。
ここで、早速、ポイントがあります。
のちほど Flow については解説しますが、Azure Mobile App を使用した Client-directed Login では、モバイル・アプリ側だけでなく、Azure Mobile App のサービス側もアイデンティティ・プロバイダー (Facebook, Google など) にアクセスします。
このため、アイデンティティ・プロバイダー (Facebook, Google など) には、双方 (モバイル・アプリそのものと Azure Mobile App のサービス) の設定をおこないます。
今回は、アイデンティティ・プロバイダーとして Facebook を使用しましょう。
Facebook にログインして、[アプリを管理] (下図) を選択し、Facebook Developers Dashboard で新しいアプリを追加してください。(この際、作成されたアプリの App ID, App Secret をコピーしておいてください。)
Facebook Developers Dashboard で、作成したアプリに、モバイル・アプリと Azure Mobile App の登録をおこないます。
例えば、iOS の場合には、下図の通り [ネイティブiOSアプリ] (Native iOS App) の箇所にアプリ情報を登録します。(以降は、iOS 用の Facebook SDK を使用してコードを記述し、access token を取得します。)
今回は、サンプルとして、実際のモバイル・アプリではなく、Web アプリケーションからアクセスしてみましょう。
このため、[モバイルWebアプリ] (Mobile Web) に このアドレス (今回は、https://tsmatsuz-test1.azurewebsites.net と仮定) を設定し、[App Domain] にこのドメイン (tsmatsuz-test1.azurewebsites.net) を設定します。
また、上述の通り、 Azure Mobile App の登録も必要なため、[Facebookでログインが可能なウェブサイト] (Website with Facebook Login) にサービスのアドレス (今回は、https://tsmatsuz-zumo01.azure-mobile.net/ と仮定) を設定し、[App Domain] にこのドメイン (tsmatsuz-zumo01.azure-mobile.net) を設定します。
結論として、下図のような設定内容になるでしょう。
つぎに、Azure 側の設定です。
まず、当然ですが、Azure Portal (または、Visual Studio 2013) で、Azure Mobile App のサービスを作成しておきます。
上述の通り、Azure Mobile App のサービス自身も Facebook の Graph API にアクセスするため、Azure Mobile App のサービスを作成したら、下図の通り、Facebook の設定もおこなっておきましょう。(上記でコピーした Facebook アプリの App ID, App Secret を設定します。)
また、今回はサンプルとして JavaScript からアクセスするので、忘れずに、CORS (Cross-Origin Resource Sharing) の設定もおこなっておきましょう。(CORS については、「JSONP などクロス ドメイン問題の回避と諸注意」を参照してください。)
プログラミング – Facebook SDK を使った連携
では、コード (プログラム) を作成します。
前述の通り、実際の Native application (iOS, Android, Windows など) ではネイティブ・アプリ専用の Facebook SDK を使用しますが、今回は、実際のモバイル・アプリではなく Web アプリケーションからアクセスして access token を取得するので、JavaScript 用の Facebook SDK を使用してみましょう。
まず、単純に、Facebook SDK のみを使用したサンプルを作ってみましょう。
例えば、下記は、Facebook にログインをおこない、友達リストを取得してブラウザーに表示する単純なサンプル コードです。(下記の appId には、上記で取得した APP ID を設定してください。)
<!DOCTYPE html><html xmlns="http://www.w3.org/1999/xhtml"><head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> <title></title> <script src="https://ajax.aspnetcdn.com/ajax/jquery/jquery-1.8.0.js"></script> <script src="https://ajax.aspnetcdn.com/ajax/knockout/knockout-3.0.0.js"></script> <script> $(document).ready(function () { // cache on $.ajaxSetup({ cache: true }); // script reference (FB SDK) $.getScript('//connect.facebook.net/ja_JP/all.js', function () { FB.init({ appId: '508116955952644', }); FB.getLoginStatus(function (response) { if (response.authResponse) { // some initializaiton when logged-in ... } }); }); // when login button clicked $('#loginbutton').click(function () { FB.login(function (response) { if (response.authResponse) { // some initializaiton when logged-in ... alert('login succeeded !'); } else { alert('login failure'); } }); }); // knockout initialize (bind ViewModel) var socialViewModel = { friends: ko.observableArray() }; ko.applyBindings(socialViewModel); // when friends button clicked $('#friendsbutton').click(function () { FB.api('/me/taggable_friends', function (response) { $.each(response.data, function (i, f) { socialViewModel.friends.push(f); }); }); }); }); </script></head><body> <button id="loginbutton">Facebook Login !</button> <button id="friendsbutton">Get Friend List !</button> <ul data-bind="foreach: friends"> <li> <div data-bind="text: name" /> </li> </ul></body></html>
実行結果は、以下のようになります。
[Facebook Login !] ボタンを押すと Facebook のログイン画面が表示されるので、ユーザー ID とパスワードを入力してログインします。ログイン後に [Get Friend List !] ボタンを押すと、下図の通り、友達リストが箇条書きで表示されます。
なお、初回のログイン時は、下図のようなコンセント UI が表示されます。この辺りは、他のコンシューマー系のアイデンティティ・フェデレーションと同様です。(この画面で承認をおこなうと、利用者のアカウントにアプリとして登録され、このアプリが Facebook の情報にアクセスできるようになります。もちろん、あとから削除も可能です。)
このコードからは見えませんが、上記コードの FB.api(‘/me/taggable_friends’ …) などの箇所では、内部で、Access token が Facebook の Graph API (https://graph.facebook.com) に渡されています。Graph API では、受け取った Access token の妥当性チェックをおこない、Access token からユーザーの識別をおこなって、答えを返しています。(Facebook の社員ではないので知りませんが、きっとそのはずです。)
補足 : Facebook の Authentication Flow について
Facebook を使用して server-to-server interaction などをおこなう一般的なフローについては「Facebook developers : Manually Build a Login Flow」が参考になります。
ただし、今回のように JavaScript の Faceboook SDK を使用した場合は、「JSONP などクロス ドメイン問題の回避と諸注意」で解説した iframe による XDM (Cross Document Messaging) の方式が使用されています。
また、モバイル用 (iOS など) の Facebook SDK では、インストールされている Facebook App と連携して動作し、もし、Facebook App がインストールされていない場合には Web Flow を使用します。
このように、SDK 内部では、少し複雑な実装 (Flow) がおこなわれています。
プログラミング – Azure Mobile App との連携
では、このコードに、Azure Mobile App との連携処理を追加してみます。
今回は、Facebook にログインし、ログインされたユーザーのみが Azure 上のテーブルに読み書きできるようなサンプルを構築してみましょう。
まず、Azure Portal (もしくは、Visual Studio 2013) を使って、作成した Azure Mobile App のサービスに「TestTbl」という名前をテーブルを作成します。
このテーブルのアクセス権として、下図の通り、「認証されたユーザーのみ」(Authenticated user only) を設定しておきましょう。(このテーブルには、認証されたユーザーしかアクセスできません。)
ソースコードを作成する際は、Azure Portal にログインし、作成した Azure Mobile App の Start Page を確認すると HTML / JavaScript のサンプル コードが取得できますので、参考にしてみてください。
今回は、下記太字の通り処理を追加してみましょう。(下記の「tsmatsuz-zumo01」、「Xrbotp…」は、サービスごとに異なります。)
今回は、Facebook のログインに成功した後で、Facebook SDK から access token の文字列を取得し、この access token を使って Azure Mobile App に Client-directed Login をおこないます。
<!DOCTYPE html><html xmlns="http://www.w3.org/1999/xhtml"><head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> <title></title> <script src="https://ajax.aspnetcdn.com/ajax/jquery/jquery-1.8.0.js"></script> <script src="https://ajax.aspnetcdn.com/ajax/knockout/knockout-3.0.0.js"></script> <script src="https://ajax.aspnetcdn.com/ajax/mobileservices/MobileServices.Web-1.1.0.min.js"></script> <script> var oauthtoken = null; var client = null; var table = null; $(document).ready(function () { // cache on $.ajaxSetup({ cache: true }); // script reference (FB SDK) $.getScript('//connect.facebook.net/ja_JP/all.js', function () { FB.init({ appId: '508116955952644', }); FB.getLoginStatus(function (response) { if (response.authResponse) { // some initializaiton when logged-in ... } }); }); // when login button clicked $('#loginbutton').click(function () { FB.login(function (response) { if (response.authResponse) { // get access token from Facebook SDK oauthtoken = FB.getAuthResponse()['accessToken']; // initialize connection to Zumo client = new WindowsAzure.MobileServiceClient( "https://tsmatsuz-zumo01.azure-mobile.net/", "Xrbotp..." ); // get table object from Zumo table = client.getTable('TestTbl'); // login to Zumo using access token (Client-directed Login) client.login('facebook', { 'access_token': oauthtoken}).then( function () { alert('login succeeded !'); }, function (error) { alert('Zumo login error'); }); } else { alert('login failure'); } }); }); // knockout initialize (bind ViewModel) var socialViewModel = { friends: ko.observableArray() }; ko.applyBindings(socialViewModel); // add data to Zumo table (TestTbl) $('#addbutton').click(function () { table.insert({ text: 'test' }).then( function () { alert('added !'); }, function () { alert('failed !'); }); }); }); </script></head><body> <button id="loginbutton">Facebook Login !</button> <button id="addbutton">Add Data !</button></body></html>
補足 : 今回は説明を省略しますが、「Build Insider : 第4回 Windows Azure の認証におけるその他サービス ~ Windows Azureモバイル・サービス、多要素認証」で解説したように、Azure Mobile App の機能は REST を使っているので、JavaScript、C#、Objective-C 以外のあらゆるコードから使用できます。
Client-directed Login の REST の Request / Response は「MSDN : Client-directed login operation」を参照してください。
Azure Mobile App のサーバー側 (バックエンド) では、Azure Mobile App のログイン時 (上記コードの client.login の際) に、Facebook の Graph API にアクセスして、この渡された access token の検証をおこなってユーザーを識別します。つまり、access token として妥当な値を渡さないとログインに失敗し、Azure Mobile App で認証が必要な処理 (例えば、上記テーブルの読み書きなど) はおこなえません。
このように、Login 処理は自分で実装する必要がありますが、Client-directed Login においても、外部のアイデンティティ・プロバイダーと連携したセキュアなデータ公開や、リソース (データなど) に対するアクセス権 (認可) の容易なカスタマイズなど、「Build Insider : 第4回 Windows Azure の認証におけるその他サービス ~ Windows Azureモバイル・サービス、多要素認証」で解説した Azure Mobile App のメリットを享受できるわけです。
では、作成したアプリケーションを配置して動作を確認してみましょう。
[Facebook Login !] ボタンを押すと Facebook のログイン画面が表示され、内部で、Facebook と Azure Mobile App にログインします。
つぎに、[Add Data !] ボタンを押すと Azure Mobile App のテーブルにデータを登録します。
この際、試しに、Azure Mobile App の Server script を使って、TestTbl の insert トリガーに以下の通り記述してみてください。
すると、下図の通り、Facebook:<facebook userid> 形式のログが出力されます。つまり、Azure Mobile App は、誰がアクセスしたか分かっています。
補足 : Azure Mobile App の Server script では HTTP の処理が可能なため (HTTP Header の設定も可能です)、Facebook の Graph API を呼び出してユーザーの詳細情報も取得できます。(access token は user オブジェクトから取得できます。)
くどいようですが、このアプリケーションでは、上述のサンプルのように、Facebook の友達リストや、投稿の取得など、Facebook と連携した動作を簡単に実装できます。アプリケーション自身が access token を持っているためです。
補足 : Facebook SDK を無視して作るなら (自分で Graph API の REST 呼び出しを記述するなら)、Service-directed Login を使って client.currentUser の mobileServiceAuthenticationToken を取得することで、モバイル・アプリ側で access token を使った処理をおこなえるかもしれません。。。(すみません、やってません)
※ 変更履歴
2015/03/26 Azure Mobile Service から Azure Mobile App に名称変更
Categories: Uncategorized
4 replies»