-
Notifications
You must be signed in to change notification settings - Fork 5.5k
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
Fix bugs in extend_remember_period
#5351
base: main
Are you sure you want to change the base?
Conversation
This PR adds better tests for `extend_remember_period` and tries to better document what the feature is supposed to do. Currently it's not very well specified, and I'm not sure it's behaving as expected. I found https://gitlab.com/gitlab-org/gitlab/-/merge_requests/32730 and heartcombo#3950 (comment) which both describe how the feature should work. To summarise: - if you log in to the application regularly, `extend_remember_period` will keep your session alive - if you *don't* log into the application for a while (longer than `config.remember_for`) you'll get logged out In reality, it looks like what happens is: - if you log in to the application regularly, your session will stay alive for as long as `config.remember_for` - if you *don't* log into the application for a while (longer than `config.remember_for`) you'll stay logged in, as long as your warden session remains intact So this means for example if you keep your browser open for longer than `config.remember_for`, your rememberable cookie will expire, but you'll still be logged in. Currently how `extend_remember_period` works is that it only extends the session when [`Stratgies::Rememberable#authenticate`](https://github.com/heartcombo/devise/blob/master/lib/devise/strategies/rememberable.rb#L30) gets called. This gets called when the user logs in and a strategy is used. But if there's already a user logged in and recognised by warden, then warden [short circuits the strategies](https://github.com/wardencommunity/warden/blob/master/lib/warden/proxy.rb#L334). So the first thing this PR change is to add a hook so that `extend_remember_period` now works on every request. The next bug is that if once `config.remember_for` is up, the user is not currently forgotten.
@@ -127,37 +127,83 @@ def cookie_expires(key) | |||
end | |||
end | |||
|
|||
test 'extends remember period when extend remember period config is true' do |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The tests added in #4039 were incorrect; this assertion was passing because the user was getting logged out (because the test moves backwards in time). Added an assert_response
to confirm this, then refactored the test to be correct.
end | ||
|
||
travel_to 33.months.from_now do | ||
# don't log in for over a year, we get logged out |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm pretty stuck getting this working, because I can't work out a way to get around warden's short circuiting. I think the answer is another hook similar to Timeoutable
but it's getting very messy.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't a timeout be set for these tests?
Otherwise the session itself has not timed out so the user is still logged in.
A valid remember token will prevent the session from timing out or automatically create one if the session doesn't exist. Neither a valid, invalid or expired remember token causes a logout.
Warden::Manager.after_set_user only: :fetch do |record, warden, options| | ||
if record.respond_to?(:extend_remember_me?) && record.extend_remember_me? && | ||
options[:store] != false && warden.authenticated?(options[:scope]) | ||
|
||
Devise::Hooks::Proxy.new(warden).remember_me(record) | ||
end | ||
end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi, I was playing with your fork after realising extend_remember_period
is bugged, but I've run into a problem with it that seems to be linked to this hook.
I have custom User#remember_me!
and User#remember_me?
methods, and I noticed that this hook results in remember_me!
getting called before remember_me?
, meaning that remember_me?
will always return true
when it is tested later in the workflow.
Should this hook's if
condition perhaps test that remember_me?
is true
, and only execute if it is?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This fork 100% isn't working right yet. I've also stopped using devise on the project I needed it for, so I don't have a good memory of the problem here.
If you're having similar issues and want to have a go at fixing them feel free to build off this fork/branch.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
remember_me?
is always true:
def remember_me?
true
end
There's a remember_me_is_active?
in the Rememberable
controller that can check that there's a valid remember cookie for the current user.
This PR adds better tests for
extend_remember_period
and tries to better document what the feature is supposed to do. Currently it's not very well specified, and I'm not sure it's behaving as expected.I found https://gitlab.com/gitlab-org/gitlab/-/merge_requests/32730 and #3950 (comment) which both describe how the feature should work. To summarise:
extend_remember_period
will keep your session aliveconfig.remember_for
) you'll get logged outIn reality, it looks like what happens is:
config.remember_for
config.remember_for
) you'll stay logged in, as long as your warden session remains intactSo this means for example if you keep your browser open for longer than
config.remember_for
, your rememberable cookie will expire, but you'll still be logged in.Currently how
extend_remember_period
works is that it only extends the session whenStratgies::Rememberable#authenticate
gets called. This gets called when the user logs in and a strategy is used. But if there's already a user logged in and recognised by warden, then warden short circuits the strategies.So the first thing this PR change is to add a hook so that
extend_remember_period
now works on every request.The next bug is that if once
config.remember_for
is up, the user is not currently forgotten.