💭

Rails7のAPIモードでDevise Token Authを使います

2023/06/16に公開

準備

私が以前に作成したこちらの記事をもとに開発環境を構築した状態から始めます。

Gemfileに以下のGemを記載した後に、bundle installを実行します。

Gemfile
gem "rack-cors"
gem 'devise'
gem 'devise_token_auth'
gem 'devise-i18n'

次のコマンドでdeviseとdevise_token_authをインストールし、Userモデルを作成します。

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

続いて、認証を行うコントローラーとログインユーザー情報を取得するコントローラーを作成します。

rails g controller api/v1/auth/registrations
rails g controller api/v1/auth/sessions

各コントローラーを修正します。

backend/app/controllers/api/v1/auth/registrations_controller.rb
class Api::V1::Auth::RegistrationsController < DeviseTokenAuth::RegistrationsController
  private

    def sign_up_params
      params.permit(:email, :password, :password_confirmation, :name)
    end
end
backend/app/controllers/api/v1/auth/sessions_controller.rb
class Api::V1::Auth::SessionsController < ApplicationController
  def index
    if current_api_v1_user
      render json: { is_login: true, data: current_api_v1_user }
    else
      render json: { is_login: false, message: "ユーザーが存在しません" }
    end
  end
end

access-token,uid,clientの値をクライアント側で利用したいので、次のようにCORSを設定します。

backend/config/initializers/cors.rb
Rails.application.config.middleware.insert_before 0, Rack::Cors do
  allow do
    origins "localhost:3000"

    resource "*",
      headers: :any,
      expose: %w[access-token uid client],
      methods: [:get, :post, :put, :patch, :delete, :options, :head]
  end
end

ルーティングの設定を行います。

backend/config/routes.rb
Rails.application.routes.draw do
  namespace :api do
    namespace :v1 do
      mount_devise_token_auth_for 'User', at: 'auth', controllers: {
        registrations: 'api/v1/auth/registrations'
      }

      namespace :auth do
        resources :sessions, only: [:index]
      end
    end
  end
end

分かりやすくするために日本語に設定します。

docker compose exec api rails g devise:i18n:locale ja

日本語を適用するためにapplication_controller.rbを次のように修正します。

backend/app/controllers/application_controller.rb
class ApplicationController < ActionController::API
        include DeviseTokenAuth::Concerns::SetUserByToken
        before_action do
                I18n.locale = :ja
        end
end

Rails7では、セッションを使用しない場合にセッションへのアクセスがあるとエラーが発生するようですので、application.rbを次のように修正します。

backend/config/application.rb
require_relative "boot"

require "rails/all"

# Require the gems listed in Gemfile, including any gems
# you've limited to :test, :development, or :production.
Bundler.require(*Rails.groups)

module Api
  class Application < Rails::Application
    # Initialize configuration defaults for originally generated Rails version.
    config.load_defaults 7.0

    # Configuration for the application, engines, and railties goes here.
    #
    # These settings can be overridden in specific environments using the files
    # in config/environments, which are processed later.
    #
    # config.time_zone = "Central Time (US & Canada)"
    # config.eager_load_paths << Rails.root.join("extras")

    # Only loads a smaller set of middleware suitable for API only apps.
    # Middleware like session, flash, cookies can be added back manually.
    # Skip views, helpers and assets when generating a new resource.
    config.api_only = true
    
    config.session_store :cookie_store, key: '_interslice_session'
    config.middleware.use ActionDispatch::Cookies
    config.middleware.use config.session_store, config.session_options
  end
end

今回はリクエストごとにトークンが変更されないよう設定します。

backend/config/initializers/devise_token_auth.rb
config.change_headers_on_each_request = false

忘れないうちに次のコマンドを実行します。

docker compose exec api rails db:migrate

動作確認

ここまでできたらいくつかのメソッドの動作確認をしてみます。今回はAdvanced REST clientを用います。

サインアップ

メソッドはPOST
リクエストURLはhttp://localhost:3001/api/v1/auth
Bodyに次の画像のように値を入力します。

SENDを押下して次のようなレスポンスが帰ってきたら成功です。

また、DETAILSを開くとuid, access-token, clientの値が帰ってきていることが確認できます。

サインイン

メソッドはPOST
リクエストURLはhttp://localhost:3001/api/v1/auth/sign_in
Bodyにemailとpasswordを入力し、SENDを押下します。
次のようなレスポンスが帰ってきたら成功です。

ログインユーザー情報の取得

メソッドはGET
リクエストURLはhttp://localhost:3001/api/v1/auth/sessions
Headersタブを選択し、DETAILSから確認できるuid,client,access-tokenの値を入力します。SENDを押下して次のようなレスポンスが帰ってきたら成功です。

サインアウト

メソッドはDELETE
リクエストURLはhttp://localhost:3001/api/v1/auth/sign_out
Bodyにui,client,access-tokenの値を入力し、SENDを押下します。
次のようなレスポンスが帰ってきたら成功です。

まとめ

Devise Token Authを用いて認証機能のバックエンドを作成し、いくつかのメソッドの動作確認を行いました。

Discussion