Skip to content

Commit 909dcc6

Browse files
committed
Polish gh-15554
Closes gh-15398
1 parent 33976d0 commit 909dcc6

File tree

3 files changed

+51
-33
lines changed

3 files changed

+51
-33
lines changed

docs/modules/ROOT/pages/servlet/authentication/architecture.adoc

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -195,7 +195,11 @@ image::{figures}/providermanagers-parent.png[]
195195
By default, `ProviderManager` tries to clear any sensitive credentials information from the `Authentication` object that is returned by a successful authentication request.
196196
This prevents information, such as passwords, being retained longer than necessary in the `HttpSession`.
197197

198-
> **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.
198+
[NOTE]
199+
====
200+
The `CredentialsContainer` interface plays a critical role in the authentication process.
201+
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.
202+
====
199203

200204
This may cause issues when you use a cache of user objects, for example, to improve performance in a stateless application.
201205
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.
@@ -249,21 +253,21 @@ image:{icondir}/number_3.png[] If authentication fails, then __Failure__.
249253
* The <<servlet-authentication-securitycontextholder>> is cleared out.
250254
* `RememberMeServices.loginFail` is invoked.
251255
If remember me is not configured, this is a no-op.
252-
See the javadoc:org.springframework.security.web.authentication.rememberme.package-summary[] package.
256+
See the javadoc:org.springframework.security.web.authentication.rememberme.package-summary[rememberme] package.
253257
* `AuthenticationFailureHandler` is invoked.
254258
See the javadoc:org.springframework.security.web.authentication.AuthenticationFailureHandler[] interface.
255259

256260
image:{icondir}/number_4.png[] If authentication is successful, then __Success__.
257261

258262
* `SessionAuthenticationStrategy` is notified of a new login.
259-
See the {security-api-url}org/springframework/security/web/authentication/session/SessionAuthenticationStrategy.html[`SessionAuthenticationStrategy`] interface.
263+
See the javadoc:org.springframework.security.web.authentication.session.SessionAuthenticationStrategy[] interface.
260264
* The <<servlet-authentication-authentication>> is set on the <<servlet-authentication-securitycontextholder>>.
261265
Later, if you need to save the `SecurityContext` so that it can be automatically set on future requests, `SecurityContextRepository#saveContext` must be explicitly invoked.
262266
See the javadoc:org.springframework.security.web.context.SecurityContextHolderFilter[] class.
263267

264268
* `RememberMeServices.loginSuccess` is invoked.
265269
If remember me is not configured, this is a no-op.
266-
See the javadoc:org.springframework.security.web.authentication.rememberme.package-summary[] package.
270+
See the javadoc:org.springframework.security.web.authentication.rememberme.package-summary[rememberme] package.
267271
* `ApplicationEventPublisher` publishes an `InteractiveAuthenticationSuccessEvent`.
268272
* `AuthenticationSuccessHandler` is invoked.
269273
See the javadoc:org.springframework.security.web.authentication.AuthenticationSuccessHandler[] interface.

docs/modules/ROOT/pages/servlet/authentication/passwords/erasure.adoc

Lines changed: 23 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,41 @@
11
== Password Erasure
22

3-
After successful authentication, it's a security best practice to erase credentials from memory to prevent them from being exposed to potential memory dump attacks. `ProviderManager` and most `AuthenticationProvider` implementations in Spring Security support this practice through the `eraseCredentials` method, which should be invoked after the authentication process completes.
3+
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.
4+
`ProviderManager` in Spring Security supports this practice through the `eraseCredentials` method, which should be invoked after the authentication process is complete.
45

56
=== Best Practices
67

7-
. *Immediate Erasure*: Credentials should be erased immediately after they are no longer needed. This minimizes the window during which the credentials are exposed in memory.
8-
. *Automatic Erasure*: Configure `ProviderManager` to automatically erase credentials post-authentication by setting `eraseCredentialsAfterAuthentication` to `true`.
9-
. *Custom Erasure Strategies*: Implement custom erasure strategies in custom `AuthenticationProvider` implementations if the default erasure behavior does not meet specific security requirements.
8+
* *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.
9+
* *Automatic Erasure*: Configure `ProviderManager` to automatically erase credentials post-authentication by setting `eraseCredentialsAfterAuthentication` to `true` (the default).
10+
* *Custom Erasure Strategies*: Implement custom erasure strategies in custom `AuthenticationManager` implementations if the default erasure behavior does not meet specific security requirements.
1011

1112
=== Risk Assessment
1213

1314
Failure to properly erase credentials can lead to several risks:
1415

