【Rails5】SNS認証でメールアドレス介さず登録・ログインできるようにする実装

SNS認証で秒速ログイン機能が実装したい!

質問箱を筆頭にワラワラ出てくる人気サービスに必ずと言って良いほど実装されているSNSログイン機能。

ろっこ

ユーザーが1回タップするだけで登録できるのすぎる……

と思い、実装していきたいなぁなんて考えていたのですがなかなか情報にたどり着かず。

どの記事もSNS認証 + メールアドレスなどの登録といった感じなんですよね。

と言うわけでネットサーフィンをしまくって何とか形にはなりました。



 
参考にさせてもらった記事
[*Rails*] deviseの使い方(rails5版)
【開発メモ】RailsアプリにTwitterログイン認証機能を実装する方法
【Rails】deviseのTwitter認証で「Unauthorized 403 Forbidden」が出てしまう場合の対処法
 

次回以降のためにもメモしておきます。良かったら使ってください
 

環境

 
Rails 5.2.1
Ruby 2.5.1
devise 4.2.0
omniauth-oauth 1.1.0
omniauth-twitter 1.4.0
 

SNS認証で登録作業を1秒で済ませる実装

1、新規プロジェクトの作成

$ rails new twitter_login
$ cd twitter_login

名前は適当にtwitter_loginにしちゃいました:)

 

2、『devise』と『omniauth-twitter』の追加

Gemfile
(略)

gem 'devise'
gem 'omniauth-twitter'

(略)

追記したらbundle installしましょう!

$ bundle

 

3-1、『devise』をインストールする

$ rails g devise:install

すると以下の文がズラーと表示されます

  ①. 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.

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

       root to: "home#index"

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

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

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

       rails g devise:views

①〜④の指示を順にこなしていきます!

3-2、①default_url_optionsの設定

config.action_mailer.default_url_options = { host: ‘localhost’, port: 3000 }を環境ファイルに追記します。

config/environments/development.rb
(略)

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

  end

3-3、②root_urlの設定

まだ何もページを作っていない状態なのでrails generateします。

$ rails g controller Pages index show

これでindexとshowページが作成されたのでroutes.rbにてroot_urlを設定します。

config/routes.rb<br>
Rails.application.routes.draw do

  root 'pages#index'
  get 'pages/show'

  end

3-4、③flash messagesの追記

指定がある通り、applcation.html.erbにフラッシュメッセージを追記します。

app/views/layouts/application.html.erb
(略)

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

  <%= yield %>

 </body>
(略)

3-5、④copy Devise viewsの実行

$ rails g devise:views

実行すると

create app/views/devise/shared

こんな感じでファイルが20個前後作成されるかと思います

 

4-1、Userモデルの作成

$ rails g devise User

を実行し、Userモデルを作ります。

4-2、Userモデルの編集

app/models/user.rb
class User < ApplicationRecord
 devise :database_authenticatable, :registerable,
           :recoverable, :rememberable, :trackable,
           :validatable,:lockable, :timeoutable, :omniauthable,
           omniauth_providers: [:twitter]

    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],
           image: auth.info.image,
           name: auth.info.name,
           nickname: auth.info.nickname,
          )
        end
 
       user
     end
 
  private
 
  def self.dummy_email(auth)
    "#{auth.uid}-#{auth.provider}@example.com"
  end


end

 

5、マイグレーションファイルの編集

コメントアウト状態なので、シャープを外していきます

db/migrate/20181113120136_devise_create_users.rb
class DeviseCreateUsers < ActiveRecord::Migration[5.2]
  def change
    create_table :users do |t|
      ## Database authenticatable
      t.string :email,              null: false, default: ""
      t.string :encrypted_password, null: false, default: ""

      ## Recoverable
      t.string   :reset_password_token
      t.datetime :reset_password_sent_at

      ## Rememberable
      t.datetime :remember_created_at

      ## Trackable
      t.integer  :sign_in_count, default: 0, null: false
      t.datetime :current_sign_in_at
      t.datetime :last_sign_in_at
      t.string   :current_sign_in_ip
      t.string   :last_sign_in_ip

      ## Confirmable
      t.string   :confirmation_token
      t.datetime :confirmed_at
      t.datetime :confirmation_sent_at
      t.string   :unconfirmed_email # Only if using reconfirmable

      ## Lockable
      t.integer  :failed_attempts, default: 0, null: false # Only if lock strategy is :failed_attempts
      t.string   :unlock_token # Only if unlock strategy is :email or :both
      t.datetime :locked_at
      t.timestamps null: false
    end

    add_index :users, :email,                unique: true
    add_index :users, :reset_password_token, unique: true
    add_index :users, :confirmation_token,   unique: true
    add_index :users, :unlock_token,         unique: true
  end
end

これで有効化されました:)

 

6、マイグレーションファイルの追加

$ rails g migration add_columns_to_users uid:string provider:string name:string nickname:string location:string image:string

これでマイグレーションファイルが追加されたので、以下を実行。

$ rake db:migrate

 

7、TwitterAPIのKeyを入力する

クリックで拡大

TwitterAPIを開き、devise.rbにkey情報を入力します

config/initializer/devise.rb
Devise.setup do |config|
  config.omniauth :twitter, 'ここにAPI key', 'ここにAPI secret'
end
Twitter Developer側のコールバックの設定

Twitter APIの仕様変更に伴い、Twitter Developer側でのコールバックが必要になりました。

多くのDevise系の記事ではコールバックは指定しなくて良いと書いてありますが、コールバックを指定しましょう

クリックで拡大

 

$ rails routes

を実行後、コールバックのURLを探し、TwitterDeveloperにて設定しましょう

クリックで拡大

8、コールバックの設定

$ rails g controller omniauth_callbacks

 

9、コントローラーの編集

app/controllers/omniauth_callbacks_controller.rb
class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController

  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

 

10、ルーティングの追記

config/routes.rb
Rails.application.routes.draw do
    devise_for :users, controllers: { :omniauth_callbacks => "omniauth_callbacks" }
end

11、viewの調整

app/views/pages/index.html.erb
	<%if user_signed_in? %>
		<h2><%=current_user.name%>さんのページ</h2>
		<a href="https://twitter.com/<%=current_user.nickname%>">Twitterで見る</a>
			<br>
		<img src="<%=current_user.image%>">
			<br>
		<%= link_to "ログアウト", destroy_user_session_path, method: :delete %>
	<%else%>
          <%= link_to "ログイン", new_user_session_path %>
	<%end%>

 

完成

適当にCSSをいじって良い感じにしてみてください。