--- layout: old_post title: MySpaceでOpenSocialアプリケーション OpenIDクライアント を試す ー (2) permalink: /tatsuya/show/418-myspace-opensocial-openid-2 ---
↓ このエントリの続き
MySpaceでOpenSocialアプリケーション「OpenIDクライアント」を試す ー (1)
引き続き、OpenIDのIdentifier入力からOpenID Provider(以下OP) エンドポイントURLの探索までを実装する
UIとしてIdentifierを入力するフォームを用意、submitにイベントを追加する。今回この辺りはjQueryを使った。
<form class="rp">
<input id="identify" type="text" name="openid_identifier" />
<input type="submit" value="Sign in" />
</form>
<script type="text/javascript">
$("form.rp").submit(function(){
var ident = $("#identify").attr("value");
openid.auth(ident, function(result){
//something do
});
});
</script>
formの値を取得し、メインロジックopenid.authを呼ぶ。以後は normalize > discovery > association > authentication > response parse > verify の順に実行していく。
この辺りはまだOpenSocialに関係無く普通のHTML + JavaScript
ちなみに処理全体の流れは、大体以下のようになる予定。
var openid = {
auth: function(request_ident, callback){
var self = this;
//IDの正規化、http://を補足( 例:tkmr.myopenid.com => http://tkmr.myopenid.com/ )
request_ident = self.normalize(request_ident);
//OpenID認証局のエンドポイントURLを探索( 例:http://tkmr.myopenid.com/ => http://myopenid.com/server )
self.discovery(request_ident, function(request_option){
//共有鍵の交換(任意) - 未実装
//var assoc_handle = self.association();
//discoveryで見付かったOpenID認証局エンドポイントURLへ認証リクエストを投げる(IFrameで代用)
self.auth_request(request_option, function(response){
//認証結果を確認、IFrameのURLから取得
var res = self.auth_response_parse(response);//認証結果の署名を確認
if(self.verify(res)){
callback(res);
}else{
callback(false);
}
}
}
}
}
参考:http://lab.koshigoe.jp/en2ja/openid-authentication-2_0.html#normalization
ユーザの入力したIdentifierの正規化を行う、正式な仕様としては XRI の正規化をサポートする必要があると思うが今回は未実装
とりあえずIdentifierが http で始まらない場合 http:// を付加しておいた。
openid.normalize = function(identify){
var new_ident = identify.search(/^(http|https):\/\//) > 0 ? identify : "http://" + identify;
return new_ident;
}
参考:http://lab.koshigoe.jp/en2ja/openid-authentication-2_0.html#discovery
・XRI ( XRIのリンク集 - Yet Another Hackadelic )
・Yadis ( 第3回 OpenIDプロトコルの特徴-DiscoveryとSREG )
今回の実装では、HTMLベース探索 を試す(XRIとYadisによる探索は未実装)
openid.discovery = function(ident, callback){
switch(ident.split("://")[0]){
case "http":
openid.html_discovery(ident, callback);
break;
case "xri":
openid.xri_discovery(ident, callback);
break;
default:
alert("error!!!!!");
break;
}
}
ユーザのIdentifier(URL)に存在するHTMLを取得し、OPのエンドポイントURLを探し出す。
例:
<html>
<head>
<link rel="openid2.provider" href="認証局エンドポイントURL" />
</head>
まずIdentifier(URL)にあるコンテンツを取得する必要がある、今回はHTTPリクエストを OpenSocial APIの gadgets.io.makeRequest で投げる。
openid.html_discovery = function(identify, callback){
var params = {};
params.contentType = gadgets.io.ContentType.TEXT;
gadgets.io.makeRequest(identify, function(res){
//取得結果(HTML)のパース&解析処理
}, params);
}
gadgets.io.ContentTypeは XML・JSON・TEXT・FEED の4種類が用意されていて、XMLならXMLHttpRequestのresponseXMLが返ってきたりと、それぞれ想像通りに動く。
・ContentType:http://code.google.com/apis/opensocial/docs/0.7/reference/gadgets.io.ContentType.html
・RequestParameter:http://code.google.com/apis/opensocial/docs/0.7/reference/gadgets.io.RequestParameters.html
また任意のヘッダをリクエストへ付けることも可能
params[gadgets.io.RequestParameters.HEADERS] = {"Accept-Language" : "ja"};
今回の対象はHTMLのため ContentType はTEXT に設定、単純なStringとしてHTMLが返ってくるので、そのHTML内にある目的の <link rel="openid2.provider" href="***" /> タグを探す
var results = {}
var links = res.data.match(/<link[^>]*>/g);
for(var i=0; i < links.length; i++){
var link = links[i];
if(link.search(/rel.*openid2.provider/) > 0){
results.provider = link.match(/href="([^"]*)"/)[1];
}else{
if(link.search(/rel.*openid2.local_id/) > 0){
results.local_id = link.match(/href="([^"]*)"/)[1];
}
}
}
callback(results);
ついでに rel="openid.server" も探しておいた方が良いかも。
するためにはレスポンスヘッダの内容を知る必要がある、はず。OpenSocial / makeRequestのドキュメントには特に記述が無かったのでレスポンスヘッダへのアクセスは不明・・・
ただ、makeRequest の通信内容を見る限りでは取得可能なように見える。
レスポンスヘッダさえ取れれば、あとは x-xrds-location に設定されたURLにあるXRDS文章を取得し、XRDSの仕様に従ってOPエンドポイントURLを見つける、で良いのかな。
XRIは・・・、仕様から勉強しておきます:)
以上、今回はOpenID Providerの認証エンドポイントURLの探索まで実装しました。
それでは明日へ続く