はじめに
では、いよいよ実装していきます!今回は、今チームで作っているフリマアプリに実装していきます。
Gemを導入
OmniAuthの脆弱性に対応するためのGemを導入します。
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編)を見てください!)
export FACEBOOK_CLIENT_ID='メモしたアプリID'
export FACEBOOK_CLIENT_SECRET='メモしたapp secret'
export GOOGLE_CLIENT_ID='メモしたクライアントID'
export GOOGLE_CLIENT_SECRET='メモしたクライアントシークレット'
変更後は$ source ~/.bash_profileを実行します。
環境変数が設定できたら、アプリ側にそれを読み込む記述を加えます。
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を使うためのオプションとアソシエーションを追記します。
以下の()の部分を追記しました。
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)
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認証を実装するためメソッドの実装
まずは、基本の動きをコントローラに記述していきます。
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メソッドの中身を作ります。
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側に以下の記述を追記します。
追記した箇所は()の中です。
.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">
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で登録するを押すと、名前とメールアドレスが自動で入ります。
今回は、プライバシーの関係で〇〇で表現しています。(笑)


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