Before
Before this change, the first access to the current user implicitly started the authentication process. Because routes can decide which authentication providers are allowed (for example, only basic authentication for REST requests), a re-authentication could happen with a limited set of providers. If a user tried to authenticate with basic authentication on a route that did not allow it, the authentication first succeeded but was dropped in the middle of the request and continued as an anonymous user with the cookie provider.
This was hard to understand and contained security risk, as code couldn't rely on the current user.
After
Now, the authentication is explicit and only ever happens once. Routes can still control which providers are allowed and we have to run the authentication before the routing, but the difference is that now, if you try to access a page that does not allow basic_auth with basic authentication credentials, you will get an access denied. Even if the route would allow access to anonymous users.
If you want to access the current user in a REQUEST or similar event, you have to run after the AuthenticationSubscriber:
// The priority for authentication must be higher than the highest event
// subscriber accessing the current user. Especially it must be higher than
// LanguageRequestSubscriber as LanguageManager accesses the current user if
// the language module is enabled.
$events[KernelEvents::REQUEST][] = ['onKernelRequestAuthenticate', 300];
Additional API changes/additions:
-
AuthenticationManagerInterface
is removed. Instead you probably want to typehint toAuthenticationProviderInterface
- If your authentication provider should just be applied to a subset of a site, implement
\Drupal\Core\Authentication\AuthenticationProviderFilterInterface
- In case your code needs to send some special HTTP response in order to let users authenticate (classical example: basic_auth), you can implement
\Drupal\Core\Authentication\AuthenticationProviderChallengeInterface
- It is possible to change the global providers (those that are allowed if no
_auth
option is set on routes) by setting the theglobal
flag on the provider definition) - Previously the
provider_id
was derived from the service id of a provider, now theprovider_id
needs to be specified explicitly on the service definition.