※上記の広告は60日以上更新のないWIKIに表示されています。更新することで広告が下部へ移動します。

プラグイン名

open_id_authenticationプラグイン

setup

何が出来るか

  • OpenIDを使ってユーザ登録やログインする処理を作る
  • OpenID Providerからの追加属性(メアドとか性別とか)取得サポート(SREG)
  • OpenID Providerをホワイトリスト/ブリックリストで制限する
  • OpenID URLからOpenID ProviderのURL(Endpoint URL)を調査して、上記ホワイト/ブラックリストに追加するためのスクリプトも用意(Maimuzoが適当に作った物)
  • open_id_authenticationプラグインは、部品を提供しているに過ぎなく、ジェネレータなどは付いてこないので、基本的に処理は自分で作る必要がある

方針

  • 結局、どんな機能が必要で、認証できた/出来なかったときどうしたいかは、アプリ毎に違うので定型化しない方がよい
  • でも、フルスクラッチで作ると辛い
  • open_id_authenticationを部品として使い、細かいところは自分で作る
  • ジェネレータで作るより、コピペでがりがりやる。(ジェネレータ無いし)
  • open_id_authenticationプラグイン自体にも手を入れる(そのままだとエラーの振り分けさえ出来ないので)
  • 下記コードをそのまま動かすには、改造版が必要。これをvender/plugins/open_id_authentication/libに上書きして使う

標準作業

# sudo gem install ruby-openid
# script/plugin install open_id_authentication
# rake open_id_authentication:db:create
# rake db:migrate

お好みで

他の認証系プラグインを使わないならUserモデルを自作する必要がある

# script/generate model User nickname:string email:string claimed_url:string fullname:string birth_date:string gender:integer postcode:string country:string language:string timezone:string

以下のホワイト/ブラックリスト形式でOpenIDプロバイダに制限を加えるなら、そのリストを作る

# script/generate model TrastedOpenidProvider endpoint_url:string

ログインしないと見れないページがあるならapp/controllers/application.rbに追加する

class ApplicationController < ActionController::Base
 # 未ログイン状態でログインが必要なページに入ろうとすると、元のページに戻される
 # ログイン専用ページがない場合など
 def block_until_authorized
   unless login?
     flash[:notice] = "Please log in"
     redirect_to(request.referer)
   end
 end

 # ログインが必要なページならば認証ページをはさみ、認証したらそのページに誘導する
 # ログイン専用ページがある場合など
 # 一部
 # http://japan.internet.com/column/developer/20080627/26.html
 # を参考に書き換え必要
 def go_through_authorized
   unless login?
     flash[:notice] = "Please log in"
     # save the URL the user requested so we can hop back to it
     # after login
     session[:jumpto] = request.parameters
     redirect_to("/login")
   end
 end
end

add to app/helper/application_helper.rb

module ApplicationHelper
 def login?
   session[:user_id]
 end

 def logined_user
   User.find(session[:user_id])
 end
end

ログインが必要なページを指定する

class SomeController < ApplicationController
 before_filter :block_until_authorized,
   :only => [ :new , :edit, :create, :update, :destroy]

end

セッションコントローラーの作成

generate controller

# script/generate controller sessions

set route to config/routes.rb(RESTful風味)

 map.open_id_complete 'session', :controller => "sessions", :action => "create", :requirements => { :method => :get }
 map.resource :session
 map.login  '/login',  :controller => 'sessions', :action => 'new'
 map.logout '/logout', :controller => 'sessions', :action => 'destroy'

paste this controller

class SessionsController < ApplicationController

 # TODO:change default page
 @@default_page = "/"

 # require property from a OpenID provider
 # [:(User model property) => "(OpenID provider property in sreg)"]
 @@required = {
   :nickname => "nickname",
   :email => "email"
 }

 # optional property from a OpenID provider (sreg)
 # [:(User model property) => "(OpenID provider property in sreg)"]
 @@optional = {
   :fullname => "fullname",
   :birth_day => "dob",
   :gender => "gender",
   :postcode => "postcode",
   :country => "country",
   :language => "language",
   :timezone => "timezone"
 }

 # TODO:if your app has an especialy login page, you can use this index action
 # GET /sessions/new
 def new
   #redirect_to :controller => "TODO::your_logined_user_controller" if login?
   redirect_to default_page
 end

 # POST /sessions
 def create
   if using_open_id?
     open_id_authentication
   else
     flash[:error] = "You must provide an OpenID URL"
     redirect_to tyied_page
   end
 end

 # DELETE /sessions
 # GET    /logout
 def destroy
   session[:user_id] = nil
   redirect_to default_page
 end

