janko / rodauth-rails

Rails integration for Rodauth authentication framework
https://github.com/jeremyevans/rodauth
MIT License
565 stars 40 forks source link

Is rodauth deleting keys from my session? #301

Closed jesseduffield closed 1 month ago

jesseduffield commented 1 month ago

I've got an intermittent issue where it appears that some keys that I've set in my session are being deleted, and I suspect rodauth may be the culprit. I can go from having the following keys in my session:

[
    [0] "session_id",
    [1] "customer_account_id",
    [2] "customer_active_session_id",
    [3] "customer_authenticated_by",
    [4] "customer_two_factor_auth_setup",
    [5] "my_key",
    [6] "my_key_2"
]

To having my_key and my_key_2 removed. I suspect that rodauth is clearing the session and re-setting its own values in the session, such that my own session values are cleared too.

Here's my RodauthApp:

class RodauthApp < Rodauth::Rails::App
  configure RodauthCustomerPortal, :customer_portal
  configure RodauthAdminPortal, :admin_portal

  route do |r|
    rodauth(:customer_portal).check_active_session
    rodauth(:admin_portal).check_active_session

    r.rodauth(:customer_portal)
    r.rodauth(:admin_portal)
  end
end

And here's my rudimentary test that rodauth is capable of clearing my session internally (Using the clear_session method which I've found from looking at the rodauth codebase:

class RodauthApp < Rodauth::Rails::App
  configure RodauthCustomerPortal, :customer_portal
  configure RodauthAdminPortal, :admin_portal

  route do |r|
    rodauth(:customer_portal).check_active_session
    rodauth(:admin_portal).check_active_session

    session[:test] = "test"
    ap session.keys
    rodauth(:customer_portal).clear_session
    ap session.keys

    r.rodauth(:customer_portal) # route customer rodauth requests
    r.rodauth(:admin_portal) # route admin rodauth requests
  end
end

Which spits out:

[
    [0] "session_id",
    [1] "test"
]

[
    [0] "session_id"
]

I'd like to know:

Thanks!

janko commented 1 month ago

Yes, that's expected behavior, Rodauth clears the entire session when on login and logout. This is to prevent session fixation attacks, see https://guides.rubyonrails.org/security.html#session-fixation-countermeasures.

As far as I know, Devise/Warden also resets the session on logout, though it doesn't seem to do it on login.

jesseduffield commented 1 month ago

Thanks for the fast response. Although what's confusing is that this does not occur on login or logout: my user is already logged in, and after the issue, my user is still able to click around the app fine.

I'm not sure whether it makes a difference but I notice the issue as part of an oauth flow with another app i.e. when a user adds an integration in our app, we redirect them to the relevant site, then when that site redirects the browser to our callback endpoint, it seems our session state has disappeared (but the rodauth-specific session state is still there). I don't know whether the fact that the user has returned from another site makes a difference; it's just that this is the only flow in our site that involves manually setting session keys (for the sake of oauth state comparison in the callback endpoint) and so naturally it's in this flow that we discover this strange behaviour.

I'm wondering if perhaps the session is being periodically reset by rodauth as part of some kind of intermittent process, e.g. checking if the session is still active. Maybe occasionally the oauth callback endpoint on my end is hit at the same time that rodauth resets the session.

EDIT: For example, I'm using the active sessions feature and I can see in rodauth's code that sometimes it clears the session right before setting it again: https://github.com/jeremyevans/rodauth/blob/ec8be20e8a42f2988be429dda30aa84974124083/lib/rodauth/features/active_sessions.rb#L123 I don't fully understand what's happening in that code though

janko commented 1 month ago

If you still stay logged in when this happens, then it doesn't seem to me like active_sessions is responsible for this behavior. The #check_active_session call clears the session hash when the active session expires, and then redirects.

Have you tried disabling active_sessions and seeing if it still happens? Does it currently happen consistently? Without knowing the details of the OAuth flow and a minimal example that reproduces the issue, I don't think I'll be able to pinpoint the issue.

I'll convert this into a discussion, because it doesn't appear to be a bug in rodauth-rails.