bekkou68 の日記

Gogengo! や IT 技術など。

Rails で OpenID ログインを rails_warden と warden-openid で簡単に実装する - Implement OpenID Login Easy by rails_warden and warden-openid with Rails

必要な gem - Required gem

gem install rails_warden
gem install warden-openid

warden-openid の概要 - Outline of warden-openid

アプリ側から OP に遷移する際に、OP にコールバック先の URL を渡します。認証に成功したら、そのコールバック先にリダイレクトします。 - warden-openid sends the callback URL when transits from application to OP. When authorization is success, it redirects to the destination of callback.

http://github.com/ursm/warden-openid

ソースコード - Source code

ソースコードは自分の GitHub にあります。Rail3 で動作確認済みです。仕様としては、OpenID でログインしたらユーザメニューに飛びます。ユーザメニューは要ログインな画面です。ヘッダーがログイン状態を表示します。 - The source code is on my GitHub. I confirmed it worked on Rails3. The specification is when user login by OpenID then go to the user menu. The user menu is login-required. The header shows the login status.

http://github.com/bekkou68/openid

ソースコードに適宜コメントを入れて解説します。 - I put some comments into source code to explain.

config/initializers/warden.rb
require 'warden-openid'

Rails.configuration.middleware.use Rack::OpenID
Rails.configuration.middleware.use RailsWarden::Manager do |manager|
  manager.default_strategies :openid
  manager.failure_app = SessionsController # 認証が失敗した時に呼ばれる。 - Called when authorization failed.
end

class Warden::SessionSerializer
  def serialize(record)
    [record.class, record.id]
  end

  def deserialize(keys)
    klass, id = keys
    klass.find(:first, :conditions => { :id => id })
  end
end

Warden::OpenID.configure do |config|
  config.user_finder do |response|
    # 認証成功後に識別URL が一致するユーザを取得する。 - Get user has the same identity URL after authorization is success.
    User.find_by_identity_url(response.identity_url)
  end
end

[added at 2010/09/20] The following line deleted because Rails で warden.rb を編集後に redirect_to 後の flash に値が空になる - Value of flash After redirect_to Becomes Empty Caused by Editing warden.rb - bekkou68の日記

Rails.configuration.middleware.use Rack::Session::Cookie
app/controllers/sessions_controller.rb
class SessionsController < ApplicationController
  layout "application"

  def new
  end

  def signin
    # 認証。色々やってくれるすごいメソッド。 - Authentication. It does many things and is wonderful.
    authenticate!
    redirect_to :controller => "menus", :action => "index"
  end

  # 認証に失敗したら呼ばれる。 - Called when authentication is failed.
  def unauthenticated
    redirect_to :action => "new"
  end
end
app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
  protect_from_forgery

  def login_required
    # 認証されているかどうか。このステータスを見ると分かりやすい。 - Whether authenticated or not. This status makes clear.
    return true if authenticated?
    redirect_to :controller => "sessions", :action => "new"
    false
  end
end
db/migrate/*_create_users.rb
class CreateUsers < ActiveRecord::Migration
  def self.up
    create_table :users do |t|
      t.string :name
      t.string :identity_url # 忘れずに! - Don't forget!

      t.timestamps
    end
  end

  def self.down
    drop_table :users
  end
end

最後に - At the end

大体これくらい書くだけで実装できます。gem を作った人はすごい! - You can implement almost with writing this. Developers of gem are awesome!
間違っていたことを書いていたら教えてください。 - If I write some wrong, please tell me.