2015年8月14日金曜日

[Azure AD]App Model v2.0を利用して組織内外共用のアプリケーションを開発する

こんにちは、富士榮です。

近年は企業の働き方の変革が進み、業務アプリケーションについても企業組織内だけでなくグループ企業間で共用したり、サプライチェーンの中の関連企業との間で同じアプリケーションを共同利用するようなケースが増えてきています。

そうなってくると、Azure Active Directory(Azure AD)を使って認証するようなアプリケーションについても単一テナントに紐づけるのではなく、他のAzure ADテナントやマイクロソフトアカウントを使ってログインできるようにしたくなるところです。

これまでもマルチテナントアプリケーションとしてAzure AD上にアプリケーションを登録することは可能でしたが、Azureの管理ポータルのようにマイクロソフトアカウントを使ったログインまではできませんでした。今回Public Previewとして登場したApp Model v2.0ではその部分を補完してくれています。尚、中身はOAuth2.0およびOpenID Connectです。

 Active Directory Teamのブログでのアナウンス
  Now in public preview: The Converged Microsoft Account and Azure Active Directory Programming Model
   http://blogs.technet.com/b/ad/archive/2015/08/12/azure-ad-microsoft-account-preview-sign-in-personal-and-work-accounts-using-a-single-stack.aspx

 開発者向けドキュメント
  App Model v2.0 Preview: Auth Protocols - OAuth 2.0 & OpenID Connect
   https://azure.microsoft.com/en-us/documentation/articles/active-directory-v2-protocols/


早速、どのように動くのか確認してみます。

今回は、Azure ADの組織アカウントでも個人のマイクロソフトアカウントでもログインでき、個人のユーザ情報を表示するアプリケーションを作ってみます。尚、アプリケーションはAzure上にホストするWebアプリをVisual Studio OnlineでPHPを使って書いてみます。
ブラウザだけで何でもできるので非常に簡単です。


必要な作業は以下の通りです。
1. Azure App ServiceよりWebアプリを作成する
2. クライアントをアプリケーション登録ポータルから登録する
3. Visual Studio Onlineでアプリケーションを書く


では、準備を進めます。

1. Azure App ServiceよりWebアプリを作成する

この作業の最大の目的はURLを確定させることです。
ここで取得したURLをredirect_uriとしてアプリケーション登録するためです。

中身はなんでもいいので、とりあえずAzureの管理ポータルから簡易作成します。


URLのうちホスト名は[任意の名前].azurewebsites.netとなるので、他と重複しない名前を付けてください。


2. クライアントをアプリケーション登録ポータルから登録する

次にアプリケーションを登録します。
以下よりアプリケーション登録ポータルにログインし、アプリケーションを登録します。尚このポータルへはAzure ADの組織アカウントもしくはマイクロソフトアカウントでログインします。

 https://apps.dev.microsoft.com/

ログインすると右上に[アプリの追加]というボタンがあるので、ここをクリックして登録を開始します。


アプリケーションID(client_id)は自動的に割り当てられるので、まずは任意のアプリケーション名をつけます。



次にプラットフォームの項目より[プラットフォームの追加]をクリックしてアプリケーションのプラットフォームを選択します。今回はWebアプリケーションを選択します。



次にリダイレクトURIの設定を行うので、先に登録したアプリケーションのURLを使います。今回はこの後作成するPHPページをindex.phpとしたので、ここでは先ほどのホスト名+index.phpをリダイレクトURIとして登録しています。



次はアプリケーションシークレットを生成します。これがclient_secretになります。
アプリケーションシークレットの項目の[新しいパスワードを生成]をクリックし、生成されるclient_secretをメモしておきます。




最後にページ下部にある、[保存]をクリックしてアプリケーション登録は完了です。



3. Visual Studio Onlineでアプリケーションを書く

では、実際に動くアプリケーションを書いてみます。
先ほど書いたように今回はVisual Studio Onlineを使ってPHPアプリケーションを書きます。

まずは、先ほど作成したアプリケーションをAzure管理ポータル(今回は新ポータルを使っています)から開き[ツール]-[拡張機能]-[Visual Studio Online]の順に開きます。
※あらかじめ拡張機能としてVisual Studio Onlineを追加しています。


するとエディタが開くので右クリックで新規にindex.phpという名前でファイルを作成し、コードを書いていきます。


