Help us understand the problem. What is going on with this article?

初心者でも簡単!SNS認証を実装(いざ実装編)

 はじめに

では、いよいよ実装していきます!今回は、今チームで作っているフリマアプリに実装していきます。

 Gemを導入

OmniAuthの脆弱性に対応するためのGemを導入します。

Gemfile
gem 'omniauth-facebook'
gem 'omniauth-google-oauth2'
gem "omniauth-rails_csrf_protection"
ターミナル
bundle install

FacebookとGoogleで使用するAPIキーを環境変数に設定していきます。
前回取得した、API側の設定でメモしたAPP_IDとAPP_SECRETを準備し、$ vim ~/.bash_profileを実行し、以下の内容を追記します。(まだ、APIキーを取得していない場合は、SNS認証を実装(Google編)かSNS認証を実装((Faceboook編)を見てください!)

~/.bash_profile
export FACEBOOK_CLIENT_ID='メモしたアプリID'
export FACEBOOK_CLIENT_SECRET='メモしたapp secret'
export GOOGLE_CLIENT_ID='メモしたクライアントID'
export GOOGLE_CLIENT_SECRET='メモしたクライアントシークレット'

変更後は$ source ~/.bash_profileを実行します。
環境変数が設定できたら、アプリ側にそれを読み込む記述を加えます。

config/initializers/devise.rb
config.omniauth :facebook,ENV['FACEBOOK_CLIENT_ID'],ENV['FACEBOOK_CLIENT_SECRET']
config.omniauth :google_oauth2,ENV['GOOGLE_CLIENT_ID'],ENV['GOOGLE_CLIENT_SECRET']

SNS認証に必要なモデル、コントローラの準備

次に、uidやproviderをはじめとする、SNS認証時の情報を保存するSnsCredentialモデルを作成します。この時に、Userモデルとのアソシエーションのために、外部キーとしてuser_idを持たせます。

ターミナル
$ rails g model sns_credential provider:string uid:string user:references
$ rails db:migrate

モデルにomniauthを使うためのオプションとアソシエーションを追記します。
以下の()の部分を追記しました。

models/user.rb
class User < ApplicationRecord
  # Include default devise modules. Others available are:
  # :confirmable, :lockable, :timeoutable, :trackable and :omniauthable
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :validatable, :omniauthable, omniauth_providers: [:facebook, :google_oauth2]

  has_one :parsonal_user, dependent: :delete
  has_many :sns_credentials
models/sns_credential.rb
class SnsCredential < ApplicationRecord
  # associations
  belongs_to :user, optional: true
end

続いてdeviseのコントローラをカスタマイズするためのコントローラを作成します。

ターミナル
$ rails g devise:controllers users

以下のようにdeviseのルーティングを変更します
変更した箇所は()の中です

ターミナル
 devise_for :users, controllers: {
    omniauth_callbacks: 'users/omniauth_callbacks',
    registrations: 'users/registrations',
    sessions: 'users/sessions'
    }

SNS認証を実装するためメソッドの実装

まずは、基本の動きをコントローラに記述していきます。

controllers/users/omniauth_callbacks_controller.rb
class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController
  def facebook
    authorization
  end

  def google_oauth2
    authorization
  end

  def failure
    redirect_to root_path
  end

  private
  def authorization
    sns_info = User.from_omniauth(request.env['omniauth.auth'])
    @user = sns_info[:user]

    if @user.persisted?
      sign_in_and_redirect @user, event: :authentication # this will throw if @user is not activated
    else
      @sns_id = sns_info[:sns].id
      render 'devise/registrations/new'
    end
  end

次に、User.from_omniauthメソッドの中身を作ります。

user.rb
  def self.from_omniauth(auth)
    sns = SnsCredential.where(provider: auth.provider, uid: auth.uid).first_or_create
    user = sns.user || User.where(email: auth.info.email,).first_or_initialize(
      nick_name: auth.info.name,
        email: auth.info.email
    )
    if user.persisted?
      sns.user = user
      sns.save
    end
    { user: user, sns: sns }
  end
end

最後にhaml側に以下の記述を追記します。
追記した箇所は()の中です。

views/devise/sessions/new.html.haml
.p-login-main
    .p-login-user
      .p-login-user__account
        %p アカウントをお持ちでない方はこちら
        = link_to signup_registration_path, class: "p-login-user__account--link" do
          新規会員登録
      .p-login-user__inner
        .p-login-user__inner--btn
          %button.facebook-login
            = fa_icon 'facebook-square'
            (= link_to 'Facebookでログイン', user_facebook_omniauth_authorize_path, method: :post)
          %button.google-login
            = fa_icon 'google'
            (= link_to 'Googleでログイン', user_google_oauth2_omniauth_authorize_path, method: :post)
<img width="1257" alt="スクリーンショット 2020-03-29 15.36.31.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/591360/4bc12249-3308-0bb8-d1d3-33227bd345e4.png">
<img width="1264" alt="スクリーンショット 2020-03-29 15.41.54.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/591360/c15faa04-b595-9df9-a64e-ccc87b0a1cd8.png">

views/users/new.html.haml
ruby:views/users/new.html.haml

         .p-reg-btn__mail
            = fa_icon 'envelope'
            = link_to 'メールアドレスで登録する', signup_registration_path, class: 'p-reg-btn__link'
          .p-reg-btn__facebook
            = fa_icon 'facebook-square'
            = link_to 'Facebookで登録する', user_facebook_omniauth_authorize_path, class: 'p-reg-btn__link', method: :post
          .p-reg-btn__google
            = fa_icon 'google'
            = link_to 'Googleで登録する', user_google_oauth2_omniauth_authorize_path, class: 'p-reg-btn__link--color', method: :post

ここまでです。
以下のようにfacebookまたはgoogleで登録するを押すと、名前とメールアドレスが自動で入ります。
今回は、プライバシーの関係で〇〇で表現しています。(笑)

スクリーンショット 2020-03-29 15.36.31.png

スクリーンショット 2020-03-29 15.41.54.png

次回はここで少し工夫したことをやっていきます。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away