From 36f1de945f229b66080025c81353173db12da92e Mon Sep 17 00:00:00 2001 From: Josh Cummings <3627351+jzheaux@users.noreply.github.com> Date: Fri, 22 Aug 2025 15:21:13 -0600 Subject: [PATCH] Add OneTimeTokenAuthentication Closes gh-17799 --- .../security/SerializationSamples.java | 3 + ....ott.OneTimeTokenAuthentication.serialized | Bin 0 -> 775 bytes .../ott/OneTimeTokenAuthentication.java | 56 ++++++++++++++++++ .../OneTimeTokenAuthenticationProvider.java | 3 +- .../ott/OneTimeTokenAuthenticationToken.java | 14 +++++ ...imeTokenReactiveAuthenticationManager.java | 6 +- 6 files changed, 77 insertions(+), 5 deletions(-) create mode 100644 config/src/test/resources/serialized/7.0.x/org.springframework.security.authentication.ott.OneTimeTokenAuthentication.serialized create mode 100644 core/src/main/java/org/springframework/security/authentication/ott/OneTimeTokenAuthentication.java diff --git a/config/src/test/java/org/springframework/security/SerializationSamples.java b/config/src/test/java/org/springframework/security/SerializationSamples.java index 18c60a72c0..e946012dce 100644 --- a/config/src/test/java/org/springframework/security/SerializationSamples.java +++ b/config/src/test/java/org/springframework/security/SerializationSamples.java @@ -78,6 +78,7 @@ import org.springframework.security.authentication.jaas.event.JaasAuthentication import org.springframework.security.authentication.jaas.event.JaasAuthenticationSuccessEvent; import org.springframework.security.authentication.ott.DefaultOneTimeToken; import org.springframework.security.authentication.ott.InvalidOneTimeTokenException; +import org.springframework.security.authentication.ott.OneTimeTokenAuthentication; import org.springframework.security.authentication.ott.OneTimeTokenAuthenticationToken; import org.springframework.security.authentication.password.CompromisedPasswordException; import org.springframework.security.authorization.AuthorityAuthorizationDecision; @@ -400,6 +401,8 @@ final class SerializationSamples { }); generatorByClassName.put(OneTimeTokenAuthenticationToken.class, (r) -> applyDetails(new OneTimeTokenAuthenticationToken("username", "token"))); + generatorByClassName.put(OneTimeTokenAuthentication.class, + (r) -> applyDetails(new OneTimeTokenAuthentication("username", authentication.getAuthorities()))); generatorByClassName.put(AccessDeniedException.class, (r) -> new AccessDeniedException("access denied", new RuntimeException())); generatorByClassName.put(AuthorizationServiceException.class, diff --git a/config/src/test/resources/serialized/7.0.x/org.springframework.security.authentication.ott.OneTimeTokenAuthentication.serialized b/config/src/test/resources/serialized/7.0.x/org.springframework.security.authentication.ott.OneTimeTokenAuthentication.serialized new file mode 100644 index 0000000000000000000000000000000000000000..6cec2620acf2e695451d3c92b17cc1a16f859491 GIT binary patch literal 775 zcmb7?zfK!L5XR?h2V(xk3KCL^P=$mdIxDp+Ly#dl$&!r~DFtZnZg3X%c8}dLK2xC3 zrbtZ+UVx;{Go+w{m!KeZiloTyS&HoxL~L=|+nxR9H}lQcAMn6vc%yXJH>u{byQf)# zeWee4gHca&8u+Y7?@BA0w(|8XEV>Tn`Ot7SUwJ9OC+7^+Yz}g#r}c!TcC8#sSQ_e`Rao zXb6^uAU)!ux~_zqD#V_5LCv}xENRM%m2%b(mYv%50^VXmvd1sa#Y1EwNQ&AmAck!;MB9z ztEZp8v-2W&TTn9m7_$@ryne}j?W46j8yzW)xzDak1Ha9aRA56hNf^6s=f_sbu7Vg= zsg=MhNQ0`xKbch25oIBE3jp* authorities) { + super(authorities); + this.principal = principal; + setAuthenticated(true); + } + + @Override + public Object getPrincipal() { + return this.principal; + } + + @Override + public @Nullable Object getCredentials() { + return null; + } + +} diff --git a/core/src/main/java/org/springframework/security/authentication/ott/OneTimeTokenAuthenticationProvider.java b/core/src/main/java/org/springframework/security/authentication/ott/OneTimeTokenAuthenticationProvider.java index 74da3fc0c4..12c91267db 100644 --- a/core/src/main/java/org/springframework/security/authentication/ott/OneTimeTokenAuthenticationProvider.java +++ b/core/src/main/java/org/springframework/security/authentication/ott/OneTimeTokenAuthenticationProvider.java @@ -56,8 +56,7 @@ public final class OneTimeTokenAuthenticationProvider implements AuthenticationP } try { UserDetails user = this.userDetailsService.loadUserByUsername(consumed.getUsername()); - OneTimeTokenAuthenticationToken authenticated = OneTimeTokenAuthenticationToken.authenticated(user, - user.getAuthorities()); + OneTimeTokenAuthentication authenticated = new OneTimeTokenAuthentication(user, user.getAuthorities()); authenticated.setDetails(otpAuthenticationToken.getDetails()); return authenticated; } diff --git a/core/src/main/java/org/springframework/security/authentication/ott/OneTimeTokenAuthenticationToken.java b/core/src/main/java/org/springframework/security/authentication/ott/OneTimeTokenAuthenticationToken.java index b956a3771a..1f91779e3c 100644 --- a/core/src/main/java/org/springframework/security/authentication/ott/OneTimeTokenAuthenticationToken.java +++ b/core/src/main/java/org/springframework/security/authentication/ott/OneTimeTokenAuthenticationToken.java @@ -40,6 +40,10 @@ public class OneTimeTokenAuthenticationToken extends AbstractAuthenticationToken private @Nullable String tokenValue; + /** + * @deprecated Please use constructor that takes a {@link String} instead + */ + @Deprecated(forRemoval = true, since = "7.0") public OneTimeTokenAuthenticationToken(@Nullable Object principal, String tokenValue) { super(Collections.emptyList()); this.tokenValue = tokenValue; @@ -50,6 +54,10 @@ public class OneTimeTokenAuthenticationToken extends AbstractAuthenticationToken this(null, tokenValue); } + /** + * @deprecated Please use {@link OneTimeTokenAuthentication} instead + */ + @Deprecated(forRemoval = true, since = "7.0") public OneTimeTokenAuthenticationToken(Object principal, Collection authorities) { super(authorities); this.principal = principal; @@ -60,7 +68,9 @@ public class OneTimeTokenAuthenticationToken extends AbstractAuthenticationToken * Creates an unauthenticated token * @param tokenValue the one-time token value * @return an unauthenticated {@link OneTimeTokenAuthenticationToken} + * @deprecated Please use constructor that takes a {@link String} instead */ + @Deprecated(forRemoval = true, since = "7.0") public static OneTimeTokenAuthenticationToken unauthenticated(String tokenValue) { return new OneTimeTokenAuthenticationToken(null, tokenValue); } @@ -70,7 +80,9 @@ public class OneTimeTokenAuthenticationToken extends AbstractAuthenticationToken * @param principal the principal * @param tokenValue the one-time token value * @return an unauthenticated {@link OneTimeTokenAuthenticationToken} + * @deprecated Please use constructor that takes a {@link String} instead */ + @Deprecated(forRemoval = true, since = "7.0") public static OneTimeTokenAuthenticationToken unauthenticated(Object principal, String tokenValue) { return new OneTimeTokenAuthenticationToken(principal, tokenValue); } @@ -80,7 +92,9 @@ public class OneTimeTokenAuthenticationToken extends AbstractAuthenticationToken * @param principal the principal * @param authorities the principal authorities * @return an authenticated {@link OneTimeTokenAuthenticationToken} + * @deprecated Please use {@link OneTimeTokenAuthentication} instead */ + @Deprecated(forRemoval = true, since = "7.0") public static OneTimeTokenAuthenticationToken authenticated(Object principal, Collection authorities) { return new OneTimeTokenAuthenticationToken(principal, authorities); diff --git a/core/src/main/java/org/springframework/security/authentication/ott/reactive/OneTimeTokenReactiveAuthenticationManager.java b/core/src/main/java/org/springframework/security/authentication/ott/reactive/OneTimeTokenReactiveAuthenticationManager.java index da97cec2fc..1c62c03689 100644 --- a/core/src/main/java/org/springframework/security/authentication/ott/reactive/OneTimeTokenReactiveAuthenticationManager.java +++ b/core/src/main/java/org/springframework/security/authentication/ott/reactive/OneTimeTokenReactiveAuthenticationManager.java @@ -22,6 +22,7 @@ import reactor.core.publisher.Mono; import org.springframework.security.authentication.ReactiveAuthenticationManager; import org.springframework.security.authentication.ott.InvalidOneTimeTokenException; +import org.springframework.security.authentication.ott.OneTimeTokenAuthentication; import org.springframework.security.authentication.ott.OneTimeTokenAuthenticationToken; import org.springframework.security.core.Authentication; import org.springframework.security.core.userdetails.ReactiveUserDetailsService; @@ -59,10 +60,9 @@ public final class OneTimeTokenReactiveAuthenticationManager implements Reactive .map(onSuccess(otpAuthenticationToken)); } - private Function onSuccess(OneTimeTokenAuthenticationToken token) { + private Function onSuccess(OneTimeTokenAuthenticationToken token) { return (user) -> { - OneTimeTokenAuthenticationToken authenticated = OneTimeTokenAuthenticationToken.authenticated(user, - user.getAuthorities()); + OneTimeTokenAuthentication authenticated = new OneTimeTokenAuthentication(user, user.getAuthorities()); authenticated.setDetails(token.getDetails()); return authenticated; };