Skip to content
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

DisabledSessionError when using authenticate_user! api only #5443

Open
mbackermann opened this issue Dec 21, 2021 · 21 comments
Open

DisabledSessionError when using authenticate_user! api only #5443

mbackermann opened this issue Dec 21, 2021 · 21 comments
Assignees

Comments

@mbackermann
Copy link

mbackermann commented Dec 21, 2021

Pre Check

  • Create a new Rails 7 app rails new test_app --api
  • Add devise
  • run rails g devise:install
  • run rails g devise User
  • POST to /users and see the error stated below

Environment

  • Ruby 3.0.0
  • Rails 7.0.0
  • Devise 4.8.1

Current behavior

When using authenticate_user! on a controller on a rails API only app I am getting the following error:
ActionDispatch::Request::Session::DisabledSessionError (Your application has sessions disabled. To write to the session you must first configure a session store):

Expected behavior

It should throw fail or success on warden depending on if the user is signed in or not.

@mbackermann
Copy link
Author

More context: Before Rails 7, the session passed to warden was a Hash. So even if the session was disabled, we were still able to write to the hash. Now, the session is an ActionDispatch::Session object, which is not writable on Rails API only apps, because the ActionDispatch::Session is disabled.

@morenocarullo
Copy link

morenocarullo commented Jan 11, 2022

I understand that Devise relies heavily on warden etc which rely on sessions, or a fake version of it at least. Thus, we've circumvented this by creating this concern/module that we have included in the relevant Devise-related controllers in our app:

module RackSessionFixController
  extend ActiveSupport::Concern

  class FakeRackSession < Hash
    def enabled?
      false
    end
  end

  included do
    before_action :set_fake_rack_session_for_devise
    
    private

    def set_fake_rack_session_for_devise
      request.env['rack.session'] ||= FakeRackSession.new
    end
  end
end

if the devise maintainers like it, we (AKA me or my team) can integrate this into Devise itself (E.g. allowing that logic to happen when API-mode is enabled) and expand the testsuite accordingly.

@carlosantoniodasilva WDYT ?

@arpu
Copy link

arpu commented Jan 22, 2022

@morenocarullo i use Rails.application.config.session_store :disabled
and have the same Problem can you provide your FakeRakeSession Example?

@morenocarullo
Copy link

@arpu you need to drop that module I wrote in my earlier comment and include it in the SessionControllers. If @carlosantoniodasilva or other maintainer can suggest their acceptance, I can for sure make it included in devise itself so that it's automatic.

@arpu
Copy link

arpu commented Jan 24, 2022

reference rails change rails/rails#42231

@souzagab
Copy link

I understand that Devise relies heavily on warden etc which rely on sessions, or a fake version of it at least. Thus, we've circumvented this by creating this concern/module that we have included in the relevant Devise-related controllers in our app:

module RackSessionFixController
  extend ActiveSupport::Concern

  class FakeRackSession < Hash
    def enabled?
      false
    end
  end

  included do
    before_action :set_fake_rack_session_for_devise
    
    private

    def set_fake_rack_session_for_devise
      request.env['rack.session'] ||= FakeRackSession.new
    end
  end
end

if the devise maintainers like it, we (AKA me or my team) can integrate this into Devise itself (E.g. allowing that logic to happen when API-mode is enabled) and expand the testsuite accordingly.

@carlosantoniodasilva WDYT ?

Thanks a lot for the help @morenocarullo.

I am using this resolution while the issue is not resolved

@connortorrell
Copy link

Any update on when this will be fixed?

@morenocarullo
Copy link

@connortorrell you can use the solution posted here. I'm waiting for maintainers to say they'll accept the PR -- before it stays there forever

@NfoCipher
Copy link

Did they accept the PR?

@morenocarullo
Copy link

@NfoCipher I was waiting for an OK here to create the PR. BUT, since I got no answer ... I'll create the PR so that at least people can have a branch to point to, and will push to make it merged..

@KidA001
Copy link

KidA001 commented Feb 15, 2022

Thank you @morenocarullo, using your fix as well. +1 for getting an official fix merged

@morenocarullo
Copy link

FYI, I am preparing a PR for this issue. To begin with, we'll have a fork with the fix applied which is slightly better than the module-drop-in there, but I really want to make it upstream into the official branch.

@morenocarullo
Copy link

PR is here: #5474

Feel free to use the referenced branch/fork while we wait for it to be merged.

@NfoCipher
Copy link

This: waiting-for-dev/devise-jwt#235 (comment)
also seems to work.

@VictorRubia
Copy link

Hi, I am facing this error Minitest::UnexpectedError: ActionDispatch::Request::Session::DisabledSessionError: Your application has sessions disabled. To write to the session you must first configure a session store in testing environment. I am trying to do a simple assertion like

  test "should get index" do
    sign_in users(:one)
    get movies_url, as: :json
    assert_response :success
  end

but even having both workarounds (the one in application.rb and the other having RackSessionFix.rb) is not working.

Any ideas? Thanks.

@england
Copy link

england commented Dec 5, 2022

As described in https://github.com/wardencommunity/warden/blob/master/lib/warden/proxy.rb#L167 need to pass store: false to skip serializing into the session.

So adding

  def sign_up(resource_name, resource)
    sign_in(resource_name, resource, store: false)
  end

in your controller inherited from Devise::RegistrationsController should solve the problem

@styliii
Copy link

styliii commented Dec 14, 2022

In case this helps someone, you'll also need to pass in store: false for logging in.

This needs to be added to the controller inherited from Devise::SessionsController

  def auth_options
    super.merge({store: false})
  end

@thibpoullain
Copy link

thibpoullain commented Mar 2, 2023

Hi, any new about a fix ? Thx :)

This worked for me :

# application.rb

config.session_store :cookie_store, key: '_interslice_session'
    config.middleware.use ActionDispatch::Cookies
    config.middleware.use config.session_store, config.session_options

@carlosantoniodasilva
Copy link
Member

No news :), but thanks for putting it into my radar again, I'll try to take a better look at the problem and the proposed solution(s) here. Thanks.

juanarias93 added a commit to wyeworks/finder that referenced this issue Aug 26, 2023
`authenticate_user!`

  * This is a known issue reported here: heartcombo/devise#5443
  * There's also an open PR to devise for fixing it: heartcombo/devise#5474
  * If the PR gets merged eventually, this fix/patch won't be necessary
    anymore.
@sidevesh
Copy link

Any reason this is still held up ?

@fabianprado
Copy link

I'm using v1.2.3 with Rails 7.1, for me the workaround was pretty simple: setting bypass_sign_in as false, to avoid call to Devise's bypass_sign_in (which uses session).
If you see https://github.com/lynndylanhurley/devise_token_auth/blob/6b0659f18c678b319913d0fb053e96aa555857aa/app/controllers/devise_token_auth/concerns/set_user_by_token.rb#L92 it actually uses store: false.

Of course for those who needs bypass_sign_in as true, this is still an issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

No branches or pull requests