Rails3 deviseによるtwitter認証
【前回】Rails3 認証エンジン「devise」 - スマートフォンアプリ開発会社のエンジニアブログ
こんにちはRails研究員の[twitter:@gc_locks]です。
今回は前回の続き、deviseにoauth認証を乗せます。
https://github.com/plataformatec/devise/wiki/OmniAuth:-Overview
このページを参考にして、ガリガリ実装します。
Gemfile に以下を追加して、bundle install
gem "oa-oauth", :require => "omniauth/oauth"
次に、config/initializers/devise.rb にtwitterのアプリケーションの管理コードを追加。
管理コードは https://dev.twitter.com/apps から取得しましょう。
Devise.setup do |config| (略) config.omniauth :twitter, "APP_ID", "APP_SECRET" end
認証をするモデルを作ります。
TwitterAuthというモデルにします。
$ rails g devise TwitterAuth
このままではベーシック認証のモデルになってしまうので、modelとmigrationを変更を加えましょう。
著者の好みで trackableは残します。
app/model/twitter_auth.rb
class TwitterAuth < ActiveRecord::Base devise :trackable, :omniauthable end
db/migrate/..._devise_create_twitter_auths.rb
class DeviseCreateTwitterAuths < ActiveRecord::Migration def self.up create_table(:twitter_auths) do |t| t.trackable t.timestamps end end def self.down drop_table :twitter_auths end end
このままではtwitterアカウントの識別子もありませんし、
twitterに侵入して遊べないので、識別子とユーザ側の二つのトークンを加えましょう。
$ rails g migration AddTokenToTwitterAuth uid:integer screen_name:string access_token:string access_secret:string
$ rake db:migrate
これで準備完了したので、routes を見てみましょう。
twitter_auth_omniauth_callback /twitter_auths/auth/:action/callback(.:format) {:action=>/twitter/, :controller=>"devise/omniauth_callbacks"}
controller が "devise/omniauth_callbacks" だと不便なので、routesを書き換えましょう
config/routes.rb
devise_for :twitter_auths, :controllers => {:omniauth_callbacks => "omniauth_callbacks"}$ rake routes
twitter_auth_omniauth_callback /twitter_auths/auth/:action/callback(.:format) {:action=>/twitter/, :controller=>"omniauth_callbacks"}
これで、twitter_auth_omniauth_authorize_path にアクセスすると twitterの認証画面にリダイレクトされます。
そこでの認証に成功したら、 :controller => "omniauth_callbacks", :action => "twitter" にコールバックされます。
$ rails g controller OmniauthCallbacks twitter
app/controller/omniauth_callbacks_controller.rb
class OmniauthCallbacksController < ApplicationController def twitter # You need to implement the method below in your model @user = TwitterAuth.find_for_twitter_auth_oauth(env["omniauth.auth"], nil) if @user.persisted? flash[:notice] = I18n.t "devise.omniauth_callbacks.success", :kind => "TwitterAuth" sign_in_and_redirect @user, :event => :authentication else session["devise.twitter_data"] = env["omniauth.auth"] redirect_to root_path #new_user_registration_url end end endapp/model/twitter_auth.rb
class TwitterAuth < ActiveRecord::Base devise :trackable, :omniauthable def self.find_for_twitter_auth_oauth(access_token, signed_in_resource=nil) data = access_token['extra']['user_hash'] if user = TwitterAuth.find_by_uid(access_token['uid'].to_i) user else # Create a user with a stub password. TwitterAuth.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
これでサーバを起動して、http://localhost:3000/twitter_auths/auth/twitter にアクセスしてユーザが追加出来れば成功です。