-
Notifications
You must be signed in to change notification settings - Fork 1.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
@resource.allow_password_change is not persisted across requests #481
Comments
I suppose we can fix that without flag persistence by passing While using custom passwords controller
That will change interface for PUT /auth/passwords, requiring to pass |
I added a simple |
This seems to be the same as #526 I should probably close mine |
@paulius005 using some flag param is less secure, as one may update password without knowing old password or reset token, which should not happen as I suppose. That does not look like serious issue as user still must be authorized at this point, but reusing reset token instead of flag solves it anyway, so why not use it. |
Yep! Agreed |
Having this same issue, but none of the fixes mentioned here worked for me. Using the master branch of device token auth and rails 5 beta 3. |
I extended @biomancer's solution a bit to support URLs with already existing parameters: Update Due to the resource class Api::PasswordsController < DeviseTokenAuth::PasswordsController
def edit
super do
redirect_url = URI.parse(params[:redirect_url])
reset_params = {reset_password_token: @resource.reset_password_token}
redirect_url.query = Rack::Utils.parse_query(redirect_url.query).merge(reset_params).to_query
params[:redirect_url] = redirect_url.to_s
# Devise's reset_password_by_token sets the @resource's +reset_password_token+ attribute
# to its raw value after performing a database lookup. Due to devise_token_auth's +save!+
# to persist the newly generate auth token, the raw value is written to the database.
# This causes a recovery link to be only valid once, even if no new password was specified
# as well as an inconsistency to Device's use of `token_generator.digest`
@resource.reset_password_token = Devise.token_generator.digest(@resource, :reset_password_token,
@resource.reset_password_token)
@resource.save(validate: false)
end
end
protected
def resource_update_method
# Only allow setting a new password without specifying the current one if the user
# is currently in the middle of a password recovery process and the client passed
# in his current +password_reset_token+
@resource.allow_password_change = valid_reset_password_token?
super
end
#
# Checks whether a password reset token is given and if it matches the current user
#
def valid_reset_password_token?
return false if @resource.reset_password_token.blank? || @resource.reset_password_token.blank?
digest = Devise.token_generator.digest(@resource, :reset_password_token, resource_params[:reset_password_token])
digest == @resource.reset_password_token
end
end |
I tested the above solutions suggested by @stex and @biomancer. The problem still persisted for me. So, I decided to add an additional persistent allow password change field to user model. My solution is: class AddPersistentAllowPasswordChangeToUsers < ActiveRecord::Migration
def change
add_column :users, :persistent_allow_password_change, :boolean, null: false, default: false, after: :reset_password_sent_at
end
end Then, I override passwords controller of module Api
module V1
module Overrides
class PasswordsController < DeviseTokenAuth::PasswordsController
def edit
super do |resource|
resource.persistent_allow_password_change = true
resource.save!
end
end
def update
super do |resource|
resource.persistent_allow_password_change = false
resource.save!
end
end
protected
def resource_update_method
@resource.allow_password_change = @resource.persistent_allow_password_change
super
end
end
end
end
end And, I changed devise_token_auth routes in mount_devise_token_auth_for 'User', at: 'auth', controllers: {
sessions: 'api/v1/overrides/sessions',
omniauth_callbacks: 'api/v1/overrides/omniauth_callbacks',
registrations: 'api/v1/overrides/registrations',
passwords: 'api/v1/overrides/passwords'
} With this solution, every time user redirected from reset password email to application, when edit action of |
Sounds like we have an accepted solution here, so closing this for now! |
Is it fixed upstream in some released version? |
@sickrandir it might be, we are testing this release right now: which is the latest. If not feel free to submit a pull request! |
@zachfeldman thanx. I installed 0.1.43.beta1 and I can confirm that it fixes this issue for me. |
That's great! |
My application is set to require current_password when users want to change their password.
The problem is when an user wants to reset the password. After the mail is sent and the user is prompted to insert the new password, the server returns 422 with the error: "current_password can't be blank".
I'm using v0.1.37.beta4, and this version contains a pull request: d33bcdb
which is supposed to fix this problem, but it doesn't.
I guess the problem here is that @resource.allow_password change is set to true in projects_controller#edit but it's not persisted to the DB, and in the next call (projcets_controller#update) its value is false again.
I made a quick and dirty fix to store allow_password to the DB, though I'm not sure it's a good solution because this means changing the generators too....
I don't have the time to implement tests, so I didn't even open the PR. However, you can see the changes here Chosko@e3a4d3d.
The text was updated successfully, but these errors were encountered: