Open JanBussieck opened 5 years ago
Hi @JanBussieck, thanks for reporting this.
I've tested the following possible scenarios:
expire_all_remember_me_on_sign_out
is true
:authenticatable_salt
Works correctly 👍
remember_token
Works correctly 👍
expire_all_remember_me_on_sign_out
is false
:authenticatable_salt
Works correctly 👍
remember_token
It doesn't work 👎
I believe your scenario is the last one, right?
Unfortunately, I don't know the historical reasons why this approach was followed. After looking at the original pull request it seems like the scenario with remember_token
was never mentioned. I think it might have got forgotten since the default is authenticable_salt
.
Regarding the security concerns, I'm not sure what they were since the cookie is going to be signed by Rails using secret_key_base
or similar. Maybe @diegorv can help us here.
In any case, this already happens for the authenticable_salt
case. Now, this case might be seen as more secure since authenticable_salt
uses part of the encrypted_password
column - which is the hashed password.
So, in conclusion, I think this is definitely an inconsistency in Devise since it works for one case but not for the other. And I think it's better to fix it - i.e. dot not clean the remember_token
when expire_all_remember_me_on_sign_out
is false
. We can add documentation to advise users that they should implement some logic to generate unique remember_token
s that don't contain sensitive information about their users and I think that should be enough.
Thoughts?
Hi @tegon, thanks for your response and the additional clarity you provided. That is exactly the problem I encountered.
As far as I can see, the advantage over using a remember_token
over the authenticable_salt
is that it is regenerated every time a new remember-me-session is created, which means that if a remember-me-cookie were to be hijacked it would only be usable for one session, whereas a remember-me-cookie containing the authenticatable_salt
as token will remain valid for future sessions unless the user changes their password.
I could imagine that the reasoning behind not resetting the remember_token
is that it would require a user to log out on all devises in order to invalidate the current remember-me-session.
Since the remember-me-session is stored on disk rather than in memory (and thus offering more vectors of attack for cookie hijacking), there are some approaches that recommend regenerating the token every time the cookie is used to authenticate the user. While providing additional security, this would imply that a user could not stay logged in on several devices (or even browsers) at once. A potential way to tackle the problem might be to store remember-me-data (i.e. token and timestamps) in a separate table referencing the user and create a separate entry for every session.
I am not really sure, just spit balling ideas at this point.
Hi @tegon 👋
I try to handle (maybe) related issue, but there's no information about expire_all_remember_me_on_sign_out
in Rememberable doc.
Could be nice to add info to doc - the default value for expire_all_remember_me_on_sign_out
is true (look like it should be true)
Then I don't get this scenario:
remember_token
expire_all_remember_me_on_sign_out
is true
# config/initializers/devise.rb
...
config.timeout_in = 2.hours
config.remember_for = 1.day
config.expire_all_remember_me_on_sign_out = true
remember_user_token
is still valid.
Should I add sth more to my initializers?
Current behavior
When I set
expire_all_remember_me_on_sign_out = false
in the devise config, but I am using aremember_token
(instead of defaulting to theauthenticatable_salt
), then I will still be logged out on all devices.Expected behavior
I will only be logged out on the device where I initiate the log out and still be remembered on other devises.
This happens since the
remember_token
is reset regardless of whether theexpire_all_remember_me_on_sign_out
is set or not: https://github.com/plataformatec/devise/blob/master/lib/devise/models/rememberable.rb#L60This was previously addressed in this issue: https://github.com/plataformatec/devise/issues/3236
where @josevalim mentions:
Given that that is the case why enable this option at all? Especially considering that it doesn't work as expected. Thanks in advance and thanks for your work on this great gem.