Skip to content

Add Password Advice Support #17118

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 10 commits into
base: main
Choose a base branch
from

Conversation

jzheaux
Copy link
Contributor

@jzheaux jzheaux commented May 15, 2025

This commit adds configuration options to .passwordManagement to allow for additional password management flows:

  1. Show a default change password page and enforce configured password rules
  2. Enforce configured password rules at login time; either request or require that the user change their password accordingly
  3. Allow admin to force password changes

You can activate by publishing a UserDetailsPasswordManager bean and using the PasswordManagement DSL:

@Bean 
UserDetailsService users() {
    // ...
    return new InMemoryUserDetailsManager(...);
}

...
@Bean 
SecurityFilterChain securityFilters(HttpSecurity http) throws Exception {
    http
        // ...
        .passwordManagement(Customizer.withDefaults());

    return http.build();
}

Since these flows require a UserDetailsPasswordManager bean, and because .passwordManagement is a pre-existing DSL, they remain inactive until that bean is provided.

Some things to try:

  • ChangePasswordAdvisor - the PR contains several sample implementations of this interface. They can be composed in DelegatingChangePasswordAdvisor to form a custom set of password requirements. By default, two advisors are active; the compromised password advisor and the password advice advisor checking for any existing advice
  • ChangePasswordAdvice.Action - the existing advisors can be configured to have a different action, for example changing the failure action to Action.MUST_CHANGE instead of Action.SHOULD_CHANGE
  • UserDetailsPasswordManager contains any advice tied to a user. By default, .passwordManagement only checks at login time and when a password changes. However, you can write a ChangePasswordAdviceRepository implementation that checks the UserDetailsPasswordManager on each request so that the user is advised mid-session if changes are needed.

@jzheaux jzheaux marked this pull request as draft May 15, 2025 16:28
@jzheaux jzheaux force-pushed the check-password-advice branch from babcae7 to fb7b323 Compare July 29, 2025 22:44
jzheaux added 5 commits July 30, 2025 13:11
There are now two interfaces, ChangeExistingPasswordAdvisor and
ChangeUpdatingPasswordAdvisor. I have a sense that more information
may be wanted down the road for ChangeUpdatingPasswordAdvisor;
so this would allow them to evolve independently.
- This allow the request matcher to be in the filter,
preventing eager access to the session
@jzheaux jzheaux force-pushed the check-password-advice branch from cae543f to a04035d Compare July 30, 2025 19:12
jzheaux added 5 commits July 30, 2025 19:37
- These aren't super helpful in the end. Applications
can inspect the type and get a richer set of information.
In all likelihood, the only thing needed at the database level
is the action that an admin requires be taken for a password.
- Update Checkstyle
- Simplify Naming
- Add password action to User and UserDetails
- Improved class names
- Introduced defaults to guide usage
Copy link
Member

@rwinch rwinch left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for all of your work on this! I've provided some feedback below. Much of it is related to the sample, which is why I've posted it below rather than inline:

  • Try and reduce (ideally eliminate) the need for HttpServletRequest and HttpServletResponse for arguments to Spring Controllers (e.g. HomeController in the sample). This might be something required for more advanced use cases, but I'd like to try to allow users to follow best practices of not using the request/response in the controllers.
  • Can you demo how to clean up the error message when changing a password? Right now the error message seems like it would be difficult for a user to understand what is going on?
  • What does an application with the minimum amount of effort for a user look like (as many defaults as possible)?
  • I wonder if we can remove PasswordAdvice from the UserDetails. Perhaps managing this on a PasswordAdvisor implementation?
  • Does PasswordAdvisor need a UserDetails or could it use a more narrow scope (e.g. username/password)? I ask because there are likely passwords/secrets that are checked outside of the scope of a User (e.g. a consumer secret). I don't know that we need to solve for all of these use cases now, but somewhat thinking outloud. Note: If we have a rich object as an argument to PasswordAdvisor, we could consider adding an optional UserDetails later.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants