自前で OpenID プロバイダを立てつつある今日この頃.
一時は Clamshell というのを使おうと思っていたのですが, OpenID 2.0 にも対応しているということで,SimpleID を試してみることにしました.
だけど,署名が一致しないとかでどうもうまくいきません.
仕方ないので,ソースを読んでみると,どうやらおかしい部分発見.
index.php の function simpleid_sign() の部分なのですが
492 // Get all the signed fields [10.1]
493 $signed_fields = array('op_endpoint', 'return_to', 'response_nonce', 'assoc_handle', 'identity', 'claimed_id');
494 $signed_fields = array_merge($signed_fields, extension_invoke_all('signed_fields', $response));
495
496 // Check if the signed keys are actually present
497 $to_sign = array();
498 foreach ($signed_fields as $field) {
499 if (isset($response['openid.' . $field])) $to_sign[] = $field;
500 }
501
502 $response['openid.signed'] = implode(',', $signed_fields);
503
504 // Generate signature for this message
505 $response['openid.sig'] = _openid_signature($assoc, $response, $to_sign);
506 return $response;
505 行目の _openid_signature で実際に signature を openid.sig に入れるんですが,そのとき signature の対象となるのは $to_sign です..
ここで,$to_sign に何が入っているかというと $signed_fields のうち,$response で設定されていたものだけ.
つまり,$response で claimed_id が設定されていなければ,('op_endpoint', 'return_to', 'response_nonce', 'assoc_handle', 'identity') なわけです.
逆に言えば,設定されていない 'claimed_id' に対しては署名は行われないのです.
だがしかし.
'openid.signed' には何が入るかと言えば,$signed_fields の要素をつないだ文字列が入ってます.
つまり,'op_endpoint,return_to,response_nonce,assoc_handle,identity,claimed_id' ですな.
署名していないはずの,'claimed_id' までも署名されたことになっとります.
OpenID の仕様として,認証プロセスの途中で,openid.signed に含まれているものから再度署名を作り出して openid.sig と一致するかどうかを試すわけですが,
署名する対象が明確に伝わってないんだから,signature が一致しないというエラーが出て当然ですよね...
この部分をちょろちょろっと直して完了.
うまく動作するようになりました.