Reputation: 83
I'm having what may be a simple problem and I cant seem to find a way to fix it though I did find where it is.
What I am trying to do is set up devise password reset with devise_token_auth. I have the email set up with the token generator, and the email links to the end points '/api/auth/passwords/edit'
which validates the token and then redirects to my front end password reset form (done in reactjs if it matters), the issue arrises when I actually submit the form, I'm sending the token, I'm also sending the password and confirmation, expiry, uid and all the other headers.
so heres the issue, the devise passwords controller calls the before action set_user_by_token, and i found through some debugging that this is where the issue lies, I created and override module with the default code for the set_users_by_token, and through the use of binding.pry I saw that no values were coming in through the method call, but the method was being called because it hit the pry.
heres the method code
def set_user_by_token(mapping=nil)
# determine target authentication class
rc = resource_class(mapping)
# no default user defined
return unless rc
# gets the headers names, which was set in the initialize file
uid_name = DeviseTokenAuth.headers_names[:'uid']
access_token_name = DeviseTokenAuth.headers_names[:'access-token']
client_name = DeviseTokenAuth.headers_names[:'client']
# parse header for values necessary for authentication
uid = request.headers[uid_name] || params[uid_name]
@token ||= request.headers[access_token_name] || params[access_token_name]
@client_id ||= request.headers[client_name] || params[client_name]
# client_id isn't required, set to 'default' if absent
@client_id ||= 'default'
# check for an existing user, authenticated via warden/devise, if enabled
if DeviseTokenAuth.enable_standard_devise_support
binding.pry
devise_warden_user = warden.user(rc.to_s.underscore.to_sym)
if devise_warden_user && devise_warden_user.tokens[@client_id].nil?
@used_auth_by_token = false
@resource = devise_warden_user
# REVIEW: The following line _should_ be safe to remove;
# the generated token does not get used anywhere.
# @resource.create_new_auth_token
end
end
# user has already been found and authenticated
return @resource if @resource && @resource.is_a?(rc)
# ensure we clear the client_id
if !@token
@client_id = nil
return
end
return false unless @token
# mitigate timing attacks by finding by uid instead of auth token
user = uid && rc.find_by(uid: uid)
if user && user.valid_token?(@token, @client_id)
# sign_in with bypass: true will be deprecated in the next version of Devise
if self.respond_to?(:bypass_sign_in) && DeviseTokenAuth.bypass_sign_in
bypass_sign_in(user, scope: :user)
else
sign_in(:user, user, store: false, event: :fetch, bypass: DeviseTokenAuth.bypass_sign_in)
end
return @resource = user
else
# zero all values previously set values
@client_id = nil
return @resource = nil
end
end
here at the very end its hitting the else and returning resource as nil since no other conditions were met.
Any help would be really appreciated, I'm pretty sure this is where the problems is because I've been debugging for days and this is where it lead me
Upvotes: 1
Views: 1409
Reputation: 83
if youre here because you had the same issue i did hopefully i can help! after hours of grueling debugging and testing I overcame, it might be a workaround or crappy way to do it but it works while still using the devise method.
in your passwords_controller.rb there should be a "before_action :set_user_by_token, only: => [:update]"
change ":set_user_by_token" to what ever you want to name this new method we're going to make, then copy and paste the method in the original post and make some minor changes.
change these lines:
uid = request.headers[uid_name] || params[uid_name]
@token ||= request.headers[access_token_name] || params[access_token_name]
@client_id ||= request.headers[client_name] || params[client_name]
to
uid = params[uid_name]
@token ||= params[access_token_name]
@client_id ||= params[client_name]
and done. now you dont have to mess with any initializers or concers!
hopefully I helped somebody!
Upvotes: 1