protected

 def open_id_authentication
   # request options
   # :whitelist and :blacklist require ActiveRecord class
   # need to modify oepn_id_authentication.rb
   options = {
     :required => @@required.values.map {|str| str.to_sym},
     :optional => @@optional.values.map {|str| str.to_sym},
     :whitelist => TrastedOpenidProvider,
     :target_column => "endpoint_url"
   }
   authenticate_with_open_id(params[:openid_url], options) do |status, identity_url, registration|
     case status.result
     when :found_in_whitelist_or_blacklist
       failed_login "Sorry, the OpenID server is blocked by the white list"
     when :double_auth
       failed_login "Error, detect a double autentication"
     when :missing
       failed_login "Sorry, the OpenID server couldn't be found"
     when :canceled
       failed_login "OpenID verification was canceled"
     when :failed
       failed_login "Sorry, the OpenID verification failed"
     when :successful
       if @current_user = User.find_by_claimed_url(identity_url)
         successful_login
       else
         @current_user = User.new
         assign_registration_attributes!(registration)
         @current_user.claimed_url = identity_url
         @current_user.nickname = identity_url.delete("http://")[0..8] if @current_user.nickname.blank?

         if @current_user.save
           successful_login
         else
           failed_login "Your OpenID profile registration failed: " +
             @current_user.errors.full_messages.to_sentence
         end
       end
     end

   end
 end

 def successful_login
   session[:user_id] = @current_user.id
   #jumpto = session[:jumpto] || default_page
   #session[:jumpto] = nil
   #redirect_to(jumpto)
   redirect_to(root_url)
 end

 def failed_login(message)
   flash[:error] = message
   redirect_to default_page
 end

  # if you don't use map.resource in config/routes.rb, you need to use root_url method:
# def root_url
# # TODO:check with config/routes.rb
# open_id_complete
# end

 def default_page
   @@default_page
 end

 def tyied_page
   request.referer
 end

 # registration is a hash containing the valid sreg keys given above
 # use this to map them to fields of your user model
 def assign_registration_attributes!(registration)
   model_to_registration_mapping.each do |model_attribute, registration_attribute|
     unless registration[registration_attribute].blank?
       @current_user.send("#{model_attribute}=", registration[registration_attribute])
     end
   end
 end

 # TODO:change this hash like your user model.
 def model_to_registration_mapping
   @@required.merge(@@optional)
 end
   
end



必要ならapp/views/sessions/new.html.erbを作る

<% if flash[:error] -%>
 <%= flash[:error] %>
<% end -%>
<% form_tag(session_url) do |f| -%>
 <label for="openid_url" >
   OpenId URL:
 </label>
 <%= text_field_tag :openid_url -%>
 <%= submit_tag "Login" -%>
<% end -%>


公式ページ

GitHubのページ
※いや、公式かどうかはわからない

日本語解説ページ


外国語解説ページ

  • 良いところがない

のうはう

  • マイグレーションファイルの構造を載せておく
class AddOpenIdAuthenticationTables < ActiveRecord::Migration
  def self.up
    create_table :open_id_authentication_associations, :force => true do |t|
      t.integer :issued, :lifetime
      t.string :handle, :assoc_type
      t.binary :server_url, :secret
    end
    create_table :open_id_authentication_nonces, :force => true do |t|
      t.integer :timestamp, :null => false
      t.string :server_url, :null => true
      t.string :salt, :null => false
    end
  end
  def self.down
    drop_table :open_id_authentication_associations
    drop_table :open_id_authentication_nonces
  end
end

コメント

名前: