0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

devise_token_authで作る認証機能

Last updated at Posted at 2024-01-29

devise_token_authとは?

devise_token_authはRailsでトークンベースの認証機能を作れるgemのこと。
フロントとバックを分けて開発している時なんかに使う。
クライアントは、発行されたトークンを用いてユーザー認証を行う。
メールアドレスを用いた本人確認や、パスワードのリセットといった、webアプリケーションによくある機能もこのgemで作ることができる。

実行環境

Ruby 3.3.0
Rails 7.0.8

環境設定

まずは必要なgemをインストール。

gem 'devise_token_auth'
gem "devise"
gem "rack-cors"
bundle install

CORSの制御のため、rack-corsも必要

deviseとdevise_token_authをインストール

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

末尾にUser authをつけることで、以下の設定になる。
ユーザー認証に使うクラスをUserとする
認証に関連するパスはauth/~となる(https://example.com/auth/sign_in) みたいな感じ

ユーザー認証時のルーティングを設定する。
今回はappディレクトリ配下にapi/v1/authディレクトリを作成し、registrationsコントローラーをオーバーライドする。

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'
      }
    end
  end
end

ユーザー登録時に認証メールを送信するようにする。
User.rbにconfirmableを追加すればOK

  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :validatable, :confirmable # 追加

あとはmigrateを実行すればOK

rails db:migrate

テストメール設定

ユーザー登録の際、メールアドレスを使って本人確認を行う。
ローカル環境で実際にメールを送信するわけにもいかないので、テスト用にletter_opener_webを使用する。
参考
Gemfileに追加してインストール。

group :development do
  gem 'letter_opener_web', '~> 2.0'
end
bundle install

ルーティングの設定
routes.rbに以下を追記。

mount LetterOpenerWeb::Engine, at: "/letter_opener" if Rails.env.development?

config/environments/development.rb に以下を追記

  • delivery_method
    その名の通りメールの配信方法。letter_openerを使用する。
  • perform_deliveries
    実際にメールを送るかどうか。trueで送る。
config.action_mailer.delivery_method = :letter_opener
config.action_mailer.perform_deliveries = true

これで、http://localhost:3000/letter_opener/ にブラウザからアクセスすればletter_openerのGUIが表示されるはず。
スクリーンショット 0006-01-28 3.30.34.png

CORS

APIとは異なるドメインからのリクエストを想定しているので、CORSの設定をする必要がある。

  • config/initializers/cors.rb
Rails.application.config.middleware.insert_before 0, Rack::Cors do
  allow do
    # 開発環境の場合は、全てのオリジンからのリクエストを許可する
    if Rails.env.development?
      origins '*'
    else
      origins "example.com"
    end

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

実践(ユーザー登録)

テスト用に作ったクソザコフォームでテストしていく。
スクリーンショット 0006-01-28 5.21.05.png

画面ははReactで作成しており、コードは以下のような感じ。
とりあえずこれで実行してみる。

import React, { useState } from 'react';
import axios from 'axios';

function UserSignUp() {
  const [email, setEmail] = useState('');
  const [password, setPassword] = useState('');

  const handleSignUp = async () => {
    try {
      const response = await axios.post('http://localhost:3000/api/v1/auth', {
        // パラメータとして送っているのはemailとpasswordの二つのみ。
        email: email,
        password: password
      });
      console.log(response.data);
    } catch (error) {
      console.error(error);
    }
  };

  return (
    <div>
      <input
        type="text"
        placeholder="email"
        value={email}
        onChange={(e) => setEmail(e.target.value)}
      />
      <input
        type="password"
        placeholder="Password"
        value={password}
        onChange={(e) => setPassword(e.target.value)}
      />
      <button onClick={handleSignUp}>Sign Up</button>
    </div>
  );
}

export default UserSignUp;

実行すると、API側で422エラーが起きて「Unpermitted parameter: :registration.」というメッセージが出ているはず。
rails側でparamsをwrapしてしまい、以下のようなパラメーターが送られていたため、このような挙動になるらしい。

Parameters: {"email"=>"test@example.com", "password"=>"[FILTERED]", "registration"=>{"email"=>"test@example.com", "password"=>"[FILTERED]"}}

registrationsコントローラーのsign_up_paramsメソッドをオーバーライドし、registrationからパラメータを取得するようにします。

  • app/controllers/api/v1/auth/registrations_controller.rb
class Api::V1::Auth::RegistrationsController < DeviseTokenAuth::RegistrationsController
  private
  def sign_up_params
    params.require(:registration).permit(:email, :password)
  end
end

もう一度実行すると、usersテーブルにレコードが作成されました!
スクリーンショット 0006-01-28 6.00.09.png

letter_openerを開くと、アカウント認証メールが届いているはずです。
スクリーンショット 0006-02-05 4.04.43.png

Confirm my accountをクリックすると、対象ユーザーのconfirmed_atが更新される。これでユーザー登録完了!
スクリーンショット 0006-02-05 4.10.58.png

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

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?