前回のおさらい
前回はRPのサンプルをRails上で動作させました。 この時に使用したRailsのアクションをまとめておきます。
- ConsumerController#begin
- OpenIDリクエストを生成するRailsのアクション。
- ConsumerController#complete
- OpenIDレスポンスを受信するRailsのアクション。
OpenIDの一番の特徴は、
- Discovery
- 利用者が入力したOpenIDアカウント名
(User-Supplied Identifier) を元にOPのログイン画面 (OP Endpoint URL) を見つける。 - SREG
- OpenIDの拡張領域を使って利用者のメールアドレスなどをOPとRPで交換する。
Discovery…OpenIDアカウント名からOPのログイン画面を見つける
前回のサンプルでは、
# ユーザが入力したopenid_identifierを元にOpenIDリクエストを作成
17 oidreq = consumer.begin(params[:openid_identifier])
consumerはOpenID::Consumerクラスのオブジェクトで、
# 利用者をOPのログイン画面(OP EndPoint)へと誘導する
47 redirect_to oidreq.redirect_url(realm, return_to, params[:immediate])
ここで重要なのは、
- はてな
- 利用者が入力したOpenIDアカウント名
(User-Supplied Identifier) - http://
www. hatena. ne. jp/ kmachu/ - OPのエンドポイントURL
(OP Endpoint URL) - http://
www. hatena. ne. jp/ openid/ server
- 利用者が入力したOpenIDアカウント名
- Yahoo!
- 利用者が入力したOpenIDアカウント名
(User-Supplied Identifier) - yahoo.
com - OPのエンドポイントURL
(OP Endpoint URL) - https://
open. login. yahooapis. com/ openid/ op/ auth
- 利用者が入力したOpenIDアカウント名
OpenIDでは不特定多数のOPが存在するため、
- HTMLの中にOPのエンドポイントURLを記述する
- YadisとXRDSを用いる
概念を説明するよりも、
discoveryコマンドを使って認証サーバを見つけよう
ruby-openidライブラリには、
ruby-openid-2.0.4/examples/discover
まず、
$ ./discover http://www.hatena.ne.jp/kmachu/ ================================================== Running discovery on http://www.hatena.ne.jp/kmachu/ Claimed identifier: http://www.hatena.ne.jp/kmachu/ Discovered services: 1. Server URL : http://www.hatena.ne.jp/openid/server Type URIs: * http://openid.net/signon/1.1
Claimed identifierが入力したOpenIDアカウント名です。
discoverコマンドはこのURLを元にdiscoveryを行い、
Yahoo!でも試してみましょう。
Yahoo!の場合は利用者のOpenIDアカウント名ではなくyahoo.
$ ./discover yahoo.com Running discovery on yahoo.com Claimed identifier: http://www.yahoo.com/ Discovered services: 1. Server URL : https://open.login.yahooapis.com/openid/op/auth Type URIs: * http://specs.openid.net/auth/2.0/server * http://specs.openid.net/extensions/pape/1.0
はてなの例と同じように、
なお、
$ ./discover http://www.hatena.ne.jp/ ================================================== Running discovery on http://www.hatena.ne.jp/ Claimed identifier: http://www.hatena.ne.jp/ No OpenID services found
HTMLからOPのURLを取得する
はてなもYahoo!もdiscoveryによってOPのエンドポイントURLを見つけることができました。
ですが、
はてなの場合は、
curlコマンドを使ってHTMLを取得し、
$ curl http://www.hatena.ne.jp/kmachu/ | grep openid <link rel="openid.server" href="http://www.hatena.ne.jp/openid/server" />
HTML文書に含まれるlink要素として、
なお、
Yadis+XRDSからOPのURLを取得する
次にYahoo!で試してみましょう。
同じようにcurlコマンドを使ってHTMLを取得し、
$ curl http://www.yahoo.com/ | grep openid
結果は空でした。HTMLの中にはOpenIDの記述が書かれていないようです。
実はYahoo!では、
$ curl --head http://www.yahoo.com/ HTTP/1.1 200 OK Date: Thu, 27 Mar 2008 23:18:13 GMT X-XRDS-Location: http://open.login.yahooapis.com/openid20/www.yahoo.com/xrds Last-Modified: Thu, 27 Mar 2008 23:04:22 GMT Content-Length: 9616 Connection: close Content-Type: text/html; charset=utf-8
指定されたURLにアクセスするとXRDS文書が取得できます。
このXMLの中に、
$ curl http://open.login.yahooapis.com/openid20/www.yahoo.com/xrds <?xml version="1.0" encoding="UTF-8"?> <xrds:XRDS xmlns:xrds="xri://$xrds" xmlns:openid="http://openid.net/xmlns/1.0" xmlns="xri://$xrd*($v*2.0)"> <XRD> <Service priority="0"> <Type>http://specs.openid.net/auth/2.0/server</Type> <Type>http://specs.openid.net/extensions/pape/1.0</Type> <URI>https://open.login.yahooapis.com/openid/op/auth</URI> </Service> </XRD> </xrds:XRDS>
このように、
- 利用者が入力したURLからXRDS文書のURLを取得する
- XRDS文書を取得し、
XRDS文書中に書かれているOPのエンドポイントURLを取得する
ステップが一つ増えているので、
discoveryのまとめ
動的にOPのエンドポイントURLを見つけるdiscoveryには、
- HTML文書に書かれたOPのエンドポイントURL取得する
- Yadisプロトコルを使ってXRDS文書を探し、
XRDS文書に書かれたOPのエンドポイントURLを取得する

YadisとXRDS文書については、
OpenIDの拡張領域
OpenIDは拡張領域
- PAPE…OpenID Provider Authentication Policy Extension
- SREG…OpenID Simple Registration Extension 1.
0 - AX…OpenID Attribute Exchange 1.
0
PAPEはOPにおける利用者の認証レベルを表すものです。
RPがOPに対して、
SREGとAXは、
SREGを使って利用者の名前とメールアドレスを取得する
前回動かしたRailsのサンプルには、
$ ./discover http://myopenid.com ================================================== Running discovery on http://myopenid.com Claimed identifier: http://www.myopenid.com/ Discovered services: 1. Server URL : http://www.myopenid.com/server Type URIs: * http://specs.openid.net/auth/2.0/server * http://openid.net/sreg/1.0
筆者はあらかじめmyopenid.
前回も利用したRailsのサンプルを起動して、

コードを見てみましょう。SREGの要求パラメータはOpenID::SReg::Requestクラスを使って管理します。
OpenID::SREG::Requesのオブジェクトを作り、
25 sregreq = OpenID::SReg::Request.new
26 # required fields
27 sregreq.request_fields(['email','nickname'], true)
28 # optional fields
29 sregreq.request_fields(['dob', 'fullname'], false)
30 oidreq.add_extension(sregreq)
OPであるmyopenid.
ここでmyopenid.

ログインが終わりOPからRPへと戻ってくると、

ソースコードを見てみましょう。
まず、
# OpenID::Response から SREG レスポンスのオブジェクトを生成
71 sreg_resp = OpenID::SReg::Response.from_success_response(oidresp)
OPから送られてきたデータは、
# SREG レスポンスのキーと値を取得
77 sreg_resp.data.each {|k,v|
78 sreg_message << "
#{k}: #{v}"
79 }
SREでは、
しかし、
終わりに
今回はOpenIDの内部の仕組みとして、
次回はいよいよ、