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 0000000000..6cec2620ac Binary files /dev/null and b/config/src/test/resources/serialized/7.0.x/org.springframework.security.authentication.ott.OneTimeTokenAuthentication.serialized differ diff --git a/core/src/main/java/org/springframework/security/authentication/ott/OneTimeTokenAuthentication.java b/core/src/main/java/org/springframework/security/authentication/ott/OneTimeTokenAuthentication.java new file mode 100644 index 0000000000..fc0c806463 --- /dev/null +++ b/core/src/main/java/org/springframework/security/authentication/ott/OneTimeTokenAuthentication.java @@ -0,0 +1,56 @@ +/* + * Copyright 2004-present the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.security.authentication.ott; + +import java.io.Serial; +import java.util.Collection; + +import org.jspecify.annotations.Nullable; + +import org.springframework.security.authentication.AbstractAuthenticationToken; +import org.springframework.security.core.GrantedAuthority; + +/** + * The result of a successful one-time-token authentication + * + * @author Josh Cummings + * @since 7.0 + */ +public class OneTimeTokenAuthentication extends AbstractAuthenticationToken { + + @Serial + private static final long serialVersionUID = 1195893764725073959L; + + private final Object principal; + + public OneTimeTokenAuthentication(Object principal, Collection 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; };