diff --git a/docs/modules/ROOT/nav.adoc b/docs/modules/ROOT/nav.adoc index 2910253d13f..e877ebc10c4 100644 --- a/docs/modules/ROOT/nav.adoc +++ b/docs/modules/ROOT/nav.adoc @@ -40,6 +40,7 @@ ***** xref:servlet/authentication/passwords/jdbc.adoc[JDBC] ***** xref:servlet/authentication/passwords/user-details.adoc[UserDetails] ***** xref:servlet/authentication/passwords/credentials-container.adoc[CredentialsContainer] +***** xref:servlet/authentication/passwords/erasure.adoc[Password Erasure] ***** xref:servlet/authentication/passwords/user-details-service.adoc[UserDetailsService] ***** xref:servlet/authentication/passwords/password-encoder.adoc[PasswordEncoder] ***** xref:servlet/authentication/passwords/dao-authentication-provider.adoc[DaoAuthenticationProvider] diff --git a/docs/modules/ROOT/pages/servlet/authentication/architecture.adoc b/docs/modules/ROOT/pages/servlet/authentication/architecture.adoc index 4757b78ea8d..85306e6c5c2 100644 --- a/docs/modules/ROOT/pages/servlet/authentication/architecture.adoc +++ b/docs/modules/ROOT/pages/servlet/authentication/architecture.adoc @@ -195,6 +195,12 @@ image::{figures}/providermanagers-parent.png[] By default, `ProviderManager` tries to clear any sensitive credentials information from the `Authentication` object that is returned by a successful authentication request. This prevents information, such as passwords, being retained longer than necessary in the `HttpSession`. +[NOTE] +==== +The `CredentialsContainer` interface plays a critical role in the authentication process. +It allows for the erasure of credential information once it is no longer needed, thereby enhancing security by ensuring sensitive data is not retained longer than necessary. +==== + This may cause issues when you use 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, it is no longer possible to authenticate against the cached value. You need to take this into account if you use a cache. @@ -245,7 +251,7 @@ image:{icondir}/number_2.png[] Next, the <> is cleared out. -* `RememberMeServices.loginFail` is invoked.ƒ +* `RememberMeServices.loginFail` is invoked. If remember me is not configured, this is a no-op. See the javadoc:org.springframework.security.web.authentication.rememberme.package-summary[rememberme] package. * `AuthenticationFailureHandler` is invoked. diff --git a/docs/modules/ROOT/pages/servlet/authentication/passwords/erasure.adoc b/docs/modules/ROOT/pages/servlet/authentication/passwords/erasure.adoc new file mode 100644 index 00000000000..aa88652ccc7 --- /dev/null +++ b/docs/modules/ROOT/pages/servlet/authentication/passwords/erasure.adoc @@ -0,0 +1,42 @@ +== Password Erasure + +After successful authentication, it is a security best practice to erase credentials from memory to prevent them from being exposed to potential memory dump attacks. +`ProviderManager` in Spring Security supports this practice through the `eraseCredentials` method, which should be invoked after the authentication process is complete. + +=== Best Practices + +* *Immediate Erasure*: Credentials should be erased immediately after they are no longer needed, which minimizes the window during which the credentials are exposed in memory. +* *Automatic Erasure*: Configure `ProviderManager` to automatically erase credentials post-authentication by setting `eraseCredentialsAfterAuthentication` to `true` (the default). +* *Custom Erasure Strategies*: Implement custom erasure strategies in custom `AuthenticationManager` implementations if the default erasure behavior does not meet specific security requirements. + +=== Risk Assessment + +Failure to properly erase credentials can lead to several risks: + +* *Memory Access Attacks*: Attackers can access raw credentials from memory through exploits like buffer overflow attacks or memory dumps. +* *Insider Threats*: Malicious insiders with access to systems could potentially extract credentials from application memory. +* *Accidental Exposure*: In multi-tenant environments, lingering credentials in memory could accidentally be exposed to other tenants. + +=== Implementation + +[source,java] +---- +public class CustomAuthenticationManager implements AuthenticationManager { + + @Override + public Authentication authenticate(Authentication authenticationRequest) + throws AuthenticationException { + + Authentication authenticationResult; + // TODO: Perform authentication checks... + + // Erase credentials post-check + if (authenticationResult instanceof CredentialsContainer container) { + container.eraseCredentials(); + } + } + +} +---- + +By implementing these practices, organizations can significantly enhance the security of their authentication systems by ensuring that credentials are not left exposed in system memory. diff --git a/docs/modules/ROOT/pages/servlet/authentication/passwords/user-details.adoc b/docs/modules/ROOT/pages/servlet/authentication/passwords/user-details.adoc index 292f119018a..740afc3cf32 100644 --- a/docs/modules/ROOT/pages/servlet/authentication/passwords/user-details.adoc +++ b/docs/modules/ROOT/pages/servlet/authentication/passwords/user-details.adoc @@ -3,3 +3,53 @@ javadoc:org.springframework.security.core.userdetails.UserDetails[] is returned by the xref:servlet/authentication/passwords/user-details-service.adoc#servlet-authentication-userdetailsservice[`UserDetailsService`]. The xref:servlet/authentication/passwords/dao-authentication-provider.adoc#servlet-authentication-daoauthenticationprovider[`DaoAuthenticationProvider`] validates the `UserDetails` and then returns an xref:servlet/authentication/architecture.adoc#servlet-authentication-authentication[`Authentication`] that has a principal that is the `UserDetails` returned by the configured `UserDetailsService`. + +== Credentials Management + +Implementing the `CredentialsContainer` interface in classes that store user credentials, such as those extending or implementing `UserDetails`, is strongly recommended, especially in applications where user details are not cached. +This practice enhances security by ensuring that sensitive data, such as passwords, are not retained in memory longer than necessary. + +[TIP] +==== +In cases where user details are cached, consider creating a copy of the `UserDetails` that does not include credentials and returning the copy in the response from a custom `AuthenticationProvider` instead of the original object. +This can help prevent the cached instance containing credentials from being referenced by the rest of the application once the authentication process is complete. +==== + +=== When to Implement `CredentialsContainer` + +Applications that do not employ caching mechanisms for `UserDetails` should particularly consider implementing `CredentialsContainer`. +This approach helps in mitigating the risk associated with retaining sensitive information in memory, which can be vulnerable to attack vectors such as memory dumps. + +[source,java] +---- +public class MyUserDetails implements UserDetails, CredentialsContainer { + + private String username; + + private String password; + + // UserDetails implementation... + + @Override + public void eraseCredentials() { + this.password = null; // Securely dereference the password field + } + +} +---- + +=== Implementation Guidelines + +* *Immediate Erasure*: Credentials should be erased immediately after they are no longer needed, typically post-authentication. +* *Automatic Invocation*: Ensure that `eraseCredentials()` is automatically called by your authentication framework, such as `AuthenticationManager`, once the authentication process is complete. +* *Consistency*: Apply this practice uniformly across all applications to prevent security lapses that could lead to data breaches. + +=== Beyond Basic Interface Implementation + +While interfaces like `CredentialsContainer` provide a framework for credential management, the practical implementation often depends on specific classes and their interactions. + +For example, the `DaoAuthenticationProvider` class, adhering to the contract of `AuthenticationProvider`, does not perform credential erasure within its own `authenticate` method. +Instead, it relies on `ProviderManager`—Spring Security's default implementation of `AuthenticationManager`—to handle the erasure of credentials and other sensitive data post-authentication. +This separation emphasizes the principle that the `AuthenticationProvider` should not assume the responsibility for credentials management. + +Incorporating `CredentialsContainer` into your `UserDetails` implementation aligns with security best practices, reducing potential exposure to data breaches by minimizing the lifespan of sensitive data in memory.