devise_token_authでtoken認証
別の記事で紹介したRails API / React / PostgreSQLで環境構築が終わっているものとします。
[Docker]Rails API / React / PostgreSQL
目的
(参考)
環境
Windows10 for Pro
Docker for Windows
方法
1. Add gem and Bundle install
Gemfileにdeviseによるtoken認証に必要なgemを追記します。
# generate authentification with token base
gem 'devise'
gem 'devise_token_auth'
gem 'bcrypt', '~> 3.1.13'
gem 'rack-cors'
Gemfileを更新したので、dockerでビルドし直す必要があります。
docker-compose build api
2. devise_token_authの設定
次にdevise_token_authの設定を行います。rails g devise_token_auth:install (Model) (Auth)
(カッコ内は任意の名称)を実行します。
docker-compose run --rm api rails g devise_token_auth:install User auth
create config/initializers/devise_token_auth.rb
insert app/controllers/application_controller.rb
gsub config/routes.rb
create db/migrate/20191026021711_devise_token_auth_create_users.rb
create app/models/user.rb
作成されたファイルを編集していきます。
まず、migrate/のxxxxxx_devise_token_auth_create_users.rbを以下のように変更します。
## 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
## User Info
t.string :username <--- User Modelに必要な任意のカラム
t.string :email
## Tokens
t.json :tokens
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
修正したらdb:migrate
し、データベースにテーブル/カラムを追加します。
docker-compose run --rm api rails db:migrate
== 20191026021711 DeviseTokenAuthCreateUsers: migrating =======================
-- create_table(:users)
-> 0.0696s
-- add_index(:users, :email, {:unique=>true})
-> 0.0275s
-- add_index(:users, [:uid, :provider], {:unique=>true})
-> 0.0235s
-- add_index(:users, :reset_password_token, {:unique=>true})
-> 0.0146s
== 20191026021711 DeviseTokenAuthCreateUsers: migrated (0.1362s) ==============
Registration用のControllerを作成します。
docker-compose run --rm api rails g controller api/auth/registrations
Starting lifemap_db_1 ... done create app/controllers/api/auth/registrations_controller.rb
invoke test_unit
create test/controllers/api/auth/registrations_controller_test.rb
registrations_controller.rb
にSign Up(新規作成)及びユーザ情報更新時のstrong parameterを追記します。
class Api::Auth::RegistrationsController < ApplicationController
private
def sign_up_params
params.permit(:username, :email, :password, :password_confirmation)
end
def account_update_params
params.permit(:username, :email)
end
end
routes.rb
に名前空間及びregistrationsの情報を追記します。
Rails.application.routes.draw do
namespace :api do
mount_devise_token_auth_for 'User', at: 'auth', controllers: {
registrations: 'api/auth/registrations'
}
end
# For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html
end
routesを確認すると、定義した名前空間apiのファルダが起点になっていることがわかります。
$docker-compose run --rm api rake routes
Starting lifemap_db_1 ... done
Prefix Verb URI Pattern Controller#Action
new_api_user_session GET /api/auth/sign_in(.:format) devise_token_auth/sessions#new
api_user_session POST /api/auth/sign_in(.:format) devise_token_auth/sessions#create
destroy_api_user_session DELETE /api/auth/sign_out(.:format) devise_token_auth/sessions#destroy
new_api_user_password GET /api/auth/password/new(.:format) devise_token_auth/passwords#new
edit_api_user_password GET /api/auth/password/edit(.:format) devise_token_auth/passwords#edit
api_user_password PATCH /api/auth/password(.:format) devise_token_auth/passwords#update
PUT /api/auth/password(.:format) devise_token_auth/passwords#update
POST /api/auth/password(.:format) devise_token_auth/passwords#create
cancel_api_user_registration GET /api/auth/cancel(.:format) api/auth/registrations#cancel
new_api_user_registration GET /api/auth/sign_up(.:format) api/auth/registrations#new
edit_api_user_registration GET /api/auth/edit(.:format) api/auth/registrations#edit
api_user_registration PATCH /api/auth(.:format) api/auth/registrations#update
PUT /api/auth(.:format) api/auth/registrations#update
DELETE /api/auth(.:format) api/auth/registrations#destroy
POST /api/auth(.:format) api/auth/registrations#create
api_auth_validate_token GET /api/auth/validate_token(.:format) devise_token_auth/token_validations#validate_token
確認
1. User新規作成
- PostmanでPOSTリクエストを確認しました。
- Powershellからも確認できます。
$ Invoke-WebRequest -Method Post -Body 'username=norihito&email=norihito0626@gmail.com&password=norihito' http://localhost:3000/api/auth
2. Userログイン
ログインした場合、ヘッダにaccess-token
, client
, uid
の情報が返ってきます。
これらはパスワード、ユーザ情報変更やコンテンツ制限に使用します。
3. Userパスワード変更
新規password及びpassword confirmationの他に、PUTのHeadersにtoken情報を追加します。
エラー例
Deviseの継承の漏れ
エラー内容
docker-compose run --rm api rake db:migrate
rake aborted!
NoMethodError: undefined method `devise' for User
修正箇所
https://github.com/lynndylanhurley/devise_token_auth/issues/1276#issuecomment-478866479
class User < ActiveRecord::Base
extend Devise::Models <-----Devise継承の漏れの可能性
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
include DeviseTokenAuth::Concerns::User
end
DeviseTokenAuthの継承漏れ
エラー内容
#<AbstractController::ActionNotFound: The action 'create' could not be found for Api::Auth::RegistrationsController>"
修正箇所
module Api
module Auth
class RegistrationsController < DeviseTokenAuth::RegistrationsController <--DeviseTokenAuth継承されているかどうか。
Trackbleのラカム作成漏れ(Sign In時)
エラー内容
Undefined method current_sign_in_at
修正箇所
下記をmigrate/のxxxxxx_devise_token_auth_create_users.rbに追記すること。
migrateやり直しの場合は、docker-composer exec api db:rollback
を行ってから、マイグレートし直しましょう。
## 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
その他
CSRfチェックをしない
class ApplicationController < ActionController::API
include DeviseTokenAuth::Concerns::SetUserByToken
skip_before_action :verify_authenticity_token, if: :devise_controller? # <--- APIではCSRFチェックをしない
end