Scenario: As an Administrator I need to invalidate a user's session (log them out) after I update the user's password. This is in accordance with best practices as per https://cheatsheetseries.owasp.org/cheatsheets/Session_Management_Cheat_Sheet.html#Renew_the_Session_ID_After_Any_Privilege_Level_Change
I am using Devise and I saw here https://stackoverflow.com/a/45756884/664675 there is a config to log the user out: config.sign_in_after_reset_password = false
However, I have enabled this config in my devise.rb but the user remains logged in. Not sure why that is?
I am also using Redis as the session_store
Example::Application.config.session_store :cache_store,
key: '_example_session',
secure: true
Is it feasible to delete the particular user's session store from Redis upon Password reset by the Administrator? And if so how could I find their particular session key within Redis?
the flag sign_in_after_reset_password does not relate to logout user at all, sign_in_after_reset_password = false imply that in case a user update his account password by himself then do not automatically sign-in his account again, and that logic happen only on PasswordsController#update.
So you as admin try to change password of another user in a custom controller, of course it's not logout user no matter the value of sign_in_after_reset_password is.
devise use gem warden to logout user (in other word: destroy user session) and warden base on request session not base on database, that mean there's no way an admin can get another user's session to reset, so you can not force logout another user by only devise, you need to handle this feature outside devise (such as add session to user table or a devise hook something like timeoutable)
reference: https://github.com/heartcombo/devise/issues/5262
What you're looking for is the setting sign_in_after_change_password which you should set to false (it defaults to true). The method has a slightly confusing name – it means "should we sign the user in after changing their password" instead of "should the user have to sign in after changing their password".
References:
https://github.com/heartcombo/devise/blob/master/lib/devise.rb#L296-L298
https://github.com/heartcombo/devise/blob/c82e4cf47b02002b2fd7ca31d441cf1043fc634c/app/controllers/devise/registrations_controller.rb#L163-L167
Related
I have a simple rails application that uses devise authentication and I want to prevent a user from login in or requesting for password request or any thing that can grant access to a registered user.
In my user model I have a boolean field that helps me easily determine if the account has been activated or not, the boolean field is called active.
What call back methods can I use to go around this and to check if the user has been activated of not with devise. Thanks
If you mean how you can set your active boolean after a confirmation email, you can override the confirm! method devise gives.
If you need a method to prevent a non active user to login etc., override the new method in the SessionsController.
A user named 'user1' signed in at compter a. Then in another computer b, account 'user1' can't sign in, user1 must logout, then user1 can sign in on computer b.
Is devise support for this?
You can add column into users table, which will indicate if user logged in or no. Set it to true when user logs in, and then false when logs out. On user login check this column if its false, then login your user, otherwise show some notification than somebody else using this account.
To avoid situation when user just closes tab without logging off, make rake task that will logout user after some time
UPD: As #Arjan said, you dont even need rake task, you can use devise's module for this
Is there a way to ask all users to change their passwords upon
logging into a Rails application using Devise authentication? In other words, I'd like a way to "expire" a password, so that the next time a user signs in, they have to change it.
I don't think that Devise can do that out of the box, but i guess it's pretty to do it yourself. What i would do :
Upon user sign in, i would nil out the encrypted_password field of the database.
I would have overriden devise's session controller (responsible for the logins), in order to check whether encrypted_password of a user that tries to log in is nil.
If that was nil, i would redirect them to login, also flashing an error like "Your password has expired. Please create a new one."
I'm using Rail3 with Devise gem. It does a great job when you need to lock user from signing in.
But it works just for new login attempts.
If he is already logged in - it won't sign him out immediately.
Here's is the typical use case:
Given admin user
when detects suspicious activity of certain user he locks it with malicious_user.lock('locking-reason')
% can config/initializers/session_store.rb
AppFoo::Application.config.session_store :cookie_store, :key => '_foo_session'
Given HTTP's statelessness, you can't immediately log out a user because you will need to wait until they make another request to your server. You could get around this via a push service I suppose, but that would be overkill.
My solution would be to add that person to a blacklist and then check if they're on the blacklist whenever they try to access a section intended for logged-on users only. This will render them unable to log on until you decide whether or not their activity is suspicious.
Example:
User is suspected of intolerable activity
Admin wants to check this out, so they temporarily add the user to the blacklist.
User clicks on an area of the page they were currently on when added to the blacklist.
Code checks for loggin status and blacklisted users.
Since the user is blacklisted, they are informed that they need to sign in to access the content
Once the user tries to sign in again you can inform them that their account has been temporarily disabled (or you can do this in the previous step).
perhaps the easiest way would be to redirect the user to the logout action when you lock them so:
malicious_user.lock('locking-reason')
redirect_to '/logout' and return
I'm not familiar with Devise so this may not be the best solution or even possible but it's how I would approach the problem
Use a before_filter in the ApplicationController that will do the following
before_filter :kick_out_blocked_user
protected
def kick_out_blocked_user
unless current_user.try(:active?)
redirect_to destroy_user_session_path
end
end
I use devise with module TokenAuthentication
And it is ok when I unauthenticated and I follow link with ?auth_token= part. Like this:
I follow link: /orders?auth_token=q2a8w6virARzv6B2C1vR where q2a8w6virARzv6B2C1vR is authentication_token of user1. And now I logged in as user1.
But when I logged in as some user via email\password and common sign_in page and then follow such link with auth_token with another user token I unexpectedly stay logged in as first user.
Like this:
I sign in via sign in page. I
fill in email and password of user2.
And now I logged in as user2
I follow link:
/orders?auth_token=q2a8w6virARzv6B2C1vR
where q2a8w6virARzv6B2C1vR is
authentication_token of user1. And I
still logged in as user2 instead of
expected user1.
Is it bug? And what is the best practices to change this behavior to force replace authentication via token?
Rails 3.0.6
Devise 1.2.1
you did uncomment :token_authenticatable in your user model, correct?
Let's do some question necromancy...
Before running stragegies (token_authenticatable, database_authenticatable) Warden first checks if user is already set in current session.
This happens in: https://github.com/hassox/warden/blob/3d653371a2ff594d9965c1dde642c98cd8485e15/lib/warden/proxy.rb#L212
Is action responding /orders query supposed to use only token auth? If so, you can add: before_filter: reset_session (before authorize_user) so that Warden failed to unserialize user from the session and was forced to perform authentication.
[EDIT]
This issue ticket contains reasonable solution: https://github.com/plataformatec/devise/issues/1644