はじめに
こんにちは、torihaziです
ただいま朝の8時半です。
今、Rails React のSPAで
devise-token-authを使って認証周りを作成中です
ただcurlでPOSTリクエスト使って登録やろうとしたんですけど
うまくいかず。
なんででしょうね。これ書いてる今も解決してません。
ということでゆるくいきます。
現状
gemにdeviseとdevise-token-auth、rack-cors入れてbundle installやりました。
その後で
rails generate devise:install rails generate devise_token_auth:install User auth => 作成されたマイグレーションファイルいじった。 rails db:migrate
migrationファイル(抜粋)
## User Info t.string :name, null: false, unique: true, limit: 50 t.string :email, null: false, unique: true t.string :tel, null: false, unique: true t.string :profile, limit: 160 t.string :place t.string :web t.boolean :is_active, null: false, default: false
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, :recoverable, :rememberable, :validatable, :confirmable include DeviseTokenAuth::Concerns::User end
cors.rb
Rails.application.config.middleware.insert_before 0, Rack::Cors do allow do origins "localhost:3000", "127.0.0.1:3000" resource "*", headers: :any, expose: ['access-token', 'expiry', 'token-type', 'uid', 'client'], methods: [:get, :post, :put, :patch, :delete, :options, :head] end end
routes.rb
# frozen_string_literal: true Rails.application.routes.draw do namespace :api do namespace :v1 do mount_devise_token_auth_for 'User', at: 'auth' end end end
やったこと
curl localhost:3001/api/v1/auth -i -X POST -d '{"email":"test@example.com", "password":"password"}' -H "content-type:application/json"
するとレスポンスが
HTTP/1.1 422 Unprocessable Entity ~~~ {"success":false,"errors":["Missing 'confirm_success_url' parameter."],"status":"error","data":{"id":null,"provider":"email","uid":"","allow_password_change":false, "name":null,"email":"test@example.com","tel":null,"profile":null, "place":null,"web":null,"is_active":false, "created_at":null,"updated_at":null}}
422はアレです。
サーバがリクエストは理解したけど処理ができないってやつで。
原因調査
怪しいとこは
"errors":["Missing 'confirm_success_url' parameter."],
だと思う。
他の人が次でやってたのでとりあえずこれを実行。
curl localhost:3001/api/v1/auth -i -X POST -d '{"email":"test@example.com", "password":"password", "password_confirmation": "password"}' -H "content-type:application/json"
結果変わらず。やっぱりconfirm_success_urlとかいうやつが悪そう。
なんか見つけた。 https://qiita.com/mtoyopet/items/076b623ac72f4f83c5f6
POSTのauthにリクエストを送信しますが、confirmableを設定すると、リクエストパラメターにconfirm_success_urlを追加する必要があります。
こいつっぽい。
追加。王手かね。
https://zenn.dev/shogo_matsumoto/articles/c6485b39c5f621
{ "email": "送信先のメールアドレス", "password": "パスワード", "password_confirmation": "パスワード確認", "confirm_success_url": "メール内のリンクからのリダイレクト先のURL" } email→ 送信先のメールアドレスを設定(サインアップ時に入力した際にそのメールアドレスに認証メールが届く) confirm_success_url→ 本認証が完了した際にリダイレクトする URL を指定する。今回のアプリではログインページに遷移するようにするが、フロントはこれから作るので、API 確認の際は適当にhttps://google.comなどと入力しておけばいい。ちゃんとそのページに遷移したら成功ということになる。
原因
migrationファイルにてconfirmableの設定を追加し、
user.rbにおいて:confirmableを追加したことによって、
confirm_success_urlというのをpostリクエストのパラメータに
含めなければならなかったのにやらずにやっていたから。
試しに入れて適当なものやってみよう。
まだメールの設定入れてないので本登録はできないけど、正常に処理はされるはず。
ということで修正して、curl実行。
curl localhost:3001/api/v1/auth -i -X POST -d '{"email":"test@example.com", "password":"password", "confirm_success_url": "http://localhost:3001"}' -H "content-type:application/json"
てすればいくでしょう。
知らんけど。
あ、だめだ。でも500で帰ってきた。
てことはリクエストとしてはOK
サーバ側で跳ねられただけ。進展。
NotNullViolation
あー。nameとかtelか。not_nullてしたもんね。
じゃ入れたらいけるかな。
その前にmigrationファイルで 誕生日 birthカラム入れるの忘れてた。
rails db:rollback
で戻して追加して、rails db:migrate
して修正。
ということでcurlリベンジ。
curl localhost:3001/api/v1/auth -i -X POST -d '{"name": "hoge", "tel": "09012345678", "birth": "2024-04-04","email":"test@example.com", "password":"password", "confirm_success_url": "http://localhost:3001"}' -H "content-type:application/json"
およ。500だ。
なぜ。
入れたけど、サーバ側でもらえてないっぽい?
"error":"Internal Server Error","exception":"#\u003cActiveRecord::NotNullViolation:\"PG::NotNullViolation: ERROR: null value in column \\"name\\" of relation \\"users\\" ~~~
あー、あれか。
ストロングパラメータだっけか。
params.requireなんとかとかいう、コントローラに設定する
指定したものしか取得しないとかいうやつ。
さっきのqiitaの人が書いてた。
class Auth::RegistrationsController < DeviseTokenAuth::RegistrationsController private def sign_up_params params.permit(:name, :email, :password, :password_confirmation) end end
device-token-auth本家にはこう書いてあった。
Accepted params can be customized using the devise_parameter_sanitizer system.
param追加したきゃなんかしろということらしい。
そこから飛べるdevise本家にはその追加方法が書いてあった。
class ApplicationController < ActionController::Base before_action :configure_permitted_parameters, if: :devise_controller? protected def configure_permitted_parameters devise_parameter_sanitizer.permit(:sign_up, keys: [:username]) end end
ということでqiitaのじゃなくて本家採用して書いてみよう。
class ApplicationController < ActionController::API before_action :configure_permitted_parameters, if: :devise_controller? include DeviseTokenAuth::Concerns::SetUserByToken protected def configure_permitted_parameters devise_parameter_sanitizer.permit(:sign_up, keys: [:name, :tel, :birth, :confirm_success_url]) end end
ということで書いてみた。いけるかな。
ならなかったら泣きたい
curl localhost:3001/api/v1/auth -i -X POST -d '{"name": "hoge", "tel": "09012345678", "birth": "2024-04-04","email":"test@example.com", "password":"password", "confirm_success_url": "http://localhost:3001"}' -H "content-type:application/json"
失敗。500。nandeya
{"status":500,"error":"Internal Server Error","exception":"#\u003cActiveModel::UnknownAttributeError: unknown attribute 'birth' for User
ただメッセージは変わったし、さっきの問題はクリアしたっぽい。
内容はbirthなんてものはUserモデルにはないよ、てことだと思う。
嘘コケ、さっき追加したばっかやんけ。
再起動してみよか。
docker compose restart
リベンジ。
"error":"Internal Server Error","exception":"#\u003cActiveModel::UnknownAttributeError: unknown attribute 'confirm_success_url' for User
今度はこっちがないと。
直感でさっきコントローラに書いた:confirm_success_urlを削除して持っ回やってみた。
{"status":500,"error":"Internal Server Error","exception":"#\u003cActionView::Template::Error: Missing host to link to! Please provide the :host parameter, set default_url_options[:host], or set :only_path to true\u003e"
なんか変わった。
調べてみると確認用メール送りたいんだけどメール送れない、ってエラー。
要はメールの設定をしろと。
そうなんすか。知らなかったです。
ということで今回は指定があるので、letter_opener_webで。
(かれこれ1時間くらいやってるなー。疲れた。)
入れる手順は公式を見てやると
gem入れて。buildして。
develoment.rbに追加して。
config.action_mailer.delivery_method = :letter_opener_web config.action_mailer.default_url_options = { host: 'localhost:3001' }
routes.rb修正して
Rails.application.routes.draw do mount LetterOpenerWeb::Engine, at: "/letter_opener" if Rails.env.development? namespace :api do namespace :v1 do mount_devise_token_auth_for 'User', at: 'auth' end end end
とりあえずletter_openerは出た。
ということでリリリリリベンジ。
curl localhost:3001/api/v1/auth -i -X POST -d '{"name": "hoge", "tel": "09012345678", "birth": "2024-04-04","email":"test@example.com", "password":"password", "confirm_success_url": "http://localhost:3001"}' -H "content-type:application/json"
なんか変わった。結果は422
{"status":"error","data":{"id":null,"provider":"email","uid":"","allow_password_change":false,"name":"hoge","email":"test@example.com","tel":"09012345678","profile":null,"place":null,"web":null,"birth":"2024-04-04","is_active":false,"created_at":null,"updated_at":null},"errors":{"email":["has already been taken"],"full_messages":["Email has already been taken"]}}%
emailがすでにありますよ。
一旦リセットしよう。
docker compose downしてから
docker compose run --rm api rails db:migrate:reset
再度 curl。
200だーーー!
メールも来たー。
添付されたurlクリックして無事飛んだ。
なんか変なパラメータついてるけど、ここをやるのはまた後で。
終わりに
ただいま朝の11時です。
2時間かかりました。
登録自体はまだかもしれませんが、それは第2章で。
一旦休憩。