2015-06-28

onelogin/php-samlを触ってみた

SAMLのSPとなるようなアプリケーションが簡単に作れるかどうか、という技術検証で

onelogin/php-samlを触ったので使い方をメモってみましたー。

今回はSalesforceをIdP、phpのアプリをSP(ローカル環境)として

ソースに付随されているサンプルのアプリを動かしてみます。

1.  インストール

php使いの人にはお馴染みのComposerを使ってインストールします。

Windowsの場合はChocolateyだと何故か上手く行かなかったので、

本家からインストーラでインストールした方が良いかもしれないです。

$ composer init

からの composer.jsonに"onelogin/php-saml": "master-dev" を追加

{
    "name": "hoge/php",
    "authors": [
        {
            "name": "hoge",
            "email": "hoge@example.com"
        }
    ],
    "require": {
        "onelogin/php-saml":"master-dev"
    }
}

からの

$ composer install

でvenderディレクトリ配下にインストールされます。

2. 証明書の設定

SP側の証明書を設定します。

certsフォルダに秘密鍵と証明書を作成します。

$ cd php-saml/certs
$ openssl genrsa 2048 > sp.key
$ openssl req -new -key sp.key > sp.csr
$ openssl x509 -days 3650 -req -signkey sp.key < sp.csr > sp.crt

3. settings.phpの設定

まずdemo1ディレクトリ配下のsettings_example.phpをコピーしてsettings.phpを作成します。

settings.phpの中身は以下の通り。

<?php
    $spBaseUrl = 'https://localhost/php-work/vendor/onelogin/php-saml'; //php-samlへのURLをセット

    $settingsInfo = array (
    	'strict' => true,
    	'debug' => true,
        'sp' => array (
            'entityId' => $spBaseUrl.'/demo1/metadata.php',
            'assertionConsumerService' => array (
                'url' => $spBaseUrl.'/demo1/index.php?acs',
            ),
            'singleLogoutService' => array (
                'url' => $spBaseUrl.'/demo1/index.php?sls',
            ),
            'NameIDFormat' => 'urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified',
        ),
        'idp' => array (
            'entityId' => 'https://hoge.my.salesforce.com',
            'singleSignOnService' => array (
                'url' => 'https://hoge.my.salesforce.com/idp/endpoint/HttpRedirect',
            ),
            'singleLogoutService' => array (
                'url' => '',
            ),
            'x509cert' => '', //現時点では未設定でOK
        ),
        'security' => array (
            'authnRequestsSigned' => true,
        )
    );

$spBaseUrlにはphp-samlへのURLをセット。

spのNameIDFormatはlib\Saml2\Constants.php のNAMEID_****の定数値から選択します。

idpのentityIdにはマイドメインの値を設定します。

singleSignOnServiceにはSP Initiated SSO用のリダイレクト先URL

(SAML Requestのエンドポイント)を入力します。

ちなみにphp-samlではSAML RequestはRedirectのみ対応しており

SAML AssertionはPOSTのみの対応となっています。

 

また、debug=trueでエラー時にエラーの理由等の詳細な情報が出力され

strict=trueではIdP、SPのentityId等が正確に合致していないとエラーになります。

逆に、strict=falseだとentityId不一致でもログイン出来てしまうので

特別なことが無ければstrict=trueにすべきです。

 

authnRequestsSignedはデフォルトfalseになっており

falseだとAuthnRequestでSignatureが発行されません。

4. Salesforceの設定

設定>作成>アプリケーション から接続アプリケーションを以下のように作成します。

connectapp_phpsaml

各項目には3のsettings.phpに設定した値を入力し

開始URLとACS URLにはassertionConsumerServiceの値、エンティティIDにはentityIdの値

名前ID形式にはNameIDFormatの値をそれぞれセットします。

要求署名を確認をチェックして2で作成した証明書をアップロードしてください。

 

保存後にManageボタンを押下し、有効なプロファイルを設定します。

connectapp_phpsaml_manage

また、メタデータのダウンロードから出力されるXMLのX509Certificateのテキスト値

(以下のMIIErD********の部分)をコピーします。

<?xml version="1.0" encoding="UTF-8"?>
<md:EntityDescriptor xmlns:md="urn:oasis:names:tc:SAML:2.0:metadata" xmlns:ds="http://www.w3.org/2000/09/xmldsig#" entityID="https://hoge.my.salesforce.com" validUntil="2025-06-27T16:41:32.609Z">
   <md:IDPSSODescriptor WantAuthnRequestsSigned="false" protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol">
      <md:KeyDescriptor use="signing">
         <ds:KeyInfo>
            <ds:X509Data>
               <ds:X509Certificate>MIIErD********</ds:X509Certificate>
            </ds:X509Data>
         </ds:KeyInfo>
      </md:KeyDescriptor>
      <md:NameIDFormat>urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified</md:NameIDFormat>
      <md:SingleSignOnService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="https://hoge.my.salesforce.com/idp/endpoint/HttpPost"/>
      <md:SingleSignOnService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" Location="https://hoge.my.salesforce.com/idp/endpoint/HttpRedirect"/>
   </md:IDPSSODescriptor>
</md:EntityDescriptor>

またメタデータの値がsettings.phpの値と整合性が取れているかどうかも確認します。

(entityIdとかsingleSignOnServiceとか)

5. settings.phpにIdPの証明書を設定

settings.phpのidpのx509certに4でコピペした証明書のテキストをセットします。

6. デモアプリを動かす

IdP Initiated SSOの場合は

Salesforceの接続アプリケーションのIdp-init のログイン URLにアクセスすればOKです。

connectapp_phpsaml_idpsso

アプリケーションランチャーを使ってIdP Initiated SSOをする場合は

接続アプリ>manageの開始URLのところに"Idp-init のログイン URL"の値を入れて

対象アプリケーションのリンクやランチャーをクリックすればOK。

 

SP Initiated SSOの場合は

demo1/index.phpでLoginのリンクをクリックすると

SalesforceにSAML Requestが飛ぶので、Salesforceで認証後に

demo1/index.php?acsにSAML Assertionが返って、認証が出来ます。

 

署名がミスっている場合はSFDCから以下のようなSAMLResponseが

URLパラメータ経由(リダイレクト)で返却されます。

<?xml version="1.0" encoding="UTF-8"?>
<samlp:Response xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" Destination="https://localhost/php-work/vendor/onelogin/php-saml/demo1/index.php?acs" ID="_5864445b6cb74c19d7b8f837b3eddf671435452699187" InResponseTo="ONELOGIN_9137d2fcb963ddda7f82af1bbfb9225ce9ec659b" IssueInstant="2015-06-28T00:51:39.187Z" Version="2.0">
  <saml:Issuer xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" Format="urn:oasis:names:tc:SAML:2.0:nameid-format:entity">hoge.my.salesforce.com</saml:Issuer>
  <samlp:Status>
    <samlp:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:AuthnFailed"/>
  </samlp:Status>
</samlp:Response>

7. デモアプリの中身

デモアプリの根幹であるindex.phpの中身は簡潔で

SP Initiated SSOをする場合はOneLogin_Saml2_Auth#login

SAML AssertionのverifyはOneLogin_Saml2_Auth#processResponse

SLOしたい場合はOneLogin_Saml2_Auth#processSLO

を叩くだけで、SAML Assertionのverifyが通ったタイミングで

php側のセッションを発行すればOKです。

このエントリーをはてなブックマークに追加