NoMethodError with admin mode feature and sessionless authentication
Only relevant when activating the :user_mode_in_session
feature flag.
Calling one of the sessionless authentication endpoints, e.g. RSS feed, will throw a NoMethodError
due to the session being nil
. The current admin mode code expects Session.current
to be present.
Since gitlab-foss!29146 (merged), it is enforced for sessionless for this to be nil
on purpose, also checked in specs. Unclear at the moment how to solve this properly.
curl --header "Private-Token: <hidden>" http://localhost:3000/auser.atom
Trace:
NoMethodError - undefined method `[]=' for nil:NilClass:
lib/gitlab/namespaced_session_store.rb:5:in `[]='
lib/gitlab/auth/current_user_mode.rb:31:in `enable_admin_mode!'
app/controllers/concerns/sessionless_authentication.rb:36:in `enable_admin_mode!'
lib/gitlab/middleware/rails_queue_duration.rb:27:in `call'
lib/gitlab/metrics/rack_middleware.rb:17:in `block in call'
lib/gitlab/metrics/transaction.rb:62:in `run'
lib/gitlab/metrics/rack_middleware.rb:17:in `call'
lib/gitlab/request_profiler/middleware.rb:17:in `call'
lib/gitlab/query_limiting/middleware.rb:17:in `block in call'
lib/gitlab/query_limiting/transaction.rb:39:in `run'
lib/gitlab/query_limiting/middleware.rb:16:in `call'
ee/lib/gitlab/jira/middleware.rb:19:in `call'
lib/gitlab/middleware/go.rb:20:in `call'
lib/gitlab/etag_caching/middleware.rb:13:in `call'
lib/gitlab/middleware/correlation_id.rb:16:in `block in call'
lib/gitlab/middleware/correlation_id.rb:15:in `call'
lib/gitlab/middleware/multipart.rb:117:in `call'
lib/gitlab/middleware/read_only/controller.rb:48:in `call'
lib/gitlab/middleware/read_only.rb:18:in `call'
lib/gitlab/middleware/basic_health_check.rb:25:in `call'
lib/gitlab/request_context.rb:32:in `call'
config/initializers/fix_local_cache_middleware.rb:9:in `call'
lib/gitlab/middleware/static.rb:11:in `call'
lib/gitlab/webpack/dev_server_middleware.rb:27:in `perform_request'
lib/gitlab/metrics/requests_rack_middleware.rb:49:in `call'
lib/gitlab/middleware/release_env.rb:12:in `call'
Originally discussed in #35717 (comment 258121077):
@ifarkas @reprazent While reviewing and looking for solutions for the sidekiq workers, I found out that currently admin mode is not working properly for sessionless authentication (e.g. atom feeds), though CI passes.
I (wrongly) assumed that even in the case of sessionless authentication I'd have an empty, not synced to redis session for Gitlab::Session.current, but that is nil on purpose per gitlab-foss!29146 (merged) (merged), there's even a spec making sure of that. Because of that, when I request e.g. curl --header "Private-Token: " http://localhost:3000/someuser.atom, this will throw an exception because CurrentUserMode depends on the session existing under Gitlab::Session.current. I thought about adding a state sessionless to CurrentUserMode to tackle it, but this would be local to the instantiated class, and would not work with the policies, which instantiate a new CurrentUserMode.
The whole idea behind CurrentUserMode is dependent on having a session where to store the state, even if we make it up as an empty hash, such as we do for the API calls in api_guard.rb. But seeing gitlab-foss!29146 (merged) (merged) I'm starting to wonder if this is even a good idea. We were thinking on extending the PAT tokens for API calls by adding a new flag property admin-mode when creating them, so that you could choose if your token allowed admin mode or not. I'm a bit lost right now with this issue, would be very happy if you could take a bit more time to evaluate in detail and give me some hints, since you know the internals and potential implications much better
🙇