May 1, 2012

RailsでOmniAuthを使ってTwitter認証する

準備


  • Twitter Developer登録
  • Callback urlはローカルで試すために http://0.0.0.0:3000/auth/twitter/callback と設定

Gemfileに以下を追加


gem 'omniauth'
gem 'omniauth-twitter'

bundle install


OmniAuthの組み込み

% cat config/initializers/omniauth.rb
Rails.application.config.middleware.use OmniAuth::Builder do
  provider :twitter, '[Consumer key]', '[Consumer secret]'
end
[Consumer key]と[Consumer secret]は上で取得したものを設定

スキーマ参照してモデルの設定

https://github.com/intridea/omniauth/wiki/Auth-Hash-Schema

rails g model user provider:string uid:string name:string screen_name:string
rake db:migrate

% cat app/models/user.rb 
class User < ActiveRecord::Base
  def self.create_with_omniauth(auth)
    create! do |user|
      user.provider = auth['provider']
      user.uid = auth['uid']
      user.name = auth['info']['name']
      user.screen_name = auth['info']['nickname']
    end
  end
end

セッション(ログイン・ログアウト)の設定

rails g controller sessions
% cat app/controllers/sessions_controller.rb
class SessionsController < ApplicationController
  def callback
    auth = request.env["omniauth.auth"]
    user = User.find_by_provider_and_uid(auth["provider"], auth["uid"]) || User.create_with_omniauth(auth)
    session[:user_id] = user.id
    redirect_to root_path, :notice => "Logged in"
  end

  def destroy
    session[:user_id] = nil
    redirect_to root_path, :notice => "Logged out"
  end
end

Welcomeページの設定

rails g controller welcome index
% cat app/views/layouts/application.html.erb
<!DOCTYPE html>
<html>
    <head>
        <title>Omniauth</title>
        <%= stylesheet_link_tag    "application", :media => "all" %>
        <%= javascript_include_tag "application" %>
        <%= csrf_meta_tags %>
    </head>
    <body>
        <% if current_user %>
            <%= current_user.name %>
            <%= current_user.screen_name %>
            <%= link_to 'Log out', logout_path %>
        <% else %>
            <%= link_to 'Log in', '/auth/twitter' %>
        <% end %>
        <%= yield %>

    </body>
</html>

アプリケーションコントローラ

% cat app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
  protect_from_forgery

  def login_required
    if session[:user_id]
      @current_user = User.find(session[:user_id])
    else
      redirect_to root_path
    end
  end

  helper_method :current_user

  private
  def current_user
    @current_user ||= User.find(session[:user_id]) if session[:user_id]
  end
end

ルーティングの設定

% cat config/routes.rb
Omniauth::Application.routes.draw do
  get "welcome/index"
  match "/auth/:provider/callback" => "sessions#callback"
  match "/logout" => "sessions#destroy", :as => :logout
  root :to => 'welcome#index'
end

参考