Deviseとomniauthを使ってTwitterのOAuth認証
TwitterのOAuth認証を使うようなアプリってド定番なのに、時間が空くと、ワリと忘れちゃって時間をロスするので手順化しておこうと思う。
なお、usersとauthenticationsにユーザ情報を分けてるのは、Facebook認証とか追加するとき用、usersがauthenticationsが1対nになる。
[環境]
Mac OSX 10.6.8
ruby 1.8.7
rails 3.0.6
[参考]
http://blog.twiwt.org/e/14b25f
http://taksatou.blogspot.com/2011/03/twitterfacebookrails.html
http://taksatou.blogspot.com/2011/03/twitterfacebookoauthrailsomniauth.html
・Gemfileに追加
gem 'devise' gem 'omniauth', '~> 0.2.6'
・bundleする
$ bundle install
・config/omniauth.rbをつくる
Rails.application.config.middleware.use OmniAuth::Builder do if Rails.env == 'development' provider :twitter, 'TOKEN', 'SECRET' else provider :twitter, 'TOKEN', 'SECRET' end end
・Deviseのセットアップ
$ rails g devise:install create config/initializers/devise.rb create config/locales/devise.en.yml $ rails g devise user invoke active_record create db/migrate/20110816040643_devise_create_users.rb insert app/models/user.rb route devise_for :users $ rails g model Authentication
★model/user.rbを編集(色々コメントアウト)
require 'digest/sha1' class User < ActiveRecord::Base has_many :authentications devise :trackable, :omniauthable end
★model/authentication.rbに追記
class Authentication < ActiveRecord::Base belongs_to :user end
★2つのmigrationファイルをそれぞれ修正してmigration実行
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 class CreateAuthentications < ActiveRecord::Migration def self.up create_table :authentications do |t| t.integer :user_id t.string :provider t.string :uid t.string :screen_name t.string :access_token t.string :access_secret t.string :bio t.string :image_url t.string :web_url t.string :last_tid t.timestamps end end def self.down drop_table :authentications end end
$ rake db:migrate (in /rails/jhoge) == DeviseCreateUsers: migrating ============================================== -- create_table(:users) -> 0.0337s == DeviseCreateUsers: migrated (0.0340s) ===================================== $ rake db:migrate == CreateAuthentications: migrating ========================================== -- create_table(:authentications) -> 0.0156s == CreateAuthentications: migrated (0.0157s) =================================
・ログイン処理とルーティングを追加
authenticationsコントローラを作成
class AuthenticationsController < ApplicationController def create omniauth = request.env['omniauth.auth'] @authentication = Authentication.find_by_provider_and_uid(omniauth['provider'], omniauth['uid']) if @authentication #sign_in_and_redirect @user, :event => :authentication sign_in(:user, @authentication.user) set_token_to_session(current_user) redirect_to user_root_url #elsif current_user # 既にログインしてるけど、facebookとかの権限も追加するとき # current_user.authentications.create!(:provider => omniauth['provider'], :uid => omniauth['uid'], # :oauth_token => omniauth['credentials']['token'], # :oauth_token_secret => omniauth['credentials']['secret']) # redirect_to authentications_url else # 新規ユーザのとき data = omniauth['extra']['user_hash'] @user = User.new @user.authentications.build(:provider => omniauth['provider'], :uid => omniauth['uid'], :access_token => omniauth['credentials']['token'], :access_secret => omniauth['credentials']['secret'], :screen_name => data['screen_name'], :bio => data['description'], :image_url => data['profile_image_url'], :web_url => data['url'], :last_tid => nil) # data['id']で取れるけど初期値はnil @user.save! sign_in(:user, @user) redirect_to user_root_url end end end
route.rbに以下を追記
devise_for :users, :controllers => { :sessions => "users/sessions", :authentications=>"authentications" } do get '/users/sign_out', :to => 'devise/sessions#destroy', :as => :destroy_user_session get '/sessions/new', :to => 'index#index', :as => :new_user_session end match '/users/auth/:provider/callback' => 'authentications#create'
・ログイン用のリンクをviewの適当な場所に
<%= link_to image_tag('twitter_btn.png'), "/users/auth/twitter" %>
・ログインリンクをクリックしてUsersとAuthenticationsにレコードができてることを確認しておしまい