LoginSignup
151
135

More than 3 years have passed since last update.

[Rails] devise token auth を使う

Last updated at Posted at 2019-05-12

devise token authのチュートリアルのような記事です。
大部分はこの記事を参考にしています。一部、バージョンの違い(?)によるのか、エラーが出る箇所があったため、この記事を作りました。

セットアップ

はじめにRailsアプリを作ります。

terminal
rails new devise_token_auth_test

Gemfileにdevise token auth用のgemを追記します。

Gemfile
# devise関連
gem 'devise'
gem 'devise_token_auth'

# CORS設定
gem 'rack-cors'

gem 'rack-cors'を入れる理由については公式DocsCross Origin Requests (CORS)に載っています。

bundle install した後データベースを作成します。

terminal
bundle install
rake db:create

devise token auth の導入

installします。
通常のdeviseについては、公式Docsにインストールしてくださいとは載っていませんが、rails s時にエラーが出るのでインストールします。

terminal
rails g devise:install
rails g devise_token_auth:install User auth

次に、インストール時に作成されたdb/migrate/~_devise_token_auth_create_users.rbTrackableに関するカラムを追記します。
これがないと、サインイン時にUndefined method current_sign_in_atcurrent_sign_in_atはTrackableに関するカラム)とエラーが出ます。

db/migrate/~_devise_token_auth_create_users.rb
class DeviseTokenAuthCreateUsers < ActiveRecord::Migration[5.2]
  def change

    create_table(:users) do |t|
      ## Required
      t.string :provider, :null => false, :default => "email"
      t.string :uid, :null => false, :default => ""

      ## Database authenticatable
      t.string :encrypted_password, :null => false, :default => ""

      ## Recoverable
      t.string   :reset_password_token
      t.datetime :reset_password_sent_at
      t.boolean  :allow_password_change, :default => false

      ## 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

      ## User Info
      t.string :name
      t.string :nickname
      t.string :image
      t.string :email

      ## Tokens
      t.text :tokens

      t.timestamps
    end

    add_index :users, :email,                unique: true
    add_index :users, [:uid, :provider],     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

では、devise token auth の設定を追加します。

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

また、application_controllerに以下を追記してください。

controllers/application_controller.rb
class ApplicationController < ActionController::Base
  include DeviseTokenAuth::Concerns::SetUserByToken
  skip_before_action :verify_authenticity_token, if: :devise_controller? # APIではCSRFチェックをしない
end

これで準備が出来ました。

試す

サーバーを起動して動かしてみましょう。

terminal
rails s

サインアップ

terminal
curl localhost:3000/api/auth -X POST -d '{"email":"example@example.com", "password":"password", "password_confirmation": "password"}' -H "content-type:application/json"

curlを使ってUserを作成するAPI(localhost:3000/api/auth)を叩いています。
引数の説明は以下の通りです。

-X POST POSTでリクエスト
-d 'foo:bar' Bodyに入れるデータ
-H 'foo:bar' ヘッダーに入れるデータ

今回は、Bodyにemailpasswordを 、ヘッダーに、Bodyの中身がjson形式であることを示すための設定content-type:application/jsonを追加しています。

サインアップに成功すると以下のようなレスポンスが返ってくるはずです。

terminal
{"status":"success","data":{"id":1,"provider":"email","uid":"example@example.com","allow_password_change":false,"name":null,"image":null,"email":"example2@example.com","created_at":"2019-05-12T20:48:24.000+09:00","updated_at":"2019-05-12T20:48:24.000+09:00"}}

サインイン

terminal
curl localhost:3000/api/auth/sign_in -X POST -d '{"email":"example@example.com", "password":"password"}' -H "content-type:application/json" -i

-iオプションを付けてレスポンスのヘッダーも表示されるようにしています。
(ここの情報をこの後使います。)

成功すると以下のようなレスポンスが返ってくるはずです。

terminal
HTTP/1.1 200 OK
X-Frame-Options: SAMEORIGIN
X-XSS-Protection: 1; mode=block
X-Content-Type-Options: nosniff
X-Download-Options: noopen
X-Permitted-Cross-Domain-Policies: none
Referrer-Policy: strict-origin-when-cross-origin
Content-Type: application/json; charset=utf-8
access-token: xzTWhTURMmPdDjaKB2R9gw
token-type: Bearer
client: S2T6zY0aDB6VBXYVMdpjbg
expiry: 1558871460
uid: example@example.com
Cache-Control: no-store, must-revalidate, private, max-age=0

{"data":{"id":1,"email":"example@example.com","provider":"email","uid":"example@example.com","allow_password_change":false,"name":null,"image":null}}

パスワードの変更

terminal
curl localhost:3000/api/auth/password -X PUT -d '{"password":"password_new", "password_confirmation": "password_new"}' -H "content-type:application/json" -H "access-token: xzTWhTURMmPdDjaKB2R9gw" -H "client: S2T6zY0aDB6VBXYVMdpjbg" -H "uid: example@example.com"

パスワードの変更はPOSTではなくPUTを指定します。
また、ログイン時のレスポンスのヘッダーにあったaccess-token client uidをヘッダーに追加しています。

成功すると以下のようなレスポンスが返ってくるはずです。

terminal
{"success":true,"data":{"id":1,"provider":"email","allow_password_change":false,"email":"example@example.com","uid":"example@example.com","name":null,"image":null,"created_at":"2019-05-12T20:30:50.000+09:00","updated_at":"2019-05-12T21:31:33.000+09:00"},"message":"パスワードの更新に成功しました。"}

deviseのコントローラーを編集したい時

terminal
rails g controller api/auth/registrations
controllers/api/auth/registrations_controller.rb
class Api::Auth::RegistrationsController < DeviseTokenAuth::RegistrationsController
  # hogehoge
end
config/routes.rb
Rails.application.routes.draw do

  namespace :api do
    mount_devise_token_auth_for 'User', at: 'auth', controllers: {
        registrations: 'api/auth/registrations'
    }
  end

end
151
135
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
151
135