Rails - Devise - Disable Reset Password Token expiration time - ruby-on-rails

I currently working on a Rails app with devise authentication. I need to disabled the token expiration for reset password. According to Devise Documentation on Recoverable there is not configuration to do that. The only method I think to make this works is to override Recoverable and the reset_password_period_valid? function to always return true. But I not sure if is the best/proper solution.
Current on my devise.rb I have:
# ==> Configuration for :recoverable
#
# Defines which key will be used when recovering the password for an account
# config.reset_password_keys = [ :email ]
# Time interval you can reset your password with a reset password key.
# Don't put a too small interval or your users won't have the time to
# change their passwords.
config.reset_password_within = 2.hours

You can set it as 10 years, for example, and it will be like disabled token expiration.

Related

reset_password_sent_at assignment for devise

The issue is that devise is checking the reset_password_sent_at when a user clicks on the link to reset their password (from an email) and when trying to reset (in the form) an error occurs:
Reset password token has expired, please request a new one
Meaning, "when a reset_password_token is generated, #user.reset_password_sent_at needs to be set to Time.now, or else when devise runs #user.reset_password_period_valid? to find out if the reset token is still valid, it will get nil and assume the token has expired."
What I don't understand is how and where to assign reset_password_sent_at to Time.now
Do I need to assign Time.now through the console to all Users? If so, How would I do that?
Or, is it a before_create (or something else) that I need to assign Time.now to reset_password_sent_at? If so, how and where should I do this?
You don't need to worry about reset_password_sent_at; that is something devise will take care of setting correctly when a reset_password is sent to the user.
reset_password_sent_at works in conjunction with the reset_password_within parameter, set in the config/initializers/devise.rb file. It should look something like this:
config.reset_password_within = 2.hours
Most likely it is set to nil or 0, and that is making the application throw the password reset token has expired method.

Devise allows blank password during password reset

I have a Rails 3.2 app setup with Devise. Everything works great except for when I reset a password ( via the built in routes and methods ), Devise is allowing a blank password. It will validate the length and if it matches the confirmation if there is at least one character. I do have it setup where in a users account they can update their profile without entering the password, but I don't think that has anything to do with resetting the password.
Any help is appreciated.
devise.rb -> http://pastie.org/3911178
user.rb -> http://pastie.org/3911187
Thanks for pointing me in the right direction. The problem was caused by what you described. However, if I let devise handle the validation or use the same code they do, the user must provide a password when updating their account even after they are logged in. To fix this, I just checked for the rest_password_token in my validation:
def password_required?
# If resetting the password
return true if reset_password_token.present? && reset_password_period_valid?
# If the person already has a pass, only validate if they are updating pass
if !encrypted_password.blank?
password.present? || password_confirmation.present?
end
end
*UPDATE
I just updated this to ensure the password token is not expired.
You should let devise handler password validations: https://github.com/plataformatec/devise/blob/master/lib/devise/models/validatable.rb or use the code devise is using for validations.
The issue with your code is that you're doing validations only if the user doesn't has a password set (!encrypted_password.blank?) and other conditions. When recovering the password the user already has a password set so you don't run validations on password updates ...

Have devise timeout a period x after entering a number of wrong passwords?

Would it be possible to have Devise timeout for say 10 minutes if you enter a password wrong 10 times? With timeout I mean it will not be possible to enter a new password for period X and getting a message stating you have to wait.
add :lockable strategy to your model
add config.unlock_strategy = :time
add config.lock_strategy = :failed_attempts
add config.maximum_attempts = 10
add config.unlock_in = 10.minutes to initializers/devise.rb
I didn't see any tutorials or even wiki/FAQs on the devise github account. However the readme does mention the lockable module. See https://github.com/plataformatec/devise/blob/master/lib/devise/models/lockable.rb

set timeout for a token in rails

How do i set a timeout for a given authentication token? After the timeout, the token will be deleted and the user won't be able to use it on his requests.
I'm using rails 3 and devise.
I was looking for this feature too, but didn't find a way to do it directly.
You can reset the authentication token on each sign-in and use the rememberable in-between:
in your application controller, in after_sign_in_path_for():
resource.reset_authentication_token
in devise.rb:
config.remember_for = 1.day
Or you can create a cron-job to periodically clear the invalid authentication_token entries from the users table.
I'm not sure if that's exactly what you are looking for, but this is a simple option in Devise.
If you set the following option in config/initializers/devise.rb
config.timeout_in = 30.minutes
then Devise will expire the token after 30 minutes of inactivity. The same operations that Devise does for session authentication should also work with the authentication_token.
I have used that in my current project and tested it using Timecop gem:
it "should timeout without activity after 30 minutes" do
auth_token = #user.authentication_token
get "/frontend/users/#{#user.id}.json?auth_token=#{auth_token}"
response.status.should == 200
Timecop.travel(45.minutes.from_now)
get "/frontend/users/#{#user.id}.json?auth_token=#{auth_token}"
response.status.should == 401
Timecop.return
end
Also, I don't believe that the token follows the same analogy as user/password combination as mentioned in one of the comments, since you wouldn't store your password in plain text but you do with your token. I would recommend resetting the token after each logout as well.
At devise initializer file
#/config/initializers/devise.rb
# ==> Configuration for :timeoutable
# The time you want to timeout the user session without activity. After this
# time the user will be asked for credentials again. Default is 30 minutes.
config.timeout_in = 1.day
# If true, expires auth token on session timeout.
config.expire_auth_token_on_timeout = true

Devise Remember Me and Sessions

I'm confused with the devise gem config settings:
# The time the user will be remembered without asking for credentials again.
config.remember_for = 2.weeks
# The time you want to timeout the user session without activity. After this
# time the user will be asked for credentials again.
config.timeout_in = 10.minutes
I want to have a user select the "Remember Me" checkbox (i.e., keep me logged in), but the default session timeout is 10 minutes. After 10 minutes it asks me to log in again even though I have clicked "Remember me". If this is true then the remember_for is really meaningless. Obviously I'm missing something here.
Ryan is correct in that the default Devise gem does not support both the :rememberable and :timeoutable options. However, like all things Ruby, if you don't like the decision that some other coder has made, especially when it strays from the norm that most users are likely to expect, then you can simply override it.
Thanks to a (rejected) pull request we can override this behaviour by adding the following code to the top of your Devise config file (/config/initializers/devise.rb):
module Devise
module Models
module Timeoutable
# Checks whether the user session has expired based on configured time.
def timedout?(last_access)
return false if remember_exists_and_not_expired?
last_access && last_access <= self.class.timeout_in.ago
end
private
def remember_exists_and_not_expired?
return false unless respond_to?(:remember_expired?)
remember_created_at && !remember_expired?
end
end
end
end
This will now allow you to configure both options and have them work as you would expect.
config.remember_for = 2.weeks
config.timeout_in = 30.minutes
The timeout_in will automatically log you out within 10 minutes of inactivity and is incompatible with the remember_me checkbox. You can have one, but not both.
The information in previous answers is outdated. I've tested my project, which uses Rails 4 and Devise 3.5.1 and also checked devise code to be sure.
Now it looks whether Remember Me checkbox was checked:
if yes, it checks if remember_exists_and_not_expired, so basically uses config.remember_for for session management
if no, it checks if last_access <= timeout_in.ago, using config.timeout_in correspondingly

Resources