SimpleSAMLphp でHTTP Artifactを用いた認証
○ HTTP Artifact何それ
○ やだ
IdPとSPとの間で認証情報を交換する際、リダイレクトやらなんやらを使うのでブラウザからもIdPからの属性がダダ漏れ。そのため、ブラウザに情報が渡らないように"Artifact"と呼ばれる仮の文字列を使い、SPとIdPはそのArtifactを介して本当の属性情報をやりとりする、という仕組みがSAMLにある。ブラウザに見えるのはArtifactで、属性は隠される。
SPとIdPが直接通信するフェーズ (Artifact Resolve)があるのが素敵。
○ 環境
- いつもと同じ (CentOS 6.3 final)
- IdPとSPは同一マシン内 (ホスト名は違う)
○ memcached のインストールと動作確認
yumでインストール後、念の為動作確認と外部からのアクセスを遮断する。 /etc/sysconfig/memcached で OPTIONS="-l 127.0.0.1" などと設定して service memcached restart。netstat -nlp | grep memcached で11211ポートが正しく開かれているか確認。telnet localhost 11211ののちstatsと入れて何か動いているのを見て、quitで出る。nmap localhost -p 11211 とかやってもいいが nmap 5.51 ではmemcachedであることは認識してくれない。
○ php でmemcachedが動作することを確認
例えばこういったところからてきとーに http://www.happytrap.jp/blogs/2012/03/31/8620/
○ php のSOAP clientを用意
yum install php-soap
他に要る「かも」しれない。一般論としては、frontpage_config.phpにadminでアクセスした際のリストを全部緑にした上で、何かおかしかったらとりあえずSimpleSAMLphpのログとhttpdのログの両方を見て判定するのが良い。ちなみに今回はSSLなのでhttpdのログはそっちを見ること
○ 上記の公式記事の通りに設定し、…… Artifact Binding の方に 'isDefault' => TRUE 入れる
追記: このセクション間違い。SP側で設定しないとProtocolBindingがいつまでたってもHTTP-POST
○ SPからProtocolBindingとしてHTTP-Artifactを送るよう要求する
上記の設定 の後にSPの設定も行う。注意すべき点として、saml20-sp-hostedではなくconfig/authsources.phpに'ProtocolBinding' => 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact'などの設定は書くこと。
○ 注意
追記: この記述も上記の勘違いから派生している可能性アリ。ただし、同じホストで動かしているSimpleSAMLphpのIdPが2つEntityIDを持てない可能性が高いのは事実
上記の設定 の後にSPの設定も行う。注意すべき点として、saml20-sp-hostedではなくconfig/authsources.phpに'ProtocolBinding' => 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact'などの設定は書くこと。
○ 注意
追記: この記述も上記の勘違いから派生している可能性アリ。ただし、同じホストで動かしているSimpleSAMLphpのIdPが2つEntityIDを持てない可能性が高いのは事実
最初、saml20-idp-hostedに2つの設定を書いてEntityIDをそれぞれ
- https://idp.example.com/simplesamlphp/(path)/default
- https://idp.example.com/simplesamlphp/(path)/with_artifact
とし、動作の違いを比較するためほとんど設定同じでsaml20.sendartifactの設定だけ違うものを作ったら、1つめしか使われなかった。
SimpleSAMLphpのバグかSAMLの制約かまだはっきり分かってないのだけどおそらくはSAMLの制約。SPからのrequestにはSPで指定しているIdPのEntityIDなんて書いてないので、IdPはEntityIDをホスト名やそのときにSPからアクセスされたSSOサービスのパスから推測するしかない。そういうことなんだろう (SimpleSAMLphpではホスト名とpath1つめ、あるいはホスト名で推測する。EntityIDが変わってもSSOの入り口のURLは全く同じ (SimpleSAMLphpなら"'https://idp.example.com/simplesamlphp/saml2/idp/SSOService.php") なので、推測する方法はほぼない。ワークアラウンドとしてはホスト名を追加する。
○ デバッグめんどくさい
phpのエラーがSimpleSAMLphp側に吐かれるもんだと思ったらクラスが見つからないときはそっちは何も言わずにこけててhttpdのログに吐かれててうぐう
後、今回の構成の場合IdPとSPのログが混ざるため、私の方で勝手にホスト名をLoggerに吐かせている。これはSAMLを勉強するのにも結構役に立つ。具体的にはLogger.phpのlog_internal()のどこかにSimpleSAML_Utilities::getSelfHost()を忍び込ませる。
tail -f /var/log/simplesamlphp/simplesamlphp.log | awk '{for(i=1;i<7;i++) $i="";sub(/^[ \t]+/, "");print}' とするともーれつにデバッグしてるときに要らない先頭部分がそぎ落とされるので楽は楽。