deviseによるFacebook / Twitter 認証 -Rails奮闘記②-

本記事の紹介


 本記事は、私がRuby on Rail(Rails, RoR)を用いたWebアプリケーションを作る過程を示したものです。 Railsの勉強も兼ねているため、間違いなどもあった場合はご指摘いただけると大変嬉しいです!

 Devise を用いた基本的なユーザ認証の作成までは、過去記事を参照。

farma-11.hatenablog.com

deviseによるOAuth 認証


Dotenvによる環境変数の管理

 Gem: Dotenvを導入することでGitのリポジトリには含めずに外部APIの情報を環境変数として扱う。

1. Dotenvをインストール

# Gemfile
gem 'dotenv-rails', require: 'dotenv/rails-now'
$ bundle install --path vendor/bundle

2. .envファイルを作成

# .env
FB_APP_ID="[FacebookのアプリID]"
FB_APP_SECRET="[Facebookのapp secret]"
TW_APP_KEY="[TwitterのAPI key]"
TW_APP_SECRET="[TwitterのAPI secret]"

3. コンソールを起動して、呼び出せるか確認

$ bundle exec rails c
Running via Spring preloader in process 11075
Loading development environment (Rails 5.1.4)
irb(main):001:0> Dotenv.load
=> {"FB_APP_ID"=>"[FacebookのアプリID]", "FB_APP_SECRET"=>"[Facebookのapp secret]", "TW_APP_KEY"=>"[TwitterのAPI key]", "TW_APP_SECRET"=>"[TwitterのAPI secret]"}
irb(main):002:0> quit

4. .gitignore.envを追加

/.env

Facebook / Twitter 認証の実装

5. Gemfileの編集

# Gemfile
gem 'omniauth-facebook'
gem 'omniauth-twitter'

6. インストール

$ bundle install --path vendor/bundle

7. OAuthで取得するproviderとuidを保持するために、Userモデルにカラムを追加

$ rails g migration add_columns_to_users provider uid
$ rake db:migrate

8. Deviseにて取得したプロバイダの各キーを設定
 Dotenvにて管理されている各キーをENV['HOSTNAME']のように利用できる。

# config/initializers/devise.rb
# (省略)
  # ==> OmniAuth
  # Add a new OmniAuth provider. Check the wiki for more information on setting
  # up on your models and hooks.
  # config.omniauth :github, 'APP_ID', 'APP_SECRET', scope: 'user,public_repo'
  config.omniauth :facebook, ENV['FB_APP_ID'], ENV['FB_APP_SECRET']
  config.omniauth :twitter, ENV['TW_APP_KEY'], ENV['TW_APP_SECRET']
# (省略)

9. Userモデルにモジュールを追加

# app/models/user.rb
class User < ApplicationRecord
  # Include default devise modules. Others available are:
  # :confirmable, :lockable, :timeoutable and :omniauthable
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :trackable, :validatable, :omniauthable
  # (省略)
}

10. Userモデルにfindメソッドを実装

# app/models/user.rb
class User < ApplicationRecord
  # (省略)
  def self.find_for_oauth(auth)
    user = User.where(uid: auth.uid, provider: auth.provider).first

    unless user
      user = User.create(
        uid:      auth.uid,
        provider: auth.provider,
        email:    User.dummy_email(auth),
        password: Devise.friendly_token[0, 20]
      )
    end

    user
  end

  private

  def self.dummy_email(auth)
    "#{auth.uid}-#{auth.provider}@example.com"
  end
end

11. ディレクトリを作成

$ mkdir app/controllers/users

12. Userコントローラにコールバック処理を実装

# app/controllers/users/omniauth_callbacks_controller.rb
class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController
  def facebook
    callback_from :facebook
  end

  def twitter
    callback_from :twitter
  end

  private

  def callback_from(provider)
    provider = provider.to_s

    @user = User.find_for_oauth(request.env['omniauth.auth'])

    if @user.persisted?
      flash[:notice] = I18n.t('devise.omniauth_callbacks.success', kind: provider.capitalize)
      sign_in_and_redirect @user, event: :authentication
    else
      session["devise.#{provider}_data"] = request.env['omniauth.auth']
      redirect_to new_user_registration_url
    end
  end
end

13. ルーティング処理

# config/routes.rb
Rails.application.routes.draw do
  devise_for :users, controllers: { omniauth_callbacks: 'users/omniauth_callbacks' }

  # (省略)
end

まとめ


 本記事は、以下の記事を参考にまとめました。