LoginSignup
1
0

More than 1 year has passed since last update.

【Rails6 × React】devise_auth_tokenでのSNS認証時に初回ログインの場合のみ特定の処理を促す

Last updated at Posted at 2021-05-02

環境

API

  • Rails6.0

フロント

  • React

目的

Omniauthを用いたSNS認証でのユーザー登録で初回ログイン時にSNS上のアカウント情報から一部変更したり追加情報の入力を促したりしたい。
devise_auth_tokenを用いているが、deviseでも基本は同じように設計していいと思う。

実装方法

①usersテーブルにTrackable系のカラムを追加する

class AddColumnsToUsers < ActiveRecord::Migration[6.0]
  def change
    add_column :users, :sign_in_count, :integer, default: 0, null: false
    add_column :users, :current_sign_in_at, :datetime
    add_column :users, :last_sign_in_at, :datetime
    add_column :users, :current_sign_in_ip, :string
    add_column :users, :last_sign_in_ip, :string
  end
end

これらのカラムを追加。上から順に

  • サインイン回数
  • 現在のログインをした日時
  • 最後にログインした日時
  • 現在のログイン元IPアドレス
  • 最後のログインしたときのログイン元IPアドレス

の情報を持っている

②models/user.rbにてtrackableを設定

class User < ActiveRecord::Base
  # Include default devise modules. Others available are:
  # :confirmable, :lockable, :timeoutable, :trackable and :omniauthable
  devise :database_authenticatable, :registerable,  :trackable, #←これ
         :recoverable, :rememberable, :validatable, :omniauthable, omniauth_providers: [:twitter]

モデルにも設定が必要。逆に言うとこれだけでサインイン時に勝手にカラムに値が入っていく。

③omniauthでの認証時にユーザーが初回ログインかどうかを判定する

def render_data_or_redirect(message, data, user_data = {})
  # 初回ログイン時にはcookieに情報をセット。Oauth認証後ユーザー情報の編集ページに飛ばす
  cookies[:first_session] = { value: true, path: root_path, expres: 10.minutes }  if @resource.sign_in_count == 0 

devise_auth_tokenではomniauth_callbacksコントローラーでユーザーが認証できた場合に
render_data_or_redirectメソッドが呼ばれる。このメソッドでアプリ側のページに返す直前で
保存したユーザーのsign_in_countが0の場合にCookie上にfirst_sessionという値を仕込む。期限は10分とかにしとく

④フロント側でCookieから初回ログインのtmpデータを取得する

class App extends React.Component {

  componentDidMount() {
    const cookies = new Cookies();
    // ユーザー認証が済んでいる場合
    if (authToken) { 
      if (cookies.get('first_session')) {
        // 実際にはユーザー情報編集ページに飛ばす処理を入れる。次のブランチで
        alert('初回ログイン')
      }
      // 中略
      return authToken
    } else {
      return null
    }
  }

今回はルートコンポーネントのAppでログイン済みかどうかの判定をするので、
そこにcookieの中にfirst_sessionが存在しているかどうかの判定を行う条件式を実装。
なお、Cookieを読み込むライブラリとしては事前にuniversal-cookieを導入している。

npm install universal-cookie

⑤2回目以降のログイン時にCookieのtmpデータを削除する

tmpデータの有効期限が10分とかにしてるので、10分以内に2回ログインされることも想定して2回目以降のログインでは
Cookieのデータを削除するようにした。

# 2回目以降のログイン時にはfirst_sessionのクッキーデータを削除
cookies.delete(:first_session, path: root_path) if cookies[:first_session]

挙動

ここまでの流れで挙動は以下のようになる。
recommends-12-1.gif

感想

思ったよりかんたんにできた。
Trackable系のカラムちゃんと使ったことなかったのでこういう使い方ができるのか、と感動した。
Cookieを使って条件分岐しているのでセキュリティ的にどうなの?とかはあるけど一旦置いておく。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0