Azure Active Directory の SSO 開発 (PHP 編)


New Azure Portal を使用した SAML の設定 (PHP プログラミング含む) については、「Azure AD – How to register your own SAML-based application using new Azure Portal」(英語) を参照してください。

環境 :
PHP 5.5
SimpleSAMLphp 1.11.0

開発者にとっての Microsoft Azure Active Directory

こんにちは。

今日は、SAML-P を使って Azure Active Directtory と連携する PHP アプリケーション (Service Provider, SP) を構築してみます。
(OAuth 2.0 / OpenID Connect による Azure AD との連携サンプルは、「Office 365 API – PHP, Node.js, etc での使用」を参考にしてください。)

このサンプルでは SimpleSAMLphp のライブラリーを使用します。SimpleSAMLphp では、OpenID や AD などさまざまなフェデレーションが可能ですが、今回の Azure AD 連携では SAML-P (SAML 2.0) を使用します。
なお、ライブラリーが素直に Windows Azure Web Sites にはインストールできないので、今回はローカルの IIS を使ってアプリケーション (Service Provider, SP) を構築してみます。

 

Azure Active Directory (Azure AD) へのアプリケーションの登録

まず、Azure AD のテナントを作成して、今回作成予定のアプリケーションを登録しておきましょう。

フェデレーションをおこなう Azure AD テナントをクリックして、[アプリケーション] (Applications) タブを選択して [追加] ボタンを押し、表示される画面で [組織で開発中のアプリケーションを追加] (Add an application my organization is developing) を選択します。以降、追加するアプリケーションの情報を設定するウィザードが表示されるので必要な情報を設定すれば完了です。

