2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

devise_auth_tokenを使った新規登録機能の実装

Posted at

この記事はプログラミング学習者がアプリ開発中に躓いた内容を備忘録として記事におこしたものです。内容に不備などあればご指摘頂けると助かります。

今回はRails(API) x ReactでX(旧Twitter)のクローンサイトを作る際に実装した新規登録機能について実装中に多々躓いた所があったので、備忘録を兼ねて記事にしていくことにしました。

0. 開発環境

今回は以下の開発環境で実装しています。

言語など バージョン
PC Mac
Rails 7.0.6
Ruby 3.2.1
React 19.1

1. devise_auth_tokenとは?

Railsの認証ライブラリであるDeviseを拡張して、トークン認証で動くライブラリです。Deviseはセッションでの認証となりますので、認証方式が異なります。
APIモードやSPA(React/Vue)・モバイルアプリ用のバックエンド向けとなります。

2. ユーザー登録実装の流れ

1, フロントエンド側(React)でPOSTリクエストを使って指定のアドレスに必要な登録情報(Email, 電話番号, パスワードなど)を送信します。
2, バックエンド側(Rails)でデータを受け取り、DBにデータを登録します。
3, データ登録後、confirmationメールをサーバー側からクライアント側へ擬似的に送信

3. フロントエンド側でデータの送信

登録データの送信処理
  import axios from "axios";
  
  const handleSignUp = async () => {
    try {
      const response = await axios.post("http://localhost:3000/api/v1/users", {
        phone_number: user.phone_number,
        email: user.email,
        birthday: user.birthday,
        password: user.password,
        password_confirmation: user.password_confirmation,
        confirm_success_url: "http://localhost:5173",
      });
      console.log(response.data);
      setUser(defaultUser);
    } catch (error) {
      console.error(error.response.data.errors);
    }
  };

axiosはPromiseベース(非同期)で動くHTTPクライアントです。
要はHTTP通信を行うためのライブラリを意味します。

上のコードではaxiosを使ってHTTP通信のうちPOSTメソッドを実行することにより後に続くパラメーター(emailなど)をバックエンド(Rails)側に送信しています。

4. devise_auth_tokenの導入

ここでは実装に必要なgemをインストールします。
gem 'devise'
gem 'devise_token_auth'
gem 'rack-cors'

上記のgemをGemfileに追記したら、実際にプロジェクト内へインストールしていきましょう。

ターミナル
bundle install

私の場合はDockerで実装していたので、下記のコマンドになります。

ターミナル
dokcer compose exec api(サービス名) bundle install

次に初期設定ファイルなどを生成していきます。

ターミナル(通常 or Docker版)
rails g devise:install
docker compose exec api(サービス名) rails g devise:install

rails g devise_token_auth:install User users
docker compose exec api(サービス名) rails g devise_token_auth:insall User users

2つのコマンドを実行することでdeviseとdevise_token_authの導入に必要な初期設定用のファイルを生成されます。
rails g devise_token_auth:install User usersのusersの部分はルートパス(エンドポイント)を指定しています。
/users/sign_in
/users/sign_out
users
などのエンドポイントになります。

5. Usersテーブルを作成する。

rails g devise_token_auth:install User authを実行して生成されたマイグレーションファイルについて、必要な所があれば修正(null: falseの追記など)。

