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の設定
設定>作成>アプリケーション から接続アプリケーションを以下のように作成します。各項目には3のsettings.phpに設定した値を入力し
開始URLとACS URLにはassertionConsumerServiceの値、エンティティIDにはentityIdの値
名前ID形式にはNameIDFormatの値をそれぞれセットします。
要求署名を確認をチェックして2で作成した証明書をアップロードしてください。
保存後に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です。
アプリケーションランチャーを使って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です。