ここで、一点注意があります。
今回は、作成するアプリケーションを https://localhost/phpsample/ にホストし、SimpleSAMLphp を https://localhost/simplesaml/ にホストすると仮定しましょう。
この場合、SimpleSAMLphp は、どこから来たリクエストかわかるように、呼び出し元の Web サイトの URL (https://localhost/phpsample) を SAML の RelayState に保持し、IdP (今回の場合、Azure AD) に処理を要求します。つまり、IdP から見ると、要求は SimpleSAMLphp から渡され、SimpleSAMLphp に Reply します。
このため、ウィザードで設定する Application (SP) の URL には、下図の通り、SimpleSAMLphp の URL (https://localhost/simplesaml/) を設定してください。

なお、今回のサンプルでは SSO によるフェデレーションのみを実装しますが、PHP アプリケーションで Graph API を使ってユーザー一覧を取得したり、ディレクトリーの同期機能を実装する場合は、下図のウィザードで [シングル サインオン、ディレクトリ データの読み取り] や [シングル サインオン、ディレクトリ データの読み取りと書き込み] を選択しておいてください。(これについては、いつもと同様です。)

 

開発環境の準備

つぎに、開発環境を準備 (セットアップ) します。

上述の通り、今回、SAML を扱った処理は SimpleSAMLphp を使用し、アプリケーションはローカルの IIS で作成します。

このため、まず、ローカルの環境に PHP のインストールをおこないます。
インストール後、php.ini を確認して、以下の openssl と LDAP の拡張モジュールが入っているか確認してください。(これは SimpleSAMLphp を使う上で必要な一般的な手順ですが、今回のサンプルでは証明書も使わないので、もしかすると これらは不要かもしれません。。。念のため設定しときます。)

. . .
extension=php_openssl.dll
extension=php_ldap.dll
. . .

つぎに、SimpleSAMLphp を ダウンロードして展開します。(Web Platform Installer には入っていないようなので、こちら からダウンロードしてください。)
展開したフォルダーの www サブ フォルダーを IIS のアプリケーションとして公開します。例えば、C:simplesamlphp-1.11.0 に展開した場合、IIS 管理コンソールを開き、C:simplesamlphp-1.11.0www を「simplesaml」という名前 (Alias) のアプリケーションとして追加しておきます。

つぎに、展開したフォルダーにある configconfig.php を開いてください。
この baseurlpath (下記) が上記で指定した仮想ディレクトリー名 (simplesaml) になるように設定します。また、auth.adminpassword が「123」になっているので、このパスワードを適当な値に変更しておいてください。(パスワードを必ず変更する必要があります。)

<?php
$config = array (
  . . .

  'baseurlpath'           => 'simplesaml/',
  'certdir'               => 'cert/',
  'loggingdir'            => 'log/',
  'datadir'               => 'data/',
  . . .

  /**
   * This password must be kept secret, and modified from the default value 123.
   * This password will give access to the installation page of simpleSAMLphp with
   * metadata listing and diagnostics pages.
   * You can also put a hash here; run "bin/pwgen.php" to generate one.
   */
  'auth.adminpassword'    => 'test',
  'admin.protectindexpage'  => false,
  'admin.protectmetadata'    => false,
  . . .

以上で、事前のセットアップは完了です。

 

SP と IdP の設定と Metadata (メタデータ) 交換

つぎに、SimpleSAMLphp に SAML によるフェデレーション (SSO) のための構成をおこないます。
この基本的な設定方法は「SimpleSAMLphp : Service Provider QuickStart」に書かれていますが、いくつか書かれていない手順も必要なので以下に補足しておきます。

まず、SP 側 (Relying Party 側) の設定をおこないます。
上述で、Azure Portal を使って Azure AD のテナントに登録した Application の [構成] (Configuration) タブを表示します。すると、下図の通り CLIENT ID が表示されていますので、この ID をメモ帳などにコピーしておいてください。(これが、SP 側の ID になります。)

SimpleSAMLphp の configauthresources.php を開き、下記の通り設定します。
この際、entityID には「spn:<client id>」を設定します。また、SimpelSAMLphp では、既定では、NameID に urn:oasis:names:tc:SAML:2.0:nameid-format:transient の Format が使用されることを想定していますが (SAML 2.0 の場合)、Windows Azure Active Directory (Azure AD) では異なるフォーマットを使用しますので、下記の通り NameIDPolicy を Null に設定します。(2014/04 追記 : この問題は修正されました。) また、下記では NameIDPolicy を Null に設定しているため、NameID として独自の ID 形式の文字列 (例 : bHHkGa820ZGn27SYqjnoEjsbXo0PwKP_PJN9Q3pBv3A など) が使用されますが、例えば、NameIDPolicy を ‘urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress’ に設定すると、NameID として Mail Address のフォーマット (xxxxx@xxxxx.onmicrosoft.com など) が返されます。
なお、通常は証明書の設定が必要ですが、今回のログインのサンプルではなしでも動きますので、以下では省略しています。(通常は、SP 側の証明書を作成し、下記にその証明書の情報を設定します。おそらく、ログアウトの際などに必要になるはずです。)

$config = array(
  . . .

  'default-sp' => array(
    'saml:SP',

    'entityID' => 'spn:ca8f44d4-2784-43e5-b7da-32f90eb4aaaf',

    'idp' => NULL,

    'discoURL' => NULL,

    'NameIDPolicy' => NULL,
  ),
  . . .

つぎに、フェデレーションに必要な IdP (Azure AD) の情報を SimpleSAMLphp に設定します。
一般に IdP (Azure Active Directroy テナント) から情報を取得して個々に SAML-P SignOn 用の Endpoint や証明書 (Certification) の情報などを設定しますが、これらの情報はすべて Metadata と呼ばれるテキストに記述されており、SimpleSAMLphp では、この Metadata から必要な設定に変換するユーティリティがあります。
このため、今回は、このユーティリティを使ってすぐに設定が可能です。(以下に、この手順を記載します。)

Azure Portal で Azure AD のテナントに登録した Application を表示すると、下図の通り Metadata の URL が表示されていますので、この URL から Metadata のテキスト ファイル (XML) をダウンロードします。(この XML は署名されていますので、改行など勝手に挿入しないよう注意してください。)

つぎに、SimpleSAMLphp にブラウザーを使ってログインします。今回の場合、https://localhost/simplesaml/ にアクセスします。
表示される画面で [連携] (Federation) タブを選択すると [管理者でログイン] (Login as administrator) というリンクが表示されるので、このリンクをクリックして ID / Password に admin/<上記で設定した auth.adminpassword> を入力してログインします。

表示される画面に [XML を simpleSAMLphpメタデータに変換] (XML to simpleSAMLphp metadata converter) というリンクがあるのでクリックします。すると、変換用の画面が表示されるので、この画面に上記でコピーした XML の内容を貼り付けて変換します。下図の通り、PHP の設定コードに変換されます。

上記で取得した設定コード (PHP のコード) をコピーし、SimpleSAMLphp の metadatasaml20-idp-remote.php に貼り付けます。
下記のような内容です。

<?php
$metadata['https://sts.windows.net/6cf16624-15f0-4157-8cde-963a80d854bd/'] = array (
  'entityid' => 'https://sts.windows.net/6cf16624-15f0-4157-8cde-963a80d854bd/',
  'contacts' => 
  array (
  ),
  'metadata-set' => 'saml20-idp-remote',
  'SingleSignOnService' => 
  array (
    0 => 
    array (
      'Binding' => 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect',
      'Location' => 'https://login.microsoftonline.com/6cf16624-15f0-4157-8cde-963a80d854bd/saml2',
    ),
  ),
  'SingleLogoutService' => 
  array (
    0 => 
    array (
      'Binding' => 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect',
      'Location' => 'https://login.microsoftonline.com/6cf16624-15f0-4157-8cde-963a80d854bd/saml2',
    ),
  ),
  'ArtifactResolutionService' => 
  array (
  ),
  'keys' => 
  array (
    0 => 
    array (
      'encryption' => false,
      'signing' => true,
      'type' => 'X509Certificate',
      'X509Certificate' => 'MIIDPjCCAi...',
    ),

    . . . (skip code)

  ),
);

以上で、SimpleSAMLphp への SP 登録と、IdP の Metadata 登録は完了です。

つぎに、Azure Active Directory (Azure AD) のテナントに PHP Application の Metadata を登録します。この Metadata は、SignOut の際に必要になります。(SignIn では、SP が SAMLRequest を使って送信するので不要です。)

上述の SimpleSAMLphp のページの [連携] タブに戻り、SAML 2.0 SP メタデータの [メタデータを表示] をクリックすると下図の画面が表示されます。
ここに記述されている URL が Metadata の URL なのですが、今回の場合、この Metadata を Azure AD 側から参照できないので (Internet から localhost を参照できないので)、この URL で取得される XML をコピーして、どこか見える場所 (Azure Web Sites など) に配置しておきましょう。

Azure Management Portal で、Azure AD テナントの [アプリケーション] (Applications) タブをクリックして、上記で作成した Application (SP) を表示し、[構成] をクリックします。表示される画面で、下図の通り、[フェデレーションメタデータ URL] (Federation Metadata URL) に上記の URL (公開した SP 側の Metadata) を入力して保存します。

2014/08 追記 : この Federation Metadata URL の入力欄はなくなりました。このため、Manifest を編集して、この URL を設定してください。(試してませんが、たぶん、この設定方法で大丈夫かと思います。。。)
画面下の [Manage Manifest] (マニフェストの管理) – [Download Manifest] (マニフェストのダウンロード) で Manifest ファイルをダウンロードし、メモ帳などを使って下記太字の通り編集して、[Manage Manifest] (マニフェストの管理) – [Upload Manifest] (マニフェストのアップロード) で Upload しなおします。

{
  "allowActAsForAllClients": null,
  "appId": "f5b75e7d-cf79-4e0a-87a6-e9b05f364ee4",
  "appMetadata": {
    "version": 0,
    "data": []
  },
  "appRoles": [],
  "availableToOtherTenants": false,
  "displayName": "PhpSampleApp",
  . . .
  "samlMetadataUrl": "https://tsmatsuz-test1.azurewebsites.net/FederationMetadata.xml",
  . . .
}

 

PHP アプリケーションの開発

以上で SAML のフェデレーション設定は完了です。

あとは、PHP アプリケーション (https://localhost/phpsample) を実装して、この構成された SimpleSAMLphp を使用します。
今回は index.php に下記の通り記述してみましょう。

<?php
  require_once("../simplesamlphp-1.11.0/lib/_autoload.php");
  $as = new SimpleSAML_Auth_Simple('default-sp');
  $as->requireAuth();
  $attributes = $as->getAttributes();
?>
<div style="font-weight: bold;">Hello, PHP World</div>
<table border="1">
<?php  foreach ($attributes as $key => $value): ?>
  <tr>
    <td><?=$key;?></td>
    <td><?=$value[0];?></td>
  </tr>
<?php endforeach;?>
</table>

上記の requireAuth() によって、認証済でない場合には認証を促します。(リダイレクトされます。)
Azure Active Directory の認証に成功すると、再度この画面に戻ってきて、上記の通り、受け取った Claim 情報をすべて表示します。

 

動作確認

では、動作を確認してみましょう。

ブラウザーで PHP アプリケーション (https://localhost/phpsample) にアクセスすると、SimpleSAMLphp が下図の通り IdP を選択する画面を表示します。
ここで、上記で SimpleSAMLphp に設定した IdP (今回の場合、https://sts.windows.net/6cf16624-15f0-4157-8cde-963a80d854bd/) を選択します。

すると、Azure AD にリダイレクトされ、下図の Azure AD のログイン画面が表示されます。
ここに、Azure AD のテナントのユーザー ID / パスワードを入力してログインします。

すると、PHP アプリケーション (https://localhost/phpsample/index.php) が表示され、下図の通り Claim 情報が取得できているのがわかります。

この他にも、この SimpleSAMLphp を使用して、[ログイン] ボタンを付けて Azure AD に認証させる処理など、さまざまな応用的なプログラミングが可能です。

 

なお、以下のサンプルコードでは、ここで紹介した手法とは異なり、WIF と SimpleSAMLphp のライブラリーを使って WS-Federation による一連の流れを処理しています。興味ある方は、こちらのサンプルも参考にしてみてください。

Web Single Sign-On with PHP and Windows Azure Active Directory
http://www.windowsazure.com/en-us/documentation/articles/active-directory-php-web-single-sign-on/

時間があれば、今度は Node.js + WS-Federation で試してみたいと思います。(今週は、少し余裕がありまして。。。)

Comments (1)

  1. Adam says:

    Great! Sign-In works fine but i've a problem  with sign-out. I get a bad-request message when trying to sign-out. I can't find a way to get it working. Do you have the same problem with sign-out?

Skip to main content