Devise set_user_by_token问题:密码重置表单提交异常
Hey Jay, let’s break down what might be going wrong with your password reset form submission—this is a super common gotcha when pairing Devise Token Auth with a React frontend, so I’ve got a few actionable angles to check:
Double-check your form’s request payload
Devise Token Auth expects specific parameters for updating a reset password:password,password_confirmation, and thereset_password_token. A frequent mistake is either omitting the token entirely, or passing a URL-encoded version of it (make sure you’re using the raw token extracted from the reset link). Your request body should look like this:{ "password": "your-new-secure-password", "password_confirmation": "your-new-secure-password", "reset_password_token": "extracted-reset-token-here" }Ensure auth headers are persisted after token validation
When a user clicks the reset link to/api/auth/passwords/edit, the Rails endpoint validates the token and returnsaccess-token,client, anduidheaders in the response. Your React app needs to capture these headers (store them in local storage, for example) before rendering the form. If you don’t persist these, the backend won’t recognize the authenticated session tied to the reset token when you submit the form, leading to unauthorized or invalid token errors.Here’s a quick example of capturing these headers with
fetch:const token = new URLSearchParams(window.location.search).get('reset_password_token'); fetch(`/api/auth/passwords/edit?reset_password_token=${token}`) .then(res => { localStorage.setItem('access-token', res.headers.get('access-token')); localStorage.setItem('client', res.headers.get('client')); localStorage.setItem('uid', res.headers.get('uid')); // Redirect to your React password reset form component });Verify your CORS configuration
Make sure your Rails CORS initializer (config/initializers/cors.rb) allows the custom auth headers that Devise Token Auth uses. If these headers aren’t exposed, your React app can’t capture them, and subsequent requests will fail. Your CORS setup should include:Rails.application.config.middleware.insert_before 0, Rack::Cors do allow do origins 'your-react-app-domain' # e.g., 'http://localhost:3000' resource '*', headers: :any, methods: [:get, :post, :put, :patch, :delete, :options, :head], expose: ['access-token', 'client', 'uid'] # Critical for token persistence end endCheck Devise Token Auth initializer and User model
Confirm password reset is enabled in yourdevise_token_auth.rbinitializer:config.enable_password_reset = true config.reset_password_within = 6.hours # Adjust timeout as neededAlso, make sure your User model includes the
:recoverableDevise module (required for password resets):class User < ApplicationRecord devise :database_authenticatable, :registerable, :recoverable, :rememberable, :validatable include DeviseTokenAuth::Concerns::User endDig into server logs for clues
Don’t skip this! Your Rails server logs will tell you exactly why the submission is failing—whether it’s a password validation error, missing parameter, or invalid token. In your React app, log the full response from the form submission request too; a 422 Unprocessable Entity response will include error messages in the body that point directly to the issue.
内容的提问来源于stack exchange,提问作者Jay

