Rails + Devise + omniauthでTwitterの認証

ずいぶん間が空いてしまいましたが技術ネタで更新したいと思います.

最近さくらのVPSを借りまして,Railsなんか入れて遊んでみようと思ったわけです.
Twitterと連携できたらなおさら楽しいよね,ということで,
練習がてらBotのようなものでも作ってみようかとも思っています.

んで,TwitterのOAuthも使える認証機構としてDevise(Devi'c'eじゃなかった)ってのがあったので
使い始めるまでの記録をメモがてら残してみます.

参考にしたページはこのあたりです.
Rails3 認証エンジン「devise」
http://d.hatena.ne.jp/glpgsinc/20110503/1304395983
Rails3 deviseによるtwitter認証
http://d.hatena.ne.jp/glpgsinc/20110508/1304786181
Rails で Devise と OmniAuth を連携させる
http://blog.twiwt.org/e/14b25f
241: 簡単なOmniAuth
http://ja.asciicasts.com/episodes/241-simple-omniauth

//==========作業履歴==========//

// 環境
// Ubuntu 10.04, rvm 1.6.22, ruby 1.8.7, rubygems 1.6.2, rails 3.0.7

// rvmは次のようなgemsetを作成済み
rvm use 1.8.7@rails3

rails new test_d -d mysql

cd test_d

vi .rvmrc

rvm use 1.8.7@rails3


// Gemfileの編集.
// Rails3ではmysql2のバージョンが新しすぎるとハマるので0.3系以上を使わないようにする
vi Gemfile

gem 'mysql2','<0.3'
gem 'devise'
gem 'oa-oauth', :require => "omniauth/oauth"


// gemとdbの準備をする
bundle install
rake db:create
rake db:migrate

// deviseのインストール
rails g devise:install

// Oauthのconsumer_keyとconsumer_key_secretの情報を追加
// 予めdev.twitter.comで取得する
vi config/initializers/devise.rb

config.omniauth :twitter, "consumer_key","consumer_key_secret"


// deviseの機能を使えるモデルの生成
rails g devise User
// omniauthを使うためには :omniauthable
vi app/models/user.rb

class User < ActiveRecord::Base
devise :trackable, :omniauthable
end


// migrationの作成
// 要らないものは消す.足りないカラムは後からrake db:migrateで追加するので今は気にしない
vi db/migrate/20110715043006_devise_create_users.rb

class DeviseCreateUsers < ActiveRecord::Migration
def self.up
create_table(:users) do |t|
t.trackable
t.timestamps
end
end

def self.down
drop_table :users
end
end

// uid, screen_name, access_token, access_secret を入れるカラムの追加
rails g migration AddTokenToUser uid:integer screen_name:string
access_token:string access_secret:string
// DBに関係する記述が終了.migrationする
rake db:migrate

// routesの確認
rake routes
> user_omniauth_callback /users/auth/:action/callback(.:format) {:controller=>"devise/omniauth_callbacks", :action=>/twitter/}

// callbackにカスタムのコントローラーを使えるようにする為にroutesを設定
vi config/routes.rb

devise_for :users, :controllers => {:omniauth_callbacks => "omniauth_callbacks"}

> user_omniauth_callback /users/auth/:action/callback(.:format) {:controller=>"omniauth_callbacks", :action=>/twitter/}

// callback用のカスタムコントローラーの作成
rails g controller OmniauthCallbacks twitter

vi app/controllers/omniauth_callbacks_controller.rb

class OmniauthCallbacksController < ApplicationController
def twitter
# You need to implement the method below in your model
@user = User.find_for_user_oauth(env["omniauth.auth"],nil)

if @user.persisted?
flash[:notice] = I18n.t "devise.omniauth_callbacks.success",
:kind => "User"
sign_in_and_redirect @user, :event => :authentication
else
session["devise.twitter_data"] = env["omniauth.auth"]
redirect_to root_path
end
end
end



// Userモデルにメソッド追加.
// DBに既に保存されていればそれを返す.そうでなければ新しく保存する
vi app/models/user.rb

class User < ActiveRecord::Base
# Include default devise modules. Others available are:
# :token_authenticatable, :encryptable, :confirmable, :lockable,

timeoutable and
omniauthable

devise :trackable, :omniauthable

# Setup accessible (or protected) attributes for your model
#attr_accessible :email, :password, :password_confirmation, :remember_me

def self.find_for_user_oauth(access_token, signed_in_resource=nil)
data = access_token['extra']['user_hash']
if user = User.find_by_uid(access_token['uid'].to_i)
user
else
User.create!({
:uid => access_token['uid'].to_i,
:screen_name => data['screen_name'],
:access_token => access_token['credentials']['token'],
:access_secret => access_token['credentials']['secret']}
)
end
end
end


// トップページを作成,サーバーのrootに設定
rails g controller welcome index

vi config/routes.rb

root :to => 'welcome#index'


// アプリケーション内の共通テンプレートにログイン用のリンクを張る
vi app/views/layout/application.html.erb<% if user_signed_in? %>
Hi! <%= current_user.screen_name %>
|
<%= link_to "Sign Out", destroy_user_session_path %><% else %>
<%= link_to "Sign in with Twitter", user_omniauth_authorize_path(:twitter) %><% end %>


// サインアウトしたときのためのリンクのroutesを張るために編集
vi config/routes.rb

devise_for :users, :controllers => {:omniauth_callbacks =>
"omniauth_callbacks"} do
get '/users/sign_out', :to => 'devise/sessions#destroy', :as =>
:destroy_user_session
end



// 消さないとサーバーのルートが見られない
rm public/index.html
// Webrick起動
rails s

// ログインができるかの確認の為に,WebのTwitterからログアウトしておくといい.
// ブラウザで開く.localhost:3000とか.

// Sign in with TwitterをクリックしてOauth認証画面に遷移

// ログインできていることを確認

// mysqlからDBにも保存されていることを確認できる
mysql -u root test_d_development
select * from users;

//============作業履歴終了=============//

できることの幅が広がりそうなので,興味のある方は試してみてはいかがでしょうか.