Ruby on Rails5 で devise と OmniAuth を活用して Facebook 認証を実装しよう! #rails #facebook

Facebook認証を利用して、Ruby on Rails5 アプリケーションにログインできるようにしたい思います。

devise + OmniAuth というGemを利用してFacebook認証を実装します。

Deviseとは

https://github.com/plataformatec/devise

Deviseは、Railsでログイン管理を簡単に行える便利なGemです。
新規登録時に認証メールを送信したり、ログイン・ログアウト機能も簡単に実装できます。

OmniAuthとは

OmniAuthは、簡単にWebアプリケーションのマルチプロバイダ認証を実装することができるGemです。
FacebookやTwitter等のSNS認証を実装する際に利用すると便利です。
それぞれに、Gemが公開されているので、今回は、Facebook用のGemをインストールをして実装していきたいと思います。

環境

Ruby on Rails 5.0.1

Facebookアプリケーションの作成

Facebook Developers でアプリケーションを作成します。

「製品を追加」を選択して、「Facebookログイン」の「スタート」ボタンをクリックします。

ひとまず、設定する箇所は「有効なOAuthリダイレクトURL」です。
認証するアプリケーションのURLを設定します。
「変更を保存」をクリックします。

Deviseのインストール

次に、Deviseのインストールと設定を行っていきます。

Gemfileに下記を追加します。

gem 'devise'

bundleインストールを行ないます。

$ bundle install --path vendor/bundle --jobs=4

deviseのファイルを生成します。

$ bundle exec rails g devise:install
Running via Spring preloader in process 39790
      create  config/initializers/devise.rb
      create  config/locales/devise.en.yml
===============================================================================

Some setup you must do manually if you haven't yet:

  1. Ensure you have defined default url options in your environments files. Here
     is an example of default_url_options appropriate for a development environment
     in config/environments/development.rb:

       config.action_mailer.default_url_options = { host: 'localhost', port: 3000 }

     In production, :host should be set to the actual host of your application.

  2. Ensure you have defined root_url to *something* in your config/routes.rb.
     For example:

       root to: "home#index"

  3. Ensure you have flash messages in app/views/layouts/application.html.erb.
     For example:

       <p class="notice"><%= notice %></p>
       <p class="alert"><%= alert %></p>

  4. You can copy Devise views (for customization) to your app by running:

       rails g devise:views

===============================================================================

こんな出力がされればOKです。

Deviseで出力されるメッセージを日本語化します。

英語版のymlファイルを、日本語版としてコピーします。

$ cp -p config/locales/devise.en.yml config/locales/devise.ja.yml

中のメッセージを日本語に置き換えます。

Userモデルを生成します。

$ bundle exec rails g devise user
Running via Spring preloader in process 13886
      invoke  active_record
      create    db/migrate/20170304210629_devise_create_users.rb
      create    app/models/user.rb
      invoke    rspec
      create      spec/models/user_spec.rb
      invoke      factory_girl
      create        spec/factories/users.rb
      insert    app/models/user.rb
       route  devise_for :users

マイグレーションの実行

$ bundle exec rake db:migrate

ログイン画面を表示します。

http://localhost:3000/users/sign_up

メールでのログイン認証画面が表示されればOKです。

認証機能の実装

Gemfileに追記します。

gem 'omniauth'
gem 'omniauth-facebook'

インストールします。

$ bundle install --path vendor/bundle --jobs=4

Userモデルに、カラムを追加します。

app/models/user.rb

bundle exec rails g migration AddColumnsToUsers uid:string provider:string

マイグレーションの実行

$ bundle exec rake db:migrate

Deviseの設定

Facebookアプリケーションの アプリIDapp secret を追記します。

config/initializers/devise.rb

Devise.setup do |config|
  ## 省略
  config.omniauth :facebook, ENV['APP_ID'], ENV['APP_SECRET']
end

Gitでソース管理したいので、直接 アプリIDapp secret を記載することは避けて、環境変数から呼び出せるようにします。

.evnに環境変数を設定

DotenvというGemを利用して環境変数を読み込んでいるのですが、導入手順はこちらで紹介しています。
RailsにDotenvを導入!環境変数を管理しよう!

Facebookアプリケーションの「設定->ベーシック」に記載されている、 アプリIDapp secret を、 .env に設定します。

APP_ID="xxxxxxxxxxxxxxxx"
APP_SECRET="xxxxxxxxxxxxxxxxxxxxxxxxxxx"

:omniauthable を追記します。

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
end

Userモデルにメソッドを追加します。

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

  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

コールバック処理を実装

ディレクトリを作成します。

mkdir app/controllers/users

コールバックの処理を実装します。

app/controllers/users/omniauth_callbacks_controller.rb

class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController
  def facebook
    callback_from :facebook
  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

ルーティングの設定

config/routes.rb

Rails.application.routes.draw do
  # コールバック用URL
  devise_for :users, controllers: { omniauth_callbacks: 'users/omniauth_callbacks' }

 # ログアウト用
  devise_scope :user do
    delete :sign_out, to: 'devise/sessions#destroy', as: :destroy_user_session
  end
end

ログイン画面を表示

http://localhost:3000/users/sign_up

「Sign in with Facebook」というリンクが表示されていたらOKです。

他のviewに記載したい場合は、下記をviewに記述します。

user_omniauth_authorize_path(:facebook)

URLを読み込めません:このURLのドメインはアプリノドメインに含まれていません。
このURLを読み込むには、アプリ設定のアプリドメインにすべてのドメインとサブドメインを追記してください。

リンクをクリックして、このようなメッセージが表示されたらFacebookアプリケーションの設定「有効なOAuthリダイレクトURI」が設定できているか見直してみてください。

「http://localhost:3000」を追加しておくとローカルでも認証が行えます。

最後に、私はヘッダーに、ログイン/ログアウトのURLを実装しました。

app/views/layouts/application.html.erb

<!DOCTYPE html>
<html>
  <head>
    <title>Bgclub</title>
    <%= csrf_meta_tags %>

    <%= stylesheet_link_tag    'application', media: 'all', 'data-turbolinks-track': 'reload' %>
    <%= javascript_include_tag 'application', 'data-turbolinks-track': 'reload' %>
  </head>

  <body>
  <div>
    <% if user_signed_in? %>
        <%= link_to 'Sign out', destroy_user_session_path, method: :delete %>
    <% else %>
        <%= link_to 'Sign in', user_facebook_omniauth_authorize_path %>
    <% end %>
  </div>
    <%= yield %>
  </body>
</html>

以上で、Facebook認証の実装は完了とします。
今回は、Devise+OmniAuthでユーザ認証を実装する手順を参考にさせていただきました。
ありがとうございました!


Ruby on Rails が学べるオンライン講座

オンライン講座なら、好きな場所で好きな時間に学習できます。Ruby on Rails も学ぶことができるので、ぜひ、活用しましょう。

Udemy(ユーデミー)

オンライン動画学習サイトで、Ruby on Rails講座やRuby講座もあります。頻繁に講座のバーゲンセールスが実施されているので、価格をチェックしましょう!一度、購入した動画は繰り返し使えますので何度でも学習可!
世界最大級のオンライン学習サイトUdemy


CodeCamp(コードキャンプ)

現役のRubyエンジニアによる個別指導で、Webサイト制作を基礎から習得できます。無料体験レッスンが受講できるので、気軽に受講体験ができます。
Ruby と Ruby on Railsマスターコース