15-
. *Memory Access Attacks*: Attackers can access raw credentials from memory through exploits like buffer overflow attacks or memory dumps.
16-
. *Insider Threats*: Malicious insiders with access to systems could potentially extract credentials from application memory.
17-
. *Accidental Exposure*: In multi-tenant environments, lingering credentials in memory could accidentally be exposed to other tenants.
16+
* *Memory Access Attacks*: Attackers can access raw credentials from memory through exploits like buffer overflow attacks or memory dumps.
17+
* *Insider Threats*: Malicious insiders with access to systems could potentially extract credentials from application memory.
18+
* *Accidental Exposure*: In multi-tenant environments, lingering credentials in memory could accidentally be exposed to other tenants.
1819

1920
=== Implementation
2021

2122
[source,java]
2223
----
23-
public class CustomAuthenticationProvider extends AbstractUserDetailsAuthenticationProvider {
24-
@Override
25-
protected void additionalAuthenticationChecks(UserDetails userDetails,
26-
UsernamePasswordAuthenticationToken authentication)
27-
throws AuthenticationException {
28-
// Perform authentication checks
29-
if (!passwordEncoder.matches(authentication.getCredentials().toString(), userDetails.getPassword())) {
30-
throw new BadCredentialsException(messages.getMessage(
31-
"AbstractUserDetailsAuthenticationProvider.badCredentials",
32-
"Bad credentials"));
33-
}
34-
35-
// Erase credentials post-check
36-
authentication.eraseCredentials();
37-
}
24+
public class CustomAuthenticationManager implements AuthenticationManager {
25+
26+
@Override
27+
public Authentication authenticate(Authentication authenticationRequest)
28+
throws AuthenticationException {
29+
30+
Authentication authenticationResult;
31+
// TODO: Perform authentication checks...
32+
33+
// Erase credentials post-check
34+
if (authenticationResult instanceof CredentialsContainer container) {
35+
container.eraseCredentials();
36+
}
37+
}
38+
3839
}
3940
----
4041

docs/modules/ROOT/pages/servlet/authentication/passwords/user-details.adoc

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,37 +6,50 @@ The xref:servlet/authentication/passwords/dao-authentication-provider.adoc#servl
66

77
== Credentials Management
88

9-
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.
9+
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.
10+
This practice enhances security by ensuring that sensitive data, such as passwords, are not retained in memory longer than necessary.
1011

11-
=== When to Implement CredentialsContainer
12+
[TIP]
13+
====
14+
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.
15+
This can help prevent the cached instance containing credentials from being referenced by the rest of the application once the authentication process is complete.
16+
====
1217

13-
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.
18+
=== When to Implement `CredentialsContainer`
19+
20+
Applications that do not employ caching mechanisms for `UserDetails` should particularly consider implementing `CredentialsContainer`.
21+
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.
1422

1523
[source,java]
1624
----
1725
public class MyUserDetails implements UserDetails, CredentialsContainer {
26+
1827
private String username;
28+
1929
private String password;
2030
2131
// UserDetails implementation...
2232
2333
@Override
2434
public void eraseCredentials() {
25-
this.password = null; // Securely erase the password field
35+
this.password = null; // Securely dereference the password field
2636
}
37+
2738
}
2839
----
2940

3041
=== Implementation Guidelines
3142

3243
* *Immediate Erasure*: Credentials should be erased immediately after they are no longer needed, typically post-authentication.
33-
* *Automatic Invocation*: Ensure that `eraseCredentials()` is automatically called by your authentication framework, such as `AuthenticationManager` or `AuthenticationProvider`, once the authentication process is complete.
44+
* *Automatic Invocation*: Ensure that `eraseCredentials()` is automatically called by your authentication framework, such as `AuthenticationManager`, once the authentication process is complete.
3445
* *Consistency*: Apply this practice uniformly across all applications to prevent security lapses that could lead to data breaches.
3546

3647
=== Beyond Basic Interface Implementation
3748

38-
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 `AuthenticationProvider`'s contract, does not perform credential erasure within its own `authenticate` method.
49+
While interfaces like `CredentialsContainer` provide a framework for credential management, the practical implementation often depends on specific classes and their interactions.
3950

40-
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 authentication process itself should not assume the responsibility for credential management. It is worth noting that the `AuthenticationManager` API documentation specifies that the implementation should return "a fully authenticated object including credentials" via the `authenticate` method, underscoring the distinction between authentication and credential management.
51+
For example, the `DaoAuthenticationProvider` class, adhering to the contract of `AuthenticationProvider`, does not perform credential erasure within its own `authenticate` method.
52+
Instead, it relies on `ProviderManager`—Spring Security's default implementation of `AuthenticationManager`—to handle the erasure of credentials and other sensitive data post-authentication.
53+
This separation emphasizes the principle that the `AuthenticationProvider` should not assume the responsibility for credentials management.
4154

4255
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.

0 commit comments

Comments
 (0)