実際の使ったコードは以下の通りです(かなり手抜きですが・・・)。単純なcodeフローですね。ちなみにcodeからid_tokenを取得するところでcurlのエラー60番(SSLのVerificationエラー)が出るので、CURLOPT_SSL_VERIFYPEERをfalseにセットしています。マイクロソフト内部の通信のはずなんですが・・・。
<?php

// パラメータ類
$authorization_endpoint = 'https://login.microsoftonline.com/common/oauth2/v2.0/authorize';
$token_endpoint = 'https://login.microsoftonline.com/common/oauth2/v2.0/token';
$client_id = '1ae7xxxxxxxxxxxx2b99';
$client_secret = 'ErxxxxxxxxxxxxxxW0jp';
$redirect_uri = 'https://pharaohphp.azurewebsites.net/index.php';
$response_type = 'code';
$state =  'hogehoge'; // 手抜き
$nonce = 'fogafoga'; // 手抜き

// codeの取得(codeがパラメータについてなければ初回アクセスとしてみなしています。手抜きです)
$req_code = $_GET['code'];
if(!$req_code){
    // 初回アクセスなのでログインプロセス開始
    // GETパラメータ関係
    $query = http_build_query(array(
        'client_id'=>$client_id,
        'response_type'=>$response_type,
        'redirect_uri'=> $redirect_uri,
        'scope'=>'openid',
        'state'=>$state,
        'nonce'=>$nonce
    ));
    // リクエスト
    header('Location: ' . $authorization_endpoint . '?' . $query );
    exit();
}

// POSTデータの作成
$postdata = array(
    'grant_type'=>'authorization_code',
    'client_id'=>$client_id,
    'code'=>$req_code,
    'client_secret'=>$client_secret,
    'redirect_uri'=>$redirect_uri
);

// TokenエンドポイントへPOST
$ch = curl_init($token_endpoint);
curl_setopt( $ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt( $ch, CURLOPT_POSTFIELDS, http_build_query($postdata));
curl_setopt( $ch, CURLOPT_RETURNTRANSFER, true );
$response = json_decode(curl_exec($ch));
curl_close($ch);

// id_tokenの取り出しとdecode
$id_token = explode('.', $response->id_token);
$payload = base64_decode(str_pad(strtr($id_token[1], '-_', '+/'), strlen($id_token[1]) % 4, '=', STR_PAD_RIGHT));
$payload_json = json_decode($payload, true);

// 整形と表示
print<<<EOF
    <html>
    <head>
    <meta http-equiv='Content-Type' content='text/html; charset=utf-8' />
    <title>Obtained claims</title>
    </head>
    <body>
    <table border=1>
    <tr><th>Claim</th><th>Value</th></tr>
EOF;
    foreach($payload_json as $key => $value){
        print('<tr><td>'.$key.'</td><td>'.$value.'</td></tr>');
    }
print<<<EOF
    </table>
    </body>
    </html>
EOF;

?>



書いたコード自動的に保存されるので、これで準備はこれで終了です。


◆テストしてみる

いよいよ動かしてみます。
Azure ADの組織アカウントとマイクロソフトアカウントの両方でログインできて、ユーザ情報が取得できていればOKです。


まずはマイクロソフトアカウントでログインしてみます。

アプリケーションのURLを開くと、ログイン画面が出てくるのでログインアカウントの欄にマイクロソフトアカウント(メールアドレス)を入力します。


すると自動的にマイクロソフトアカウントのログインページに遷移が始まります。


ここでパスワードを入力してサインインします。



すると初回アクセスだとアプリケーションによるアクセス許可の同意画面が出てくるのでアクセスを許可します。



上手く動けばアプリケーションに遷移し、id_tokenに含まれるclaim(属性情報)が一覧で表示されます。




次はAzure ADの組織アカウントを使って同じことをしてみます。

先ほどと同じくアプリケーションを開き、今度はAzure AD上のアカウントを入力すると、Azure ADのログイン画面へ遷移しますので、パスワードを入れてサインインします。



すると同じく同意画面が出てきますのでアクセスを許可します。



同じく上手く動けばアプリケーションに遷移し、claim一覧が表示されます。マイクロソフトアカウントとAzure AD組織アカウントでは取得できる情報が若干異なるようです。




いかがでしょうか?
まだPreviewということでscopeが制限されていたりしますが、とりあえずログインまでは問題なく動くようですので、今後、外部アカウントと共同で業務を行う場合などはこのようなモデルでアプリケーションを開発するのも一つの選択肢となるかも知れません。

0 件のコメント: