Skip to content

Commit efdd412

Browse files
committed
Store Only Password Action
In all likelihood, the only thing needed at the database level is the action that an admin requires be taken for a password.
1 parent cbc61bf commit efdd412

File tree

17 files changed

+89
-89
lines changed

17 files changed

+89
-89
lines changed

config/src/main/java/org/springframework/security/config/annotation/web/configurers/PasswordManagementConfigurer.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -106,8 +106,8 @@ public void init(B http) throws Exception {
106106

107107
ChangePasswordAdvisor changePasswordAdvisor = (this.changePasswordAdvisor != null) ? this.changePasswordAdvisor
108108
: this.context.getBeanProvider(ChangePasswordAdvisor.class)
109-
.getIfUnique(() -> CompositeChangePasswordAdvisor
110-
.of(new UserDetailsChangePasswordAdvisor(), new ChangeCompromisedPasswordAdvisor()));
109+
.getIfUnique(() -> CompositeChangePasswordAdvisor.of(new UserDetailsChangePasswordAdvisor(),
110+
new ChangeCompromisedPasswordAdvisor()));
111111

112112
http.setSharedObject(ChangePasswordAdviceRepository.class, changePasswordAdviceRepository);
113113
http.setSharedObject(UserDetailsPasswordManager.class, passwordManager);

config/src/test/java/org/springframework/security/config/annotation/web/configurers/PasswordManagementConfigurerTests.java

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
import org.springframework.mock.web.MockHttpSession;
3232
import org.springframework.security.authentication.password.ChangePasswordAdvice;
3333
import org.springframework.security.authentication.password.ChangePasswordAdvisor;
34+
import org.springframework.security.authentication.password.PasswordAction;
3435
import org.springframework.security.authentication.password.UserDetailsPasswordManager;
3536
import org.springframework.security.config.Customizer;
3637
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
@@ -223,7 +224,8 @@ UserDetailsService users() {
223224
String adminPassword = UUID.randomUUID().toString();
224225
UserDetails compromised = PasswordEncodedUser.user();
225226
UserDetails admin = PasswordEncodedUser.withUserDetails(PasswordEncodedUser.admin())
226-
.password(adminPassword).build();
227+
.password(adminPassword)
228+
.build();
227229
return new InMemoryUserDetailsManager(compromised, admin);
228230
}
229231

@@ -243,24 +245,23 @@ static class AdminController {
243245
}
244246

245247
@GetMapping("/advice/{username}")
246-
ResponseEntity<ChangePasswordAdvice> requireChangePassword(@PathVariable("username") String username) {
248+
ResponseEntity<PasswordAction> requireChangePassword(@PathVariable("username") String username) {
247249
UserDetails user = this.users.loadUserByUsername(username);
248250
if (user == null) {
249251
return ResponseEntity.notFound().build();
250252
}
251-
return ResponseEntity.ok(user.getChangePasswordAdvice());
253+
return ResponseEntity.ok(user.getPasswordAction());
252254
}
253255

254256
@PostMapping("/expire/{username}")
255-
ResponseEntity<ChangePasswordAdvice> expirePassword(@PathVariable("username") String username) {
257+
ResponseEntity<PasswordAction> expirePassword(@PathVariable("username") String username) {
256258
UserDetails user = this.users.loadUserByUsername(username);
257259
if (user == null) {
258260
return ResponseEntity.notFound().build();
259261
}
260-
ChangePasswordAdvice advice = () -> ChangePasswordAdvice.Action.MUST_CHANGE;
261-
this.passwords.savePasswordAdvice(user, advice);
262+
this.passwords.savePasswordAction(user, PasswordAction.MUST_CHANGE);
262263
URI uri = URI.create("/admin/passwords/advice/" + username);
263-
return ResponseEntity.created(uri).body(advice);
264+
return ResponseEntity.created(uri).body(PasswordAction.MUST_CHANGE);
264265
}
265266

266267
}
@@ -270,11 +271,9 @@ static class HomeController {
270271

271272
private final UserDetailsPasswordManager passwords;
272273

273-
private final ChangePasswordAdvisor changePasswordAdvisor =
274-
new ChangeCompromisedPasswordAdvisor();
274+
private final ChangePasswordAdvisor changePasswordAdvisor = new ChangeCompromisedPasswordAdvisor();
275275

276-
private final ChangePasswordAdviceRepository changePasswordAdviceRepository =
277-
new HttpSessionChangePasswordAdviceRepository();
276+
private final ChangePasswordAdviceRepository changePasswordAdviceRepository = new HttpSessionChangePasswordAdviceRepository();
278277

279278
private final PasswordEncoder encoder = PasswordEncoderFactories.createDelegatingPasswordEncoder();
280279

@@ -291,13 +290,14 @@ ChangePasswordAdvice index(ChangePasswordAdvice advice) {
291290
ResponseEntity<?> changePassword(@AuthenticationPrincipal UserDetails user,
292291
@RequestParam("password") String password, HttpServletRequest request, HttpServletResponse response) {
293292
ChangePasswordAdvice advice = this.changePasswordAdvisor.advise(user, password);
294-
if (advice.getAction() != ChangePasswordAdvice.Action.ABSTAIN) {
293+
if (advice.getAction() != PasswordAction.ABSTAIN) {
295294
return ResponseEntity.badRequest().body(advice);
296295
}
297296
this.passwords.updatePassword(user, this.encoder.encode(password));
298297
this.changePasswordAdviceRepository.removePasswordAdvice(request, response);
299298
return ResponseEntity.ok().build();
300299
}
300+
301301
}
302302

303303
}

core/src/main/java/org/springframework/security/authentication/password/ChangeLengthPasswordAdvisor.java

Lines changed: 18 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616

1717
package org.springframework.security.authentication.password;
1818

19-
import org.springframework.security.authentication.password.ChangePasswordAdvice.Action;
2019
import org.springframework.security.core.userdetails.UserDetails;
2120

2221
public class ChangeLengthPasswordAdvisor implements ChangePasswordAdvisor {
@@ -25,9 +24,9 @@ public class ChangeLengthPasswordAdvisor implements ChangePasswordAdvisor {
2524

2625
private final int maxLength;
2726

28-
private Action tooShortAction = Action.MUST_CHANGE;
27+
private PasswordAction tooShortAction = PasswordAction.MUST_CHANGE;
2928

30-
private Action tooLongAction = Action.SHOULD_CHANGE;
29+
private PasswordAction tooLongAction = PasswordAction.SHOULD_CHANGE;
3130

3231
public ChangeLengthPasswordAdvisor(int minLength) {
3332
this(minLength, Integer.MAX_VALUE);
@@ -49,29 +48,30 @@ public ChangePasswordAdvice advise(UserDetails user, String password) {
4948
return ChangePasswordAdvice.ABSTAIN;
5049
}
5150

52-
public void setTooShortAction(Action tooShortAction) {
51+
public void setTooShortAction(PasswordAction tooShortAction) {
5352
this.tooShortAction = tooShortAction;
5453
}
5554

56-
public void setTooLongAction(Action tooLongAction) {
55+
public void setTooLongAction(PasswordAction tooLongAction) {
5756
this.tooLongAction = tooLongAction;
5857
}
5958

6059
public static final class TooShortAdvice implements ChangePasswordAdvice {
61-
private final Action action;
60+
61+
private final PasswordAction action;
6262

6363
private final int minLength;
6464

6565
private final int actualLength;
6666

67-
private TooShortAdvice(Action action, int minLength, int actualLength) {
67+
private TooShortAdvice(PasswordAction action, int minLength, int actualLength) {
6868
this.action = action;
6969
this.minLength = minLength;
7070
this.actualLength = actualLength;
7171
}
7272

7373
@Override
74-
public Action getAction() {
74+
public PasswordAction getAction() {
7575
return this.action;
7676
}
7777

@@ -85,30 +85,28 @@ public int getActualLength() {
8585

8686
@Override
8787
public String toString() {
88-
return "TooShort [" +
89-
"action=" + this.action +
90-
", minLength=" + this.minLength +
91-
", actualLength=" + this.actualLength +
92-
"]";
88+
return "TooShort [" + "action=" + this.action + ", minLength=" + this.minLength + ", actualLength="
89+
+ this.actualLength + "]";
9390
}
9491

9592
}
9693

9794
public static final class TooLongAdvice implements ChangePasswordAdvice {
98-
private final Action action;
95+
96+
private final PasswordAction action;
9997

10098
private final int maxLength;
10199

102100
private final int actualLength;
103101

104-
private TooLongAdvice(Action action, int maxLength, int actualLength) {
102+
private TooLongAdvice(PasswordAction action, int maxLength, int actualLength) {
105103
this.action = action;
106104
this.maxLength = maxLength;
107105
this.actualLength = actualLength;
108106
}
109107

110108
@Override
111-
public Action getAction() {
109+
public PasswordAction getAction() {
112110
return this.action;
113111
}
114112

@@ -122,11 +120,10 @@ public int getActualLength() {
122120

123121
@Override
124122
public String toString() {
125-
return "TooLong [" +
126-
"action=" + this.action +
127-
", maxLength=" + this.maxLength +
128-
", actualLength=" + this.actualLength +
129-
"]";
123+
return "TooLong [" + "action=" + this.action + ", maxLength=" + this.maxLength + ", actualLength="
124+
+ this.actualLength + "]";
130125
}
126+
131127
}
128+
132129
}

core/src/main/java/org/springframework/security/authentication/password/ChangePasswordAdvice.java

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -18,14 +18,8 @@
1818

1919
public interface ChangePasswordAdvice {
2020

21-
ChangePasswordAdvice ABSTAIN = () -> Action.ABSTAIN;
21+
ChangePasswordAdvice ABSTAIN = () -> PasswordAction.ABSTAIN;
2222

23-
Action getAction();
24-
25-
enum Action {
26-
27-
ABSTAIN, SHOULD_CHANGE, MUST_CHANGE
28-
29-
}
23+
PasswordAction getAction();
3024

3125
}

core/src/main/java/org/springframework/security/authentication/password/CompositeChangePasswordAdvisor.java

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ public ChangePasswordAdvice advise(UserDetails user, String password) {
4444

4545
public static final class Advice implements ChangePasswordAdvice {
4646

47-
private final Action action;
47+
private final PasswordAction action;
4848

4949
private final Collection<ChangePasswordAdvice> advice;
5050

@@ -53,8 +53,8 @@ private Advice(Collection<ChangePasswordAdvice> advice) {
5353
this.advice = advice;
5454
}
5555

56-
private Action findMostUrgentAction(Collection<ChangePasswordAdvice> advice) {
57-
Action mostUrgentAction = Action.ABSTAIN;
56+
private PasswordAction findMostUrgentAction(Collection<ChangePasswordAdvice> advice) {
57+
PasswordAction mostUrgentAction = PasswordAction.ABSTAIN;
5858
for (ChangePasswordAdvice a : advice) {
5959
if (mostUrgentAction.ordinal() < a.getAction().ordinal()) {
6060
mostUrgentAction = a.getAction();
@@ -64,7 +64,7 @@ private Action findMostUrgentAction(Collection<ChangePasswordAdvice> advice) {
6464
}
6565

6666
@Override
67-
public Action getAction() {
67+
public PasswordAction getAction() {
6868
return this.action;
6969
}
7070

@@ -74,11 +74,9 @@ public Collection<ChangePasswordAdvice> getAdvice() {
7474

7575
@Override
7676
public String toString() {
77-
return "Composite [" +
78-
"action=" + this.action +
79-
", advice=" + this.advice +
80-
"]";
77+
return "Composite [" + "action=" + this.action + ", advice=" + this.advice + "]";
8178
}
79+
8280
}
8381

8482
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
package org.springframework.security.authentication.password;
2+
3+
public enum PasswordAction {
4+
5+
ABSTAIN, SHOULD_CHANGE, MUST_CHANGE
6+
7+
}

core/src/main/java/org/springframework/security/authentication/password/UserDetailsChangePasswordAdvisor.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ public final class UserDetailsChangePasswordAdvisor implements ChangePasswordAdv
2222

2323
@Override
2424
public ChangePasswordAdvice advise(UserDetails user, String password) {
25-
return user.getChangePasswordAdvice();
25+
return user::getPasswordAction;
2626
}
2727

2828
}

core/src/main/java/org/springframework/security/authentication/password/UserDetailsPasswordManager.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,6 @@
2121

2222
public interface UserDetailsPasswordManager extends UserDetailsPasswordService {
2323

24-
void savePasswordAdvice(UserDetails user, ChangePasswordAdvice advice);
24+
void savePasswordAction(UserDetails user, PasswordAction action);
2525

2626
}

core/src/main/java/org/springframework/security/core/userdetails/User.java

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@
3232
import org.apache.commons.logging.LogFactory;
3333
import org.jspecify.annotations.Nullable;
3434

35-
import org.springframework.security.authentication.password.ChangePasswordAdvice;
35+
import org.springframework.security.authentication.password.PasswordAction;
3636
import org.springframework.security.core.CredentialsContainer;
3737
import org.springframework.security.core.GrantedAuthority;
3838
import org.springframework.security.core.SpringSecurityCoreVersion;
@@ -82,7 +82,7 @@ public class User implements UserDetails, CredentialsContainer {
8282

8383
private final boolean enabled;
8484

85-
private final ChangePasswordAdvice changePasswordAdvice;
85+
private final PasswordAction passwordAction;
8686

8787
/**
8888
* Calls the more complex constructor with all boolean arguments set to {@code true}.
@@ -118,7 +118,7 @@ public User(String username, @Nullable String password, boolean enabled, boolean
118118
this.accountNonExpired = accountNonExpired;
119119
this.credentialsNonExpired = credentialsNonExpired;
120120
this.accountNonLocked = accountNonLocked;
121-
this.changePasswordAdvice = ChangePasswordAdvice.ABSTAIN;
121+
this.passwordAction = PasswordAction.ABSTAIN;
122122
this.authorities = Collections.unmodifiableSet(sortAuthorities(authorities));
123123
}
124124

@@ -129,7 +129,7 @@ public User(UserDetails user) {
129129
this.accountNonExpired = user.isAccountNonExpired();
130130
this.credentialsNonExpired = user.isCredentialsNonExpired();
131131
this.accountNonLocked = user.isAccountNonLocked();
132-
this.changePasswordAdvice = user.getChangePasswordAdvice();
132+
this.passwordAction = user.getPasswordAction();
133133
this.authorities = Collections.unmodifiableSet(sortAuthorities(user.getAuthorities()));
134134
}
135135

@@ -169,8 +169,8 @@ public boolean isCredentialsNonExpired() {
169169
}
170170

171171
@Override
172-
public ChangePasswordAdvice getChangePasswordAdvice() {
173-
return this.changePasswordAdvice;
172+
public PasswordAction getPasswordAction() {
173+
return this.passwordAction;
174174
}
175175

176176
@Override

core/src/main/java/org/springframework/security/core/userdetails/UserDetails.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121

2222
import org.jspecify.annotations.Nullable;
2323

24-
import org.springframework.security.authentication.password.ChangePasswordAdvice;
24+
import org.springframework.security.authentication.password.PasswordAction;
2525
import org.springframework.security.core.Authentication;
2626
import org.springframework.security.core.GrantedAuthority;
2727

@@ -103,8 +103,8 @@ default boolean isEnabled() {
103103
return true;
104104
}
105105

106-
default ChangePasswordAdvice getChangePasswordAdvice() {
107-
return ChangePasswordAdvice.ABSTAIN;
106+
default PasswordAction getPasswordAction() {
107+
return PasswordAction.ABSTAIN;
108108
}
109109

110110
}

0 commit comments

Comments
 (0)