config/db/日付_devise_token_auth_create_users.rb
class DeviseTokenAuthCreateUsers < ActiveRecord::Migration[7.0]
  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, null: false

      ## Rememberable
      t.datetime :remember_created_at

      ## 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, null: false, default: '', unique: true, limit: 50
      t.string :profile, limit: 160
      t.string :location
      t.string :website
      t.string :birthday, null: false
      t.string :email, null: false, unique: true

      ## Tokens
      t.json :tokens

      t.timestamps
    end

    add_index :users, :email, unique: true
    add_index :users, %i[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

修正が終わればrails db:migrateでテーブルを作成する。

6. APIコントローラーの作成

次に新規登録用のコントローラーを作成していきます。

ターミナル(通常 or Docker)
rails g controller api/v1/registrations
docker compose exec api(サービス名) rails g controller api/v1/registrations

ストロングパラメーターで新規登録時に登録できるカラム名を指定します。
コントローラー内にはストロンゴパラメーターしか記述されていませんが、
DeviseTokenAuth::RegistrationsControllerを継承しているため、
ユーザー登録などの処理はdevise_token_authが全て裏で処理しています。

registrations_controller.rb
module Api
  module V1
    class RegistrationsController < DeviseTokenAuth::RegistrationsController
      private

      def sign_up_params
        params.require(:registration).permit(:name, :email, :phone_number, :birthday, :password, :password_confirmation)
      end
    end
  end
end

7. ルーティング設定

route.rb
Rails.application.routes.draw do
  namespace :api do
    namespace :v1 do
      mount_devise_token_auth_for 'User', at: 'users', controllers: {
        registrations: 'api/v1/registrations'
      }
    end
  end
end

ここではエンドポイントとそにれ対して作動するコントローラーを指定しています。
mount_devise_token_auth_for 'User', at: 'users'のところで
usersの部分でURLのエンドポイントを指定しています。
上記コードの場合、ap1/v1/usersというパス(エンドポイント)にアクセスが来た時、
devise_token_authのregistrations系のリクエスト(新規登録など)は
app/controllers/api/v1/registrations_constroller.rbを使うように設定しています。
全てのリクエストがregistrations_controller.rbにいくわけではありません。
api/v1/usersへのPOST(新規登録)などregistrationsに該当するリクエストのみが対象。
前述のフロントエンド側の操作でHTTPメソッドのPOSTでAPI側にアクセスするように実装しています。
フロントエンド側で指定したhttp://localhost:3000/api/v1/usersにアクセスするとroutes.rbに指定されたルーティングによりregistrations_controllerへ導かれます。

8. CORSに関する説明と設定

  • CORSとは
    Cross-Origin Resource Sharingの略で異なるオリジンからのリソース(Webページなど)へのアクセス制限を緩和する仕組みです。
    オリジンとはプロトコル、ドメイン、ポート番号を併せたものを指します。

オリジン例:https://qiita.com:80
上記のオリジンで説明しますと、
プロトコル:https
ドメイン:qiita.com
ポート番号:80

言い換えますと、異なるURLからリソースへのアクセスを許可する仕組みとなります。

今回私が作成しているX(旧Twitter)のクローンサイトは下記の構成になっています。
フロントエンド(React):http://localhost:5173
バックエンド(Rails) :http://localhost:3000
※オリジン(ほぼURL)が異なる事に着目

ユーザーの新規登録機能はフロントエンド側で入力したデータをバックエンド側にアクセスしてデータベースに保管する作業となります。
異なるオリジン間のリソース共有が発生するので、ここでCORSの出番となります。

以下はCORSの設定です。
また、冒頭でインストールしたrack-cors'もここで使用することとなります。

cors.rb
Rails.application.config.middleware.insert_before 0, Rack::Cors do
  allow do
    origins 'http://localhost:5173' # 許可するオリジンの指定

    resource '*',
             headers: :any,
             expose: %w[access-token expiry token-type uid client], #追記
             methods: %i[get post put patch delete options head]
  end
end

originsにフロントエンド側のURLを記述することでアクセスが可能になります。
初期設定ではorigins *に設定されているので、どのオリジンからもアクセスできる設定になっています。指定のオリジンに書き換える事で他のオリジンからのアクセスは不可となり、ホワイトリストの役割を果たします。
追記部分のexposeがあることによってフロントエンド側が認証情報を取得できるようになります。
この記述が無い場合は認証情報が不十分という理由により401エラーが発生する可能性がありますのでご注意ください。

9. confirmableを有効にする

新規登録のために必要項目を入力した後に確認メールを登録用メールアドレスに送信する設定です。

user.rb
class User < ApplicationRecord
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :validatable, :confirmable
  include DeviseTokenAuth::Concerns::User
end

モデルのuser.rbでconfirmableは初期状態ではコメントアウトされているので、deviseの使用機能として追加します。

10. letter_opener_webの設定

上記の確認メール設定で送信されたメールが正しく送信されているか、開発環境でチェックするための設定を行います。

  • letter_opener_webのインストール
Gemfile
group :development do
  gem 'letter_opener_web', '~> 3.0'
end

letter_opener_webは開発環境だけで使用するので、開発環境グループに追加してインストールします。

  • routesの編集
routes.rb
mount LetterOpenerWeb::Engine, at: '/letter_opener' if Rails.env.development?

routes.rbに上記コードを追加することで /letter_openerのエンドポイントにアクセスした時に開発環境限定でletter_opener_webのアプリケーションを実行できます。

11. developmen.rbの設定

letter_opener_webが開発環境下で使えるようにdevelopment.rbに追記します。

debelopment.rb
  # 電子メールが配信完了できない場合にエラーを発生させるかの設定
  config.action_mailer.raise_delivery_errors = true
  # フラグメントキャッシュを利用するための設定
  config.action_mailer.perform_caching = false
  # 送信されるメール内のURLのドメインが`localhost`で固定される
  config.action_mailer.default_url_options = { host: 'localhost', port: 3000 }
  # メールの配信方法を設定
  config.action_mailer.delivery_method = :letter_opener_web
  # メール配信を行うかどうかの設定
  config.action_mailer.perform_deliveries = true

※フラグメントキャッシュ:Webページの断片(部分テンプレートなど)をキャッシュし、リクエストごとに毎回生成するのではなく、キャッシュされたものを再利用することでパフォーマンスを向上させる機能。

12. 参考にしたサイト

letter_opener_web Github
letter_opener_web設定
なんとなく CORS がわかる...はもう終わりにする。

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

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?