Service Provider(以下「SP」という)としてWebアプリケーションをSAML対応する場合、検証用のIdenity Provider(以下「IdP」という)が欲しくなります。 Microsoft Azure Active DirectoryなどはIdPを無料で使用できますが、開発者全員が使用するには融通が効かないまたはオーバースペックになりかねません。

今回は、開発環境用のIdPを構築して、SPのSAML認証を検証する方法を紹介します。

この記事はFOLIO Advent Calendar 2019の12月24日の記事でもあります。

SAMLとは

SAMLはSecurity Assertion Markup Languageの略です。セキュアなWebドメイン間でユーザーの認証および承認データを交換するためのXMLベースの標準規格1のことです。 SAMLを使用することで、セキュアなコンテンツにアクセスしようとしているユーザーを認証できます。

SAMLには1.1と2.0の2つのバージョンがありますが、今から導入する場合は2.0をサポートしていればよいです。

IdPとして動作するOSS

IdPとして動作するOSSはいくつかあります。その中でもお手軽に使用できると感じたのは以下の4つです。

  • saml-idp
    • Node.jsで記述されているIdP
    • 独自で拡張したIdPサーバを用意したい場合も使用しやすい
    • CLIが用意されており、Node.jsが動作する環境があればすぐに導入が可能
    • 本家がDocker Imageを用意している
  • SimpleSAMLphp
    • PHPで記述されているIdP
    • ドキュメントが豊富
    • メンテナンスが頻繁に行われている
  • lite-idp
    • Goで記述されているIdP
    • ワンバイナリで動作
  • Mujina
    • JavaのSpring Bootフレームワークで記述されているIdP
    • メンテナンスが頻繁に行われている
    • 設定のためのREST APIがある

どれを選択するかは悩みどころですが、特にドキュメントが豊富というのが多くの人が開発に携わった際に効いてくるため、今回はSimpleSAMLphpを選択して話を進めていきます。

SimpleSAMLphpについて

SimpleSAMLphpはUNINETT社が主導しているピュアなPHPで記述されたIdPとSPです。https://simplesamlphp.orgに多くのドキュメントが存在します。

開発用にSimpleSAMLphpを準備する

ローカル開発環境にPHPが動作する場合はよいですが、少々面倒であるため、ここではDockerを使用して用意します。

SimpleSAMLphpは公式でDocker Imageを用意していません。理由は、Dockerfileは人によって好みが分かれてしまい、かつSimpleSAMLphpはSPの役割を有しており、複雑化してしまうため2だそうです。

そのため、Docker Imageを自作する必要があります。 しかし、それも面倒だと思うので3分クッキングの如く、kenchan0130/simplesamlphp - Docker Hubを用意しました。

$ docker run --name=idp \
  -p 8080:8080 \
  -e SIMPLESAMLPHP_SP_ENTITY_ID=http://app.example.com \
  -e SIMPLESAMLPHP_SP_ASSERTION_CONSUMER_SERVICE=http://localhost:90000/simplesaml/module.php/saml/sp/saml2-acs.php/test-sp \
  -d kenchan0130/simplesamlphp

SIMPLESAMLPHP_SP_ENTITY_IDにSPのエンティティID、SIMPLESAMLPHP_SP_ASSERTION_CONSUMER_SERVICEにSPのAssertion Consumer ServiceのURLを指定して起動します。 http://localhost:8080でページが表示されれば完了です。

あとは、SP側のIdPのメタデータURLをhttp://localhost:8080/simplesaml/saml2/idp/metadata.php、エンティティIDをSIMPLESAMLPHP_SP_ENTITY_IDと同じ値を設定することでSimpleSAMLphpをIdPとして使用できます。

ユーザーをカスタマイズする

kenchan0130/simplesamlphp - Docker HubはデフォルトのままだとAssertionの属性がメールアドレスとしてemailが設定されています。各種IdPを模倣したい場合のためにカスタマイズが可能です。

以下のようにユーザーに関するPHPファイルをボリュームマウントすることで設定できます。

$ docker run --name=idp \
  -p 8080:8080 \
  -e SIMPLESAMLPHP_SP_ENTITY_ID=http://app.example.com \
  -e SIMPLESAMLPHP_SP_ASSERTION_CONSUMER_SERVICE=http://localhost/simplesaml/module.php/saml/sp/saml2-acs.php/test-sp \
  -v authsources.php:/var/www/simplesamlphp/config/authsources.php \
  -d kenchan0130/simplesamlphp

例として、Microsoft Azure Active Directoryのエンタープライズアプリケーションのカスタム属性をノンカスタマイズ状態で模倣したとすると、以下のようにauthsources.phpを設定することで実現が可能です。

<?php
$azure_ad_attributes_base = array(
    'http://schemas.microsoft.com/identity/claims/tenantid' => 'ab4f07dc-b661-48a3-a173-d0103d6981b2',
    'http://schemas.microsoft.com/identity/claims/objectidentifier' => '',
    'http://schemas.microsoft.com/identity/claims/displayname' => '',
    'http://schemas.microsoft.com/ws/2008/06/identity/claims/groups' => array(),
    'http://schemas.microsoft.com/identity/claims/identityprovider' => 'https://sts.windows.net/da2a1472-abd3-47c9-95a4-4a0068312122/',
    'http://schemas.microsoft.com/claims/authnmethodsreferences' => array('http://schemas.microsoft.com/ws/2008/06/identity/authenticationmethod/password', 'http://schemas.microsoft.com/claims/multipleauthn'),
    'http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress' => '',
    'http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname' => '',
    'http://schemas.xmlsoap.org/ws/2005/05/identity/claims/surname' => '',
    'http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name' => ''
);

$config = array(
    'admin' => array(
        'core:AdminPassword',
    ),
    'example-userpass' => array(
        'exampleauth:UserPass',
        'user1:password' => array_merge($azure_ad_attributes_base, array(
            'http://schemas.microsoft.com/identity/claims/objectidentifier' => 'f2d75402-e1ae-40fe-8cc9-98ca1ab9cd5e',
            'http://schemas.microsoft.com/identity/claims/displayname' => 'User1 Taro',
            'http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress' => 'user1@example.com',
            'http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname' => 'Taro',
            'http://schemas.xmlsoap.org/ws/2005/05/identity/claims/surname' => 'User1',
            'http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name' => 'user1@example.com'
        )),
        'user2:password' => array_merge($azure_ad_attributes_base, array(
            'http://schemas.microsoft.com/identity/claims/objectidentifier' => 'f2a94916-2fcb-4b68-9eb1-5436309006a3',
            'http://schemas.microsoft.com/identity/claims/displayname' => 'User2 Taro',
            'http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress' => 'user2@example.com',
            'http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname' => 'Taro',
            'http://schemas.xmlsoap.org/ws/2005/05/identity/claims/surname' => 'User2',
            'http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name' => 'user2@example.com'
        )),
    ),
);

まとめ

今回は、SimpleSAMLphpのDocker Imageを使用して、開発環境用のIdPを構築して、SPのSAML認証を検証する方法を紹介しました。 Docker Composeとして設定しておくと、開発時にdocker-compose upするだけで開発環境が整うのでオススメです。