https://trueman-developer.blogspot.com/2019/02/vagrantphp.html
環境
Vagrant
CentOS 7.0
PHP7.2
SAMLについて
雑に説明するとシングルサインオンの共通仕様。
フォーマットはXML。
ログイン専用のサービスを介して様々なサービスで同じ認証情報を使い回す。
アクセスされた時に認証されていない場合idPに認証を丸投げ。
SPは認証後各種情報を受け取る。
ドメインが異なっても認証情報は引き継がれる。
SAMLの用語について
Identity Provider(IdP)
認証するサーバ。
ID,PASSなどを受け取り認証情報を返す。
サービスとして利用するケースが多い。
Service Provider (SP)
認証情報を利用する。
要するに自社システム。
アサーション
認証情報
SPが受け取り利用する。
SimpleSAMLphpについて
SimpleSAMLphpを使用することでSPだけでなくIdPも構築できるようだ。
https://simplesamlphp.org/
開発時Idpが用意されているとは限らないのでIdPも構築して認証するまで実装する。
もしSP側(自社システム)をSAML対応させるだけの場合は
・アクセスがあった時に認証要求用のメッセージ(XML)作成、送信。
・認証メッセージを受け取り、情報を取り出す。
理論上上記だけで良い(いろいろハマりどころがあるらしい)
今回はVagrant上でPHP環境を構築している。
https://trueman-developer.blogspot.com/2019/02/vagrantphp.html
恐らくphp-xmlとphp-zip1を導入しておけばいけるはず。
IdPを実装する場合もSPを実装する場合も以下からSimpleSAMLphpをダウンロードする。
https://simplesamlphp.org/download
SimpleSAMLphpでIdPを実装する
展開した
simplesamlphp-1.16.3のwwwフォルダをsimplesamlphpにリネームしてホストに配置する。
フォルダ構成の例は以下
.vagrant
html
simplesamlphp
Vagrantfile
ApacheのAliasを設定してSimpleSAMLphpの管理画面を表示する
simplesamlphp以下のwwwフォルダを
ApacheのAliasに設定する。
vi /etc/httpd/conf/httpd.conf
/Alias → エンターで検索
Alias /simplesaml /vagrant/simplesamlphp/www
service httpd restart
ホストのVagrantfileがあるディレクトリにhtml, simplesamlphpディレクトリを配置している。
http://192.168.33.10/simplesaml にアクセスされた時にsimplesamlphp/www が実行される
はずなのだが
You don't have permission to access /simplesaml on this server
が発生する。
chown -R apache:apache /vagrant/simplesamlphp
sudo chmod 777 -R /vagrant/simplesamlphp/www/
どちらもうまくいかない。
https://stackoverflow.com/questions/23337446/getting-a-403-forbidden-error-for-simplesaml-after-apache-upgrade
設定方法が変わったらしい
以下はVagrant上(PHP実行環境)での作業。
vi /etc/httpd/conf.d/hosts.conf
hosts.confを以下のように編集する。
<VirtualHost *:80>
ServerName test.test
DocumentRoot /var/www/html
<Directory /var/www/html>
Require all granted
</Directory>
Alias /simplesaml /vagrant/simplesamlphp/www
<Directory /vagrant/simplesamlphp/www/>
Require all granted
</Directory>
</VirtualHost>
ServerName test.test
DocumentRoot /var/www/html
<Directory /var/www/html>
Require all granted
</Directory>
Alias /simplesaml /vagrant/simplesamlphp/www
<Directory /vagrant/simplesamlphp/www/>
Require all granted
</Directory>
</VirtualHost>
ServerName自体はなんでもいい。
service httpd restart
以上でwebsite/simplesamlにアクセスした時に、/vagrant/simplesamlphp/wwwつまりホスト側のsimplesamlphp/wwwを見にいくようになる。
http://192.168.33.10/simplesaml にアクセスした時に
http://192.168.33.10/simplesaml/module.php/core/frontpage_welcome.php にリダイレクトされて
SimpleSAMLphp設定ページ が表示されたらOK(ちなみに上記設定だけだとServerNameが効いていない)
ログインパスワード設定
デフォルトは123だが変更しないとログインできない。
simplesamlphp/config/config.php を編集する。
'auth.adminpassword' => '123',
を任意の値に変更
'enable.saml20-idp' => false,
をtrueに変更。
ちなみに直下の
'enable.shib13-idp' => false,
はシボレスという認証形式になる。今回はやらない。
変更したら「管理者からログイン」から試してみる。
認証を有効化するためにenableファイルを作成
touch simplesamlphp/modules/exampleauth/enable
空ファイルを作成するだけでいいようだ。simplesamlphp/config/authsources.php を書き換え。
コメントアウトされているexample-userpassのコメントを解除する。
これで単純なIDとPASSにより認証ができるようになる。
証明書作成
https://www.geotrust.co.jp/support/ssl/csr/apache_openssl_new.html
simplesamlphp/cert 以下に証明書ファイルを配置する。
cd /simplesamlphp/cert
openssl req -newkey rsa:2048 -new -x509 -days 3652 -nodes -subj "/C=JP/ST=Tokyo/CN=test.test" -out server.crt -keyout server.pem
openssl req -newkey rsa:2048 -new -x509 -days 3652 -nodes -subj "/C=JP/ST=Tokyo/CN=test.test" -out server.crt -keyout server.pem
simplesamlphp/metadata/saml20-idp-hosted.php
を出力した証明書ファイルに設定(server.crt, server.pemにしているなら不要)
ちなみにここでexample-userpassを使用するという設定をしているようだ。
IdPの指定
/simplesamlphp/config/authsources.php'default-sp' => array(
'idp' => 'http://192.168.33.10/simplesaml/saml2/idp/metadata.php',
URLの確認方法はSimpleSAMLphp設定ページ → 連携 → SAML 2.0 IdPメタデータ → メタデータを表示 から取得できる。
IdP連携設定
SPの情報をIdPに設定する。今回SPとIdPが同一なので混同しないように注意。
SAML 2.0 SPメタデータ(default-sp) → メタデータ表示 → 表示された一番下のPHPコードをコピー
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | 'SingleLogoutService' => array ( 0 => array ( 'Binding' => 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect' , ), ), 'AssertionConsumerService' => array ( 0 => array ( 'index' => 0, 'Binding' => 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST' , ), 1 => array ( 'index' => 1, 'Binding' => 'urn:oasis:names:tc:SAML:1.0:profiles:browser-post' , ), 2 => array ( 'index' => 2, 'Binding' => 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact' , ), 3 => array ( 'index' => 3, 'Binding' => 'urn:oasis:names:tc:SAML:1.0:profiles:artifact-01' , 'Location' => 'http://192.168.33.11/simplesaml/module.php/saml/sp/saml1-acs.php/default-sp/artifact' , ), ), ); |
simplesamlphp/metadata/saml20-sp-remote.php に貼り付け。
管理画面の連携画面に表示されたらOK.

以上でIdPとしてサーバが機能するようになる。
用途としてはテストくらいで自分で実装することはあまりないかもしれない。
SimpleSAMLphpでSPを実装する
SPだけでいいなら以下の手順だけでいい。
SP側連携設定
IdPの情報を取得
IdPによって変わる。SimpleSAMLPHPの例。
SimpleSAMLphp設定ページ → 連携
http://192.168.33.10/simplesaml/module.php/core/frontpage_federation.php
SAML 2.0 IdPメタデータ → メタデータ表示 → 表示された一番下のPHPコードをコピー
$metadata['http://192.168.33.11/simplesaml/saml2/idp/metadata.php'] = array (
'metadata-set' => 'saml20-idp-remote',
'entityid' => 'http://192.168.33.11/simplesaml/saml2/idp/metadata.php',
'SingleSignOnService' =>
array (
0 =>
array (
'Binding' => 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect',
'Location' => 'http://192.168.33.11/simplesaml/saml2/idp/SSOService.php',
),
),
'SingleLogoutService' =>
array (
0 =>
array (
'Binding' => 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect',
'Location' => 'http://192.168.33.11/simplesaml/saml2/idp/SingleLogoutService.php',
),
),
'certData' => 'MIIDeTCCAmGgAwIBAgIJAO9A91A+/kZ8Ci1ZmNbdPmOrquI4eTI=',
'NameIDFormat' => 'urn:oasis:names:tc:SAML:2.0:nameid-format:transient',
);
ldpメタデータは今回同じところから取得しているが基本的にldpサーバからxmlなどでメタデータを受け取って登録することになる。
simplesamlphp/metadata/saml20-ldp-remote.php に貼り付け。
既存の$metadataは削除かコメントアウト。
spの情報はxxxx-sp-remote.phpにldpの情報はxxxx-ldp-remote.phpに記述すると覚えておけば良い。
連携画面に追加されていたら成功。

認証チェック
http://192.168.33.10/simplesaml/module.php/core/frontpage_auth.php
SimpleSAMLphp設定ページ → 認証 → 設定されている認証元をテスト から
default-sp
→ simplesamlphp/config/authsources.php のexample-userpassからstudent:studentpass を入力してみる。
認証に成功して以下のような画面が表示されることを確認する。

エラーになる場合,saml20-ldp-remote.phpとsaml20-sp-remote.phpが逆になっていないか、どこかでshib13を誤って設定していないか確認する。
テストサーバを立ち上げてログインする
ごく単純な画面からシングルサインオンを確認する。
html/test.php
1 2 3 4 5 6 7 8 9 10 11 12 13 | <?php require_once ( '../simplesamlphp/lib/_autoload.php' ); $auth = new SimpleSAML_Auth_Simple( 'default-sp' ); $auth ->requireAuth(); $attributes = $auth ->getAttributes(); print_r( $attributes ); echo ( $attributes [ "uid" ][0]); echo ( $attributes [ "eduPersonAffiliation" ][0]); echo ( $attributes [ "eduPersonAffiliation" ][1]); |
require_onceでsimplesamlphpの_autoload.phpを指定する。
$auth->requireAuth(); で未認証の場合は認証画面へリダイレクト。
$attributes の中には以下のような認証情報が入っている。
今回のケースだとsimplesamlphp/config/authsources.php のdefault-sp['example-userpass'] が認証情報になる。
studentとemployeeそれぞれで認証して値が変わることを確認する。
Array ( [uid] => Array ( [0] => test ) [eduPersonAffiliation] => Array ( [0] => member [1] => student ) )
上記のように表示されたら成功
ログアウト処理
html/logout.php
1 2 3 4 5 6 | <?php require_once ( '../simplesamlphp/lib/_autoload.php' ); $auth = new SimpleSAML_Auth_Simple( 'default-sp' ); |
html/logout.html
1 2 3 4 5 6 7 8 9 10 11 12 | <!DOCTYPE html> < html lang = "ja" > < head > < meta charset = "utf-8" /> < meta http-equiv = "X-UA-Compatible" content = "IE=edge" > < title >ログアウト</ title > < meta name = "viewport" content = "width=device-width, initial-scale=1" > </ head > < body > < span >ログアウトしました</ span > </ body > </ html > |
$auth->logout ではログアウト後のURLを指定する必要がある。
使用可能なAPI一覧は以下
https://simplesamlphp.org/docs/1.7/simplesamlphp-sp-api
参考
https://simplesamlphp.org/docs/stable/
https://blog.cybozu.io/entry/4224
https://qiita.com/akihira207/items/cd904a54daa79aeff650
https://auth0.com/blog/jp-how-saml-authentication-works/
http://siblog.seiwatec.co.jp/?p=344
https://qiita.com/haya43/items/c74d2710cd9b57d2cbb4