Rails の devise_token_auth と Next.js でログイン処理

rails

Rails で ログインAPI を作るなら、devise_token_authがおすすめです。

ほとんどの人は devise で user 管理をしているでしょうから、それを拡張する形で導入できます。

Next.js とかからも利用できます。

まず、以下を実行します。

% bundle exec rails g devise_token_auth:install User auth

すると、以下のようなルーティングが自動生成されます。

config/routes.rb

Rails.application.routes.draw do
  mount_devise_token_auth_for 'User', at: 'auth'
end

このルートの実態は以下のようになります。

/auth/sign_in がサインイン
/auth がサインアップ
て感じですね。

% bundle exec rails routes
GET    /auth/sign_in(.:format)
POST   /auth/sign_in(.:format)
DELETE /auth/sign_out(.:format)
GET    /auth/password/new(.:format)
GET    /auth/password/edit(.:format)
PATCH  /auth/password(.:format)
PUT    /auth/password(.:format)
POST   /auth/password(.:format)
GET    /auth/cancel(.:format)
GET    /auth/sign_up(.:format)
GET    /auth/edit(.:format)
PATCH  /auth(.:format)
PUT    /auth(.:format)
DELETE /auth(.:format)
POST   /auth(.:format)
GET    /auth/validate_token(.:format)

devise_token_auth は以下のカラムを利用してそうです。

provider
uid
token

リクエストごとに、以下の httpヘッダーが返ってくるようです。

HTTP/1.1 200 OK
access-token: xzTWhTURMmPdDjaKB2R9gw
token-type: Bearer
client: S2T6zY0aDB6VBXYVMdpjbg
expiry: 1558871460
uid: example@example.com

以下のように説明されています。

access-token
これはリクエスト毎にユーザーのパスワードとして提供されます。この値のハッシュ・バージョンは、後で比較するためにデータベースに保管されます。この値はリクエスト毎に変更されるべきです。

client
これにより異なるクライアント上で複数の同時セッションを管理することができます。たとえば、携帯電話とラップトップの両方で同時に認証を受けたい場合があります。

expiry
現在のセッションが失効になる日にちです。これは、クライアントがAPIリクエストを必要とせずに期限切れのトークンを無効にするために使用できます。

uid
ユーザーを識別するために使用される一意の値。アクセストークンでユーザーのDBを検索すると、APIがtiming attacksを受けやすくなるため、これが必要です。

以下の設定がいじれます。

change_headers_on_each_request ですが、これは false にしておいた方がよさそうです。
trueにしたままだと、ログインセッション一本だけしかできなそうなので、不便じゃないでしょうか。
つまり、同一ブラウザの複数タブで作業してると、他のが強制ログアウトされてしまいそう。
もちろん、セキュリティ度をあげたいなら、良いです。
上記 header の client の項目があるので、複数ブラウザがokならばよい、という意味ならこれを true にしても問題なさそう。

デフォルトではそれぞれのリクエストの後にaccess-tokenヘッダが変わります。
クライアントは変更されるトークンを追跡し続ける責務があります。
ng-token-authとj-tokerの両方でこれが実行されます。
これは安全ですが、管理が難しいです。
この設定をfalseにすると、リクエスト毎にトークンヘッダが変更されなくなります。

config/initializers/devise_token_auth.rb

DeviseTokenAuth.setup do |config|
  # リクエストごとにトークンを更新するか
  # 扱いやすいようにFalseにします
  config.change_headers_on_each_request = false

  # トークンの有効期間
  # デフォルトでは2週間です
  config.token_lifespan = 2.weeks

  # ヘッダーの名前対応
  config.headers_names = {:'access-token' => 'access-token',
                          :'client' => 'client',
                          :'expiry' => 'expiry',
                          :'uid' => 'uid',
                          :'token-type' => 'token-type' }
end
ソースコード

devise – rubygems.org
https://rubygems.org/gems/devise

heartcombo/devise
https://github.com/heartcombo/devise

devise_token_auth – rubygems.org
https://rubygems.org/gems/devise_token_auth

lynndylanhurley/devise_token_auth
https://github.com/lynndylanhurley/devise_token_auth

参考記事

【翻訳】devise-auth-token公式ドキュメント – 2018年8月11日
https://sainu.hatenablog.jp/entry/2018/08/11/194319

【Rails API 入門】devise-token-auth – 2020年05月06日
https://qiita.com/tomokazu0112/items/5fdd6a51a84c520c45b5

Rails API + React + devise_token_authでログイン機能を実装する
https://qiita.com/kazama1209/items/caa387bb857194759dc5

[Rails] devise token auth を使う – 2020年09月14日
https://qiita.com/Masahiro_T/items/6bc49a625b437a7c2f45

Cookie(Session)での認証とTokenでの認証の違いについて
https://magazine.techcareer.jp/technology/skill/11273

[rails]既存のdevise を入れた後にdevise_token_authを追加、API化する時 – 2020年12月13日
https://qiita.com/gonza_kato_atsushi/items/9b6e92e636825ce91501

DeviseとDevise token authを共存させる(後から追加する) – 2019年11月07日
https://qiita.com/wktq/items/8a4653153af47933c169

あんまよく知らなかったんですが、railsってマイグレーション中にこういう風に処理も書けるんですね

class AddTokensToCustomers < ActiveRecord::Migration[6.0]
  def up
    add_column :customers, :provider, :string, null: false, default: 'email'
    add_column :customers, :uid, :string, null: false, default: ''
    add_column :customers, :tokens, :text
    Customer.reset_column_information
    Customer.find_each do |customer|
      customer.uid = user.email
      customer.provider = 'email'
      customer.save!
    end
    add_index :customers, [:uid, :provider], unique: true
  end

  def down
  end
end

devise + devise token authでWebにもアプリにも対応 – 2019年10月22日
https://qiita.com/DaichiSaito/items/b6239d70ab10b2070bc4

普通の devise の場合

ところで何気なく使ってる通常の devise のログインセッションで
どうやって保存されてるんでしょうか?

クッキーに保存していると思いますが、その値は?
まさか、user_id そのままではないでしょう。

warden + secret key が関係してそうですが、
詳細はわかりません、分かり次第追記します。

Deviseのモヤモヤを解消して快適なRailsライフを送ろう! – 2020年12月25日
https://zenn.dev/kitabatake/articles/start-to-like-the-devise

Railsのsecret_key_baseを理解する(翻訳) – 2017年10月24日
https://techracho.bpsinc.jp/hachi8833/2017_10_24/46809

warden のコードリーディング – 2020年6月5日
https://ogidow.hateblo.jp/entry/2020/06/05/105208

Wardenの使い方 まとめ – 2018年10月27日
https://nekorails.hatenablog.com/entry/2018/10/27/172832

Devise を知るにはまず Warden を知るが良い
http://vimtaku.github.io/blog/2014/03/02/warden

コメント

タイトルとURLをコピーしました