Spring Security AuthenticationProvider

`AuthenticationProvider` contains the authentication logic for a particular kind of credential. It receives an `Authentication` request, validates it, and returns an authenticated `Authentication` object or signals that authentication cannot be performed.

In Spring Security, an `AuthenticationProvider` is a strategy for authenticating one or more credential types. Its main method is `authenticate(Authentication authentication)`, which examines the supplied credentials and either produces an authenticated result, returns `null` when another provider should try, or throws an `AuthenticationException` when authentication fails.

The `supports(Class<?> authentication)` method tells Spring Security which `Authentication` implementations a provider can process. This lets a provider be selected based on the authentication request type, such as `UsernamePasswordAuthenticationToken`.

A common provider is `DaoAuthenticationProvider`, which authenticates username/password requests using a `UserDetailsService` and `PasswordEncoder`. Applications can also define custom providers for specialized credentials, such as an API token or another authentication mechanism.

`ProviderManager` commonly coordinates one or more `AuthenticationProvider` instances. It can try suitable providers in sequence until one authenticates the request or the authentication attempt ultimately fails. The provider itself should focus on validating its supported credential type rather than managing the entire security filter chain.

Key points

Interview questions

What is the purpose of `AuthenticationProvider` in Spring Security?

`AuthenticationProvider` defines how a particular kind of authentication request is verified. Its `authenticate()` method performs the credential validation and returns an authenticated `Authentication` on success. The `supports()` method tells Spring which authentication token type the provider can handle. This separates authentication mechanisms from the components that collect the credentials.

What is the difference between `authenticate()` and `supports()`?

`supports()` answers whether a provider knows how to process a particular `Authentication` class. `authenticate()` actually attempts to validate the credentials contained in the request. Therefore, `supports()` is about applicability, while `authenticate()` is about authentication itself. A provider should not use `supports()` as a substitute for credential validation.

What should an `AuthenticationProvider` return when authentication succeeds?

It should return an authenticated `Authentication` object representing the successfully verified principal. The returned object can contain the principal and appropriate granted authorities. It should not simply return the original unauthenticated request token without establishing its authenticated state correctly. The exact token type depends on the authentication mechanism.

Why can an application configure multiple `AuthenticationProvider` implementations?

Different providers can handle different authentication mechanisms or credential types. For example, one provider might process username/password authentication while another handles an API-key token. A `ProviderManager` can coordinate these providers and delegate a request to an appropriate provider. This makes authentication mechanisms modular rather than forcing all credential validation into one class.

When would you create a custom `AuthenticationProvider`?

A custom provider is useful when the application's credential type or verification process is not adequately represented by an existing provider. Examples include a proprietary token, a specialized external authentication protocol, or a domain-specific credential. The provider should define a clear `Authentication` token contract and limit itself to authentication concerns. Existing Spring Security providers should generally be reused when they already match the required mechanism.