文系エンジニアのブログ

文系20代後半からWEB系エンジニアを目指す

【rails】FacebookとgoogleのAPIをつかったログインと新規登録機能の実装

今回はrailsアプリでfacebookgoogleAPIを使ったログインと新規登録の方法を記事にします。
またusersテーブルとsns認証用のテーブルは別に保存する事が多いと思うので複数テーブルで保存する方法で記載します。

実装手順に移る前の準備すること

・deviseのgemを使った通常のログインや新規登録機能の実装はできていること
facebookgoogleAPIキーの取得が終わっていること
・「user_id」、「uid」、「provider」カラムがあるSNS認証用のテーブルとdeviseを使った場合のusersテーブルが作成されていること
(今回の場合は「sns_credential」テーブルというのを作りました)

実装手順

gemインストール

Gemfileに以下のgemを記述してbundle installします。

gem 'omniauth'
gem 'omniauth-facebook'
gem 'omniauth-google-oauth2'

APIキーをコードに記載

config/insitializers/devise.rbを以下のように編集

Devise.setup do |config|
  config.omniauth :facebook, 'AppIDをここにいれる', 'AppSecretIDをここに入れる'
  config.omniauth :google_oauth2,  'クライアントIDをここにいれる', 'クライアントシークレットをここに入れる'
end

deviseにomniauthableの機能を拡張させる

app/model/user.rbのファイルの末尾に

omniauthable, omniauth_providers
%i[facebook google_oauth2]を追加
 devise :database_authenticatable, :registerable,
        :recoverable, :rememberable, :validatable,
        :omniauthable, omniauth_providers: %i[facebook google_oauth2]

userモデルにfindメソッドを追加する

app/model/user.rbに以下のようにfind_for_oauthメソッドを記述します

class User < ActiveRecord::Base
//中略//

  def self.find_for_oauth(auth)
    sns = SnsCredential.where(uid: auth.uid, provider: auth.provider).first
    unless sns
      @user = User.create(
      email:    auth.info.email,
      password: Devise.friendly_token[0,20]
      )
      sns = SnsCredential.create(
      user_id: @user.id,
      uid: auth.uid,
      provider: auth.provider
      )
   end
    sns
    @user
  end

 end

コールバック処理の実装

app/controller以下に、usersフォルダを作成します。
そのusersフォルダに、
omniauth_callbacks_controller.rb
というコントローラーのファイルを作ります。
ファイルの中身は下記のように記述します。

class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController
  def facebook
    callback_from :facebook
  end

  def google_oauth2
    callback_from :google
  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

ルーティングの設定

コールバック用にルーティングを設定します。

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

実際のログイン画面を確認する

http://localhost:3000/users/sign_inにアクセスして確認してみます。
f:id:Mchinta:20190104002942p:plain

例えば
「 Sign in with GoogleOauth2 」のボタンをクリックしてみて、以下のような画面が出てくれば成功です。
f:id:Mchinta:20190522002417p:plain

参考までに

SNS認証用のテーブルについて

こんな感じでカラムは作成しています

①ターミナルでrails g model sns_credential
マイグレーションファイルを以下のように記述してrake db:migrate

class CreateSnsCredentials < ActiveRecord::Migration
  def change
    create_table :sns_credentials do |t|
      t.integer :user_id, foreign_key: true
      t.string  :uid
      t.string  :provider
      t.timestamps
    end
  end
end

③アソシエーションを組みます
まずはuser.rbを編集します。
dependent: :destroyはuserが削除された時に一緒にsnsのレコードも削除されるようにする記述です。

class User < ActiveRecord::Base
  has_many :sns_credentials, dependent: :destroy
end

次にsns_credential.rbを編集します。

class SnsCredential < ActiveRecord::Base
  belongs_to :user
end