この記事の概要
- RailsのAPIモードで認証周り作ったときに苦労したので、備忘録メモとして…。
成果物
- GitHub: try-rails6-api-with-devise
各種バージョン
- Ruby 2.7
- Rails 6.0.0
- mysql 5.7.21
前提条件
- Dockerを使える環境が整っていること
できること
- Rails 6.0 + Docker + MySQL5x + devise-token-auth での環境構築
- devise-token-authを使った、サインアップ、サインイン、サインアウトができる
- ユーザがサインインしていることを確認し、サインインしていたらuser情報を取得する
できないこと(やらないこと)
- コピペで環境構築できるように作った記事なので、各項目の詳しい説明は割愛
環境構築手順
1. try-rails6-api のテンプレートを使用し、リポジトリを作成する
- リポジトリ名は
try-rails6-api-with-devise
とする - 必要に応じて、
try-rails6-api
と記載している箇所を自分で作成したリポジトリ名に変更する(当記事であればtry-rails6-api-with-devise
に変更)
2. try-rails6-apiのREADME.md に沿って環境構築する
3. 必要なGemを追加する
Gemfile
Gemfile
・
・
・
# 認証
gem "devise"
gem "devise_token_auth"
# Use Rack CORS for handling Cross-Origin Resource Sharing (CORS), making cross-origin AJAX possible
# ※ 疎通確認をPostmanでする場合、必要となる場合があるので追加しておく
gem 'rack-cors'
4. ビルド&追加したGemをインストールする
docker-compose build --no-cache
docker-compose run back bundle exec rails g devise:install
docker-compose run back bundle exec rails g devise_token_auth:install User auth
5. devise_token_auth
の設定
config/initializers/devise_token_auth.rb
config/initializers/devise_token_auth.rb
# frozen_string_literal: true
DeviseTokenAuth.setup do |config|
# By default the authorization headers will change after each request. The
# client is responsible for keeping track of the changing tokens. Change
# this to false to prevent the Authorization header from changing after
# each request.
config.change_headers_on_each_request = false
# By default, users will need to re-authenticate after 2 weeks. This setting
# determines how long tokens will remain valid after they are issued.
# config.token_lifespan = 2.weeks
# Limiting the token_cost to just 4 in testing will increase the performance of
# your test suite dramatically. The possible cost value is within range from 4
# to 31. It is recommended to not use a value more than 10 in other environments.
config.token_cost = Rails.env.test? ? 4 : 10
# Sets the max number of concurrent devices per user, which is 10 by default.
# After this limit is reached, the oldest tokens will be removed.
# config.max_number_of_devices = 10
# Sometimes it's necessary to make several requests to the API at the same
# time. In this case, each request in the batch will need to share the same
# auth token. This setting determines how far apart the requests can be while
# still using the same auth token.
# config.batch_request_buffer_throttle = 5.seconds
# This route will be the prefix for all oauth2 redirect callbacks. For
# example, using the default '/omniauth', the github oauth2 provider will
# redirect successful authentications to '/omniauth/github/callback'
# config.omniauth_prefix = "/omniauth"
# By default sending current password is not needed for the password update.
# Uncomment to enforce current_password param to be checked before all
# attribute updates. Set it to :password if you want it to be checked only if
# password is updated.
# config.check_current_password_before_update = :attributes
# By default we will use callbacks for single omniauth.
# It depends on fields like email, provider and uid.
# config.default_callbacks = true
# Makes it possible to change the headers names
config.headers_names = {:'access-token' => 'access-token',
:'client' => 'client',
:'expiry' => 'expiry',
:'uid' => 'uid',
:'token-type' => 'token-type' }
# By default, only Bearer Token authentication is implemented out of the box.
# If, however, you wish to integrate with legacy Devise authentication, you can
# do so by enabling this flag. NOTE: This feature is highly experimental!
# config.enable_standard_devise_support = false
# By default DeviseTokenAuth will not send confirmation email, even when including
# devise confirmable module. If you want to use devise confirmable module and
# send email, set it to true. (This is a setting for compatibility)
# config.send_confirmation_email = true
end
6. rack-cors
の設定
rack-cors がインストールされていることを確認する
docker-compose run --rm back bundle info rack-cors
設定ファイル作成
touch config/initializers/core.rb
config/initializers/core.rb
config/initializers/core.rb
Rails.application.config.middleware.insert_before 0, Rack::Cors do
allow do
origins "localhost:3000" # フロント側のポート番号を指定
resource "*",
headers: :any,
expose: ["access-token", "expiry", "token-type", "uid", "client"],
methods: [:get, :post, :put, :patch, :delete, :options, :head]
end
end
7. Modelの設定
app/models/user.rb
app/models/user.rb
# frozen_string_literal: true
class User < ActiveRecord::Base
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable, :trackable and :omniauthable
devise :database_authenticatable, :registerable,
:rememberable, :validatable
include DeviseTokenAuth::Concerns::User
end
8. Controllerの設定
(01) Registrations Controller
コントローラ作成
docker-compose run back rails g controller v1/registrations --no-assets --no-helper
app/controllers/v1/registrations_controller.rb
app/controllers/v1/registrations_controller.rb
module V1
class RegistrationsController < DeviseTokenAuth::RegistrationsController
private
def sign_up_params
params.permit(:email, :password, :password_confirmation, :name)
end
end
end
(02) Users Controller
コントローラ作成
docker-compose run back rails g controller v1/users --no-assets --no-helper
app/controllers/v1/users_controller.rb
app/controllers/v1/users_controller.rb
module V1
class UsersController < ApplicationController
# Sign inしてないと以下のMethodは実行できない
before_action :authenticate_v1_user!
# 全件検索
def index
user = User.all
if user
render json: { user: user}, status: :ok
else
render user
end
end
end
end
(03) Application Controller
app/controllers/application_controller.rb
app/controllers/application_controller.rb
class ApplicationController < ActionController::API
include DeviseTokenAuth::Concerns::SetUserByToken
rescue_from ActiveRecord::RecordNotFound, with: :render_404
before_action :configure_permitted_parameters, if: :devise_controller?
def render_404
render status: 404, json: { message: "record not found." }
end
def configure_permitted_parameters
devise_parameter_sanitizer.permit(:sign_up, keys: [:name])
end
end
9. Routingの設定
config/routes.rb
config/routes.rb
Rails.application.routes.draw do
mount_devise_token_auth_for 'User', at: 'auth'
namespace :v1, defaults: { format: :json } do
get :healthcheck, to: 'sessions#healthcheck'
mount_devise_token_auth_for 'User', at: 'auth', controllers: {
registrations: 'v1/registrations',
sessions: "devise_token_auth/sessions"
}
resources :users
end
end
10. マイグレーション実行
docker-compose run --rm back bundle exec rake db:migrate
疎通確認
- Postmanを使用
1. コンテナ起動
docker-compose up
2. サインアップ
URL
[POST] http://localhost:4000/v1/auth
Body: raw(JSON)
{"email": "sample@test.com", "password": "xxxxxxxx", "name": "サンプル 太郎"}
3. サインイン
URL
[POST] http://localhost:4000/v1/auth/sign_in
Body: raw(JSON)
{"email": "sample@test.com", "password": "xxxxxxxx"}
4. サインアウト
URL
[DELETE] http://localhost:4000/v1/auth/sign_out
Headers
- サインインで取得した、以下の項目を設定する
- access-token
- uid
- client
- expiry
- content-type
- token-type
5. ユーザ情報取得(サインインしていないと取得できない)
URL
[GET] http://localhost:4000/v1/users
Headers
- サインインで取得した、以下の項目を設定する
- access-token
- uid
- client
- expiry
- content-type
- token-type