OpenID対応
http://project.webjourney.org/issues/show/4
認証用のユーザーID, パスワード管理に解放されたくてConsumerを書いています。
まず、openid用のライブラリを導入。
sudo gem install ruby-openid
でRailsで簡単なテスト用Applicationを書く。gem の中にサンプルがあるのでそれをさらにミニマイズしたものが以下。
# app/controller/id_test_controller.rb require 'openid' require 'openid/store/filesystem' class IdTestController < ApplicationController def index end def begin @openid_url = params[:openid_url] if request.post? begin request = consumer.begin(@openid_url) redirect_to request.redirect_url(url_for(:controller =>''), return_to) rescue OpenID::OpenIDError => e flash[:error] = "Error authentication (#{e.message})." redirect_to :action => "index" end else redirect_to :action => "index" end end def complete parameters = params.reject{|k,v|request.path_parameters[k]} response = consumer.complete(parameters, return_to) case response.status when OpenID::Consumer::FAILURE flash[:error] = "Authentication Failure (#{response.message})." redirect_to :action => "index" when OpenID::Consumer::SUCCESS # ここに認証成功の処理を書く end end private def return_to url_for(:action => "complete", :only_path => false) end def consumer if @consumer.nil? dir = File.join(RAILS_ROOT, "tmp", "idstore") store = OpenID::Store::Filesystem.new(dir) @consumer = OpenID::Consumer.new(session, store) end @consumer end end
<%# app/views/id_test/index.html %> <html> <body> <h1>OpenID Consumer Test</h1> <div><%= flash[:error] %></div> <% form_tag :action => 'begin' do %> <%= text_field_tag 'openid_url', @openid_url %> <%= submit_tag 'login' %> <% end %> </body> </html>
<%# app/views/id_test/complete.html %> <html> <body> <h1>OpenID Authentication Success!!</h1> </body> </html>
- consumer.begin で共通鍵を生成して、ユーザーにはOpenID Providerのサイトへリダイレクトしておく
- ユーザーの認証情報がOpenID Providerサイトへ入力され、認証処理が行われる。
- 結果がパラメーターで渡されて、Consumerサイトへ再度リダイレクトされる。
- Consumerサイトでは、Filesystemからconsumerの情報をとって、認証結果を照合して、認証できたかどうかを判定できる。
なるほど。実際にコードを書いてみるまでよくわからなかったけど、これは中々おもしろい仕組みだなぁと。どこまでできるのかは要チェックかも。
とりあえず、既存のWjUserモデルには openid_url を追加すれば対応できそう。パスワードが不要になったり、いろいろとvalidationを買えなければならないけれど。あとはAjaxの部分HTMLで認証画面を遷移させている部分。。。iframeにすればOK??