RP側のAssertion出来た。
OP側も作り出してみた。
RP
取れたのはいいんだけど、OAuthを調べた後だと、どこの馬の骨とも知れないRPに安々とデータを渡していいものか…と思ってしまう。
前回調べたYadisは「XRDSファイルの場所を辿る」って部分も含めてYadisプロトコルだったらしい。
class Yadis{}はclass Xrds{}に変更した。
OAuthと同じ感覚でclass OpenID_Consumer{}としてたけど、仕様に合わせるべくclass OpenID_RP{}に変更。
データの保存は、abstract class OpenID_Store{}ってのを作って、実装はそれを継承させる。
どうせ一時のデータだから、serializeしてMemcacheに入れる事に。
class OpenID_Store_Memcache extends OpenID_Store{}とした。
Assertion
<?php class OpenID_RP { // 〜〜〜 略 〜〜〜 public function assertion() { if (OpenID_Utils::getOpenIDParam('mode')=='id_res') { if (!is_null(OpenID_Utils::getOpenIDParam('invalidate_handle'))) { throw new OpenID_Exception('Invalidate handle'); } if ($this->_store) { $assoc_cache = $this->_store->getAssociation(OpenID_Utils::getOpenIDParam('assoc_handle')); $auth_cache = $this->_store->getAuthorization(OpenID_Utils::getOpenIDParam('assoc_handle')); if (isset($assoc_cache, $auth_cache)) { $this->_assoc_req = $assoc_cache[0]; $this->_assoc_res = $assoc_cache[1]; $this->setAssocType($this->_assoc_res['assoc_type']); $this->setSessionType(@$this->_assoc_res['session_type']); OpenID_Utils::debug('assertion cache association req', $this->_assoc_req); OpenID_Utils::debug('assertion cache association res', $this->_assoc_res); OpenID_Utils::debug('assertion cache authorization', $auth_cache); // verify return_to if ($auth_cache['openid.return_to']!=OpenID_Utils::getOpenIDParam('return_to')) { throw new OpenID_Exception('Assertion error: invalid return_to'); } // verify sig $signed = explode(',', OpenID_Utils::getOpenIDParam('signed', '')); $plain_arr = array(); foreach ($signed as $key) { $plain_arr[$key] = OpenID_Utils::getOpenIDParam($key); } $plain = OpenID_Utils::buildKeyValue($plain_arr); $sig = hash_hmac($this->getAssocAlgo(), $plain, base64_decode($this->_assoc_res['mac_key']), true); if ($sig==base64_decode(OpenID_Utils::getOpenIDParam('sig'))) { return true; } OpenID_Utils::debug('assertion sig', base64_encode($sig)); throw new OpenID_Exception('Assertion error: invalid openid.sig'); } } throw new OpenID_Exception('Assertion error: not found assiciation'); } return false; } // 〜〜〜 略 〜〜〜 }
間接通信 エラー時の間接応答
間接通信でエラーがあった場合、RPにリダイレクトすると仕様に書いてある。
だけど巷のOPは、Assertionで不正なパラメータを送ってもリダイレクトせずに、ユーザエージェントに対してエラーが発生した事を伝えてきた。(mixiとYahoo!)
この辺は意外と適当なのかもしれない。
5.2.3. エラー時の間接応答
Final: OpenID Authentication 2.0 - 最終版
不正な要求があった場合や無効な引数が含まれていた場合、OP は、ユーザエージェントを "openid.return_to" URL 値にリダイレクトしなければならない (MUST)。ただし、値が存在し、その値が有効な URL である場合に限る。
OP
XRDSファイルはContent-Type: application/xrds+xmlとmixiのXRDSのパスだけを修正したもの。
index.phpではヘッダにX-XRDS-Location: http://〜〜〜を出力。
OpenID APIは、送られてきたopenid.modeをみて叩くメソッドを分岐させた。
作ったメソッドは、associateとcheckid_setupだけ。
多分Sregとかにも対応させた場合、ここの分岐がちょっと変わる。
こっちもデータはMemcacheにいれた。
で、自作RPライブラリとうまい事やり取り出来たから、OpenID Enabledのサンプルと連携させてみたら、Stateless modeを使ってるらしく駄目だった。
OpenID Enabledのライブラリだと、こんなフォームを生成してる。
<form accept-charset="UTF-8" enctype="application/x-www-form-urlencoded" id="openid_message" action="https://mixi.jp/openid_server.pl" method="post"> <input type="hidden" name="openid.ns" value="http://specs.openid.net/auth/2.0" /> <input type="hidden" name="openid.ns.sreg" value="http://openid.net/extensions/sreg/1.1" /> <input type="hidden" name="openid.ns.pape" value="http://specs.openid.net/extensions/pape/1.0" /> <input type="hidden" name="openid.sreg.required" value="nickname" /> <input type="hidden" name="openid.sreg.optional" value="fullname,email" /> <input type="hidden" name="openid.pape.preferred_auth_policies" value="" /> <input type="hidden" name="openid.realm" value="http://localhost:80/php-openid-2.1.3/examples/consumer/" /> <input type="hidden" name="openid.mode" value="checkid_setup" /> <input type="hidden" name="openid.return_to" value="http://localhost:80/php-openid-2.1.3/examples/consumer/finish_auth.php?janrain_nonce=2010-05-24T06%3A38%3A51ZGKt15U" /> <input type="hidden" name="openid.identity" value="http://specs.openid.net/auth/2.0/identifier_select" /> <input type="hidden" name="openid.claimed_id" value="http://specs.openid.net/auth/2.0/identifier_select" /> <input type="hidden" name="openid.assoc_handle" value="1274683131:8tIfki7Unl1kBvOu7h5B:4526f2f65d" /> <input type="submit" value="Continue" /> </form>
Stateless modeについて詳しく書いてあるサイトがあんまりなかった…。
ちょっと古い記事だけど、多分ここが詳しい。
斜め読みOpenID Authentication 1.1 Modes - Yet Another Hackadelic
http://d.hatena.ne.jp/ZIGOROu/20070322/1174560537