[[servlet-authentication-providermanager]]
= ProviderManager
:figures: images/servlet/authentication/architecture

{security-api-url}org/springframework/security/authentication/ProviderManager.html[`ProviderManager`] is the most commonly used implementation of <<servlet-authentication-authenticationmanager,`AuthenticationManager`>>.
`ProviderManager` delegates to a `List` of <<servlet-authentication-authenticationprovider,``AuthenticationProvider``s>>.
// FIXME: link to AuthenticationProvider
Each `AuthenticationProvider` has an opportunity to indicate that authentication should be successful, fail, or indicate it cannot make a decision and allow a downstream `AuthenticationProvider` to decide.
If none of the configured ``AuthenticationProvider``s can authenticate, then authentication will fail with a `ProviderNotFoundException` which is a special `AuthenticationException` that indicates the `ProviderManager` was not configured support the type of `Authentication` that was passed into it.

image::{figures}/providermanager.png[]

In practice each `AuthenticationProvider` knows how to perform a specific type of authentication.
 For example, one `AuthenticationProvider` might be able to validate a username/password, while another might be able to authenticate a SAML assertion.
This allows each `AuthenticationProvider` to do a very specific type of authentication, while supporting multiple types of authentication and only exposing a single `AuthenticationManager` bean.

`ProviderManager` also allows configuring an optional parent `AuthenticationManager` which is consulted in the event that no `AuthenticationProvider` can perform authentication.
The parent can be any type of `AuthenticationManager`, but it is often an instance of `ProviderManager`.

image::{figures}/providermanager-parent.png[]

In fact, multiple `ProviderManager` instances might share the same parent `AuthenticationManager`.
This is somewhat common in scenarios where there are multiple <<servlet-securityfilterchain,`SecurityFilterChain`>> instances that have some authentication in common (the shared parent `AuthenticationManager`), but also different authentication mechanisms (the different `ProviderManager` instances).

image::{figures}/providermanagers-parent.png[]

[[servlet-authentication-providermanager-erasing-credentials]]
By default `ProviderManager` will attempt to clear any sensitive credentials information from the `Authentication` object which is returned by a successful authentication request.
This prevents information like passwords being retained longer than necessary in the `HttpSession`.

This may cause issues when you are using a cache of user objects, for example, to improve performance in a stateless application.
If the `Authentication` contains a reference to an object in the cache (such as a `UserDetails` instance) and this has its credentials removed, then it will no longer be possible to authenticate against the cached value.
You need to take this into account if you are using a cache.
An obvious solution is to make a copy of the object first, either in the cache implementation or in the `AuthenticationProvider` which creates the returned `Authentication` object.
Alternatively, you can disable the `eraseCredentialsAfterAuthentication` property on `ProviderManager`.
See the {security-api-url}org/springframework/security/authentication/ProviderManager.html[Javadoc] for more information.
