LoginSignup
28
33

More than 5 years have passed since last update.

Ruby on Rails ~OmniAuthによるTwitter/FacebookのOAuth認証を実装(コードメモ)~事前に作成したDeviseによる認証と併用

Last updated at Posted at 2017-01-09

今回は、事前に作成したDeviseによる認証機能とは別に、TwitterやFacebookアカウントで認証できるように実装していきます。

1.gemの追加。

Gemfile

gem 'devise'
gem 'omniauth'
gem 'omniauth-twitter'
gem 'omniauth-facebook'
$ bundle install

2.UserモデルにOmniAuthで利用するカラムを追加。

$ bundle exec rails generate migration AddOmniauthColumnsToUsers provider uid name
db/migrate/...
class AddOmniauthColumnsToUsers < ActiveRecord::Migration
  def change
    add_column :users, :uid,      :string, null: false, default: ""
    add_column :users, :provider, :string, null: false, default: ""
    add_column :users, :name,     :string

    add_index :users, [:uid, :provider], unique: true
  end
end
$ bundle exec rake db:migrate

uid, provider, name の3つのカラムが追加されました。

3.OAuth認証に必要なキー・シークレットトークンを追記。

(1)Facebook の API Key

Home – Facebook開発者 で取得。https://developers.facebook.com/
ログイン → 右上の「Register Now」から developer 登録。
Facebook Developers の右上の「+新しいアプリを作成」。
・アプリ名:任意
・名前空間:任意
・カテゴリ:その他(任意)

と入力して、App ID, App Secret を取得。
アプリをFacebookに結合する方法を選択で、Facebookでログインが可能なウェブサイトに「http://localhost:3000」を入力。

(2)Twitter の API Key

Twitter Developers で取得。https://dev.twitter.com/
ログイン → 右上 My Applications → Create a new application
・Name:任意
・Description:任意
・Website:適当なURL(http://localhost:3000 だとNG)
・Callback URL:http://127.0.0.1:3000/auth/twitter/callback
http://localhost:3000 だとNG)

その後、Consumer key, Consumer secret を取得し、 key, secret を config/initializers/devise.rb に設定。
Settings で 「Allow this application to be used to Sign in with Twitter」にチェック。一回TwitterでOAuth認証を行うと、次回からは確認画面が省略される。

config/initializers/devise.rb
  # API key
  if Rails.env.production?     
    config.omniauth :facebook, "App ID", "App Secret"
    config.omniauth :twitter,  "Consumer key", "Consumer secret"
  else
    config.omniauth :facebook, "App ID", "App Secret"
    config.omniauth :twitter,  "Consumer key", "Consumer secret"
  end

4.Userモデルにomniauthableを追加。

app/models/user.rb
  devise :database_authenticatable, :omniauthable, :registerable,
         :recoverable, :rememberable, :trackable, :validatable, :confirmable

5.OAuthのcallback 用ルーティングを追加。

config/routes.rb
devise_for :users, :controllers => {
  :sessions      => "users/sessions",
  :registrations => "users/registrations",
  :passwords     => "users/passwords",
  :omniauth_callbacks => "users/omniauth_callbacks" 
}

6.Users::OmniauthCallbacksControllerを作成。

app/controllers/users/omniauth_callbacks_controller.rb
class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController
  def facebook
    # You need to implement the method below in your model (e.g. app/models/user.rb)
    @user = User.find_for_facebook_oauth(request.env["omniauth.auth"], current_user)

    if @user.persisted?
      set_flash_message(:notice, :success, :kind => "Facebook") if is_navigational_format?
      sign_in_and_redirect @user, :event => :authentication
    else
      session["devise.facebook_data"] = request.env["omniauth.auth"]
      redirect_to new_user_registration_url
    end
  end

  def twitter
    # You need to implement the method below in your model
    @user = User.find_for_twitter_oauth(request.env["omniauth.auth"], current_user)

    if @user.persisted?
      set_flash_message(:notice, :success, :kind => "Twitter") if is_navigational_format?
      sign_in_and_redirect @user, :event => :authentication
    else
      session["devise.twitter_data"] = request.env["omniauth.auth"].except("extra")
      redirect_to new_user_registration_url
    end
  end
end

※deviseのコントローラー作成は以下のとおり。

$ rails g devise:controllers users

以下のControllerが生成される。

confirmations_controller.rb
omniauth_callbacks_controller.rb
passwords_controller.rb
registrations_controller.rb
sessions_controller.rb
unlocks_controller.rb

7.通常サインアップ時の uid フィールド設定の実装。

app/controllers/users/registrations_controller.rb
class Users::RegistrationsController < Devise::RegistrationsController

  def build_resource(hash=nil)
    hash[:uid] = User.create_unique_string
    super
  end

end
app/models/user.rb
class User < ActiveRecord::Base
  # ・・・

  # 通常サインアップ時のuid用、Twitter OAuth認証時のemail用にuuidな文字列を生成
  def self.create_unique_string
    SecureRandom.uuid
  end

  # ・・・
end

8.OAuth 認証時の email フィールド設定の実装。

app/models/user.rb
  devise :database_authenticatable, :omniauthable, :registerable,
         :recoverable, :rememberable, :trackable, :validatable, :confirmable

  def self.find_for_facebook_oauth(auth, signed_in_resource=nil)
    user = User.where(:provider => auth.provider, :uid => auth.uid).first
    unless user
      user = User.create(name:     auth.extra.raw_info.name,
                         provider: auth.provider,
                         uid:      auth.uid,
                         email:    auth.info.email,
                         password: Devise.friendly_token[0,20]
                        )
    end
    user
  end

  def self.find_for_twitter_oauth(auth, signed_in_resource=nil)
    user = User.where(:provider => auth.provider, :uid => auth.uid).first
    unless user
      user = User.create(name:     auth.info.nickname,
                         provider: auth.provider,
                         uid:      auth.uid,
                         email:    User.create_unique_email,
                         password: Devise.friendly_token[0,20]
                        )
    end
    user
  end

  # 通常サインアップ時のuid用、Twitter OAuth認証時のemail用にuuidな文字列を生成
  def self.create_unique_string
    SecureRandom.uuid
  end

  # twitterではemailを取得できないので、適当に一意のemailを生成
  def self.create_unique_email
    User.create_unique_string + "@example.com"
  end

9ビューにOAuth認証用のログインへのリンクを表示。

app/views/layouts/application.html.erb
<%= link_to "Sign in with Facebook", user_omniauth_authorize_path(:facebook), :class => 'navbar-link' %>
<%= link_to "Sign in with Twitter",  user_omniauth_authorize_path(:twitter),  :class => 'navbar-link' %>

以上で終了です。

28
33
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
28
33