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

ローカルで試した限りだと、たとえsaml20.sendartifact がTRUEであっても、IdPはArtifactを使わず普通のレスポンスを送ってくれる。うざい

仕様レベルでは把握してないものの、IdPは自分が対応できるBindingのうちでisDefaultが付いているものはそれを先に、そうでない場合は順番にどれかえらぶ臭い。詳しいロジックは SAML2.php の getAssertionConsumerService() を読むと良い

というわけでisDefaultをArtifact側のBindingにつける

○ 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を持てない可能性が高いのは事実

最初、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}' とするともーれつにデバッグしてるときに要らない先頭部分がそぎ落とされるので楽は楽。


このブログの人気の投稿

LibreOfficeで表紙、目次、本体でフッターのページ番号のスタイルを変える

WiiUのコントローラが通信不良に陥った話

技術書典2 あ-03 『もわねっとのPythonの本』