This issue is part of #2371629: [meta] Finalize Session and User Authentication API and #2047951: [META] Remove calls to deprecated global $user and $GLOBALS['user']
Problem/Motivation
The coupling of the 'current_user' service to AuthenticationManager creates a circular dependency that makes it difficult to implement alternative authentication schemes like basic_auth (see #2283637: Session for an authenticated user can only be set by Cookie AuthenticationProvider). The current_user
service originally was a synthetic service that caused problems. #2180109: Change the current_user service to a proxy fixed these problems by
a) introducing a transparent proxy around the actual user object in order to remove the requirement to declare it synthetic and
b)introducing on-demand authentication (i.e. user authentication is triggered as soon as a method is called on the current_user
object).
However, in order to solve the problems a) is sufficient. b), however, introduces the possibility of user authentication with different authentication methods at multiple points in the request/response cycle e.g. when the container is rebuilt during tests or when enabling/disabling modules. If there are credentials for multiple authentication methods on one request (e.g. a developer logged into a site, testing some requests with token authentication), the behavior of the authentication system is hard to predict (see #104).
Authentication must only be performed once during the request / response cycle. User authentication requires checking the credentials sent along with the initial HTTP request based on a pre-selected authentication method.
The current system allows for a mix of multiple authentication methods. Because not all of them are equally secure, the system needs to support the restriction of authentication methods to only a subset of the site. This is especially true for HTTP basic authentication or URL token based authentication which are commonly used for machine-to-machine communication.
On a 403 (access denied), if there are no credentials on the request, some authentication methods (e.g. basic auth) require that a challenge is sent to the client. For obvious reasons this functionality also needs to be restricted to those routes where such providers are active.
Currently this dilemma is resolved by resetting authentication from within AuthenticationEnhancer
if there is a mismatch between the allowed authentication methods and the chosen one. In order to minimize the opportunity for security problems, it would be better to simply bail out and deny access in this case.
Proposed resolution
- Remove the on-demand authentication of the current user in
AccountProxy::setAccount()
and implement authentication in anEventSubscriber
that runs before language processing, routing and any other consumer of thecurrent_user
service. This provides a single point of entry for authentication which is easier to audit and control. This effectively removes the dependency of thecurrent_user
service on the authentication manager and the request object. - Remove the
AuthenticationEnhancer
and replace it with an additional request listener on theAuthenticationSubscriber
. The new listener runs after routing and filters the selected authentication provider according to the list of allowed providers specified in the_auth
option of the current route. ThrowsAccessDeniedHttpException
exception if it detects a mismatch. - Make sure that all implementers of
AuthenticationProviderInterface
respect the liskov substitution principle, i.e.AuthenticationManager
should not be a special flower, neither shouldBasicAuth
or theCookie
provider. Also ensure thatAuthenticationSubscriber
accepts anyAuthenticationProviderInterface
.
Remaining tasks
Reviews and commit.
User interface changes
None
API changes
AuthenticationManagerInterface
is completely removedAuthenticationProviderInterface
methods removed:cleanup()
(dead code)handleException() (moved to new <code>AuthenticationProviderChallengeInterface
)
AuthenticationEnhancer
replaced by implementors ofAuthenticationProviderFilterInterface
, called fromAuthenticationSubscriber
Beta phase evaluation
Issue priority | Critical |
---|---|
Prioritized changes | The main goal of this issue is security and reducing brittleness. |
Disruption | Mildly disruptive for core/contributed/custom modules |