diff --git a/core/src/main/java/org/springframework/security/jackson/CoreJacksonModule.java b/core/src/main/java/org/springframework/security/jackson/CoreJacksonModule.java index 5c6f27ba08e..bebfb361383 100644 --- a/core/src/main/java/org/springframework/security/jackson/CoreJacksonModule.java +++ b/core/src/main/java/org/springframework/security/jackson/CoreJacksonModule.java @@ -29,6 +29,7 @@ import org.springframework.security.authentication.RememberMeAuthenticationToken; import org.springframework.security.authentication.TestingAuthenticationToken; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.authentication.ott.InvalidOneTimeTokenException; import org.springframework.security.authentication.ott.OneTimeTokenAuthentication; import org.springframework.security.core.authority.FactorGrantedAuthority; import org.springframework.security.core.authority.SimpleGrantedAuthority; @@ -83,6 +84,7 @@ public void configurePolymorphicTypeValidator(BasicPolymorphicTypeValidator.Buil .allowIfSubType(SecurityContextImpl.class) .allowIfSubType(TestingAuthenticationToken.class) .allowIfSubType(OneTimeTokenAuthentication.class) + .allowIfSubType(InvalidOneTimeTokenException.class) .allowIfSubType("java.util.Collections$UnmodifiableSet") .allowIfSubType("java.util.Collections$UnmodifiableRandomAccessList") .allowIfSubType("java.util.Collections$EmptyList") @@ -111,6 +113,7 @@ public void setupModule(SetupContext context) { context.setMixIn(TestingAuthenticationToken.class, TestingAuthenticationTokenMixin.class); context.setMixIn(BadCredentialsException.class, BadCredentialsExceptionMixin.class); context.setMixIn(OneTimeTokenAuthentication.class, OneTimeTokenAuthenticationMixin.class); + context.setMixIn(InvalidOneTimeTokenException.class, InvalidOneTimeTokenExceptionMixin.class); } } diff --git a/core/src/main/java/org/springframework/security/jackson/InvalidOneTimeTokenExceptionMixin.java b/core/src/main/java/org/springframework/security/jackson/InvalidOneTimeTokenExceptionMixin.java new file mode 100644 index 00000000000..38a8351abe3 --- /dev/null +++ b/core/src/main/java/org/springframework/security/jackson/InvalidOneTimeTokenExceptionMixin.java @@ -0,0 +1,47 @@ +/* + * 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.jackson; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonTypeInfo; + +/** + * This mixin class helps in serialize/deserialize + * {@link org.springframework.security.authentication.ott.InvalidOneTimeTokenException} + * class. + * + * @author seonwoo-jung + * @since 7.1 + * @see CoreJacksonModule + */ +@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS) +@JsonIgnoreProperties({ "cause", "stackTrace", "authenticationRequest" }) +class InvalidOneTimeTokenExceptionMixin { + + /** + * Constructor used by Jackson to create + * {@link org.springframework.security.authentication.ott.InvalidOneTimeTokenException} + * object. + * @param message the detail message + */ + @JsonCreator + InvalidOneTimeTokenExceptionMixin(@JsonProperty("message") String message) { + } + +} diff --git a/core/src/main/java/org/springframework/security/jackson2/CoreJackson2Module.java b/core/src/main/java/org/springframework/security/jackson2/CoreJackson2Module.java index 2f8a87c4f41..892df014753 100644 --- a/core/src/main/java/org/springframework/security/jackson2/CoreJackson2Module.java +++ b/core/src/main/java/org/springframework/security/jackson2/CoreJackson2Module.java @@ -25,6 +25,7 @@ import org.springframework.security.authentication.BadCredentialsException; import org.springframework.security.authentication.RememberMeAuthenticationToken; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.authentication.ott.InvalidOneTimeTokenException; import org.springframework.security.authentication.ott.OneTimeTokenAuthenticationToken; import org.springframework.security.core.authority.FactorGrantedAuthority; import org.springframework.security.core.authority.SimpleGrantedAuthority; @@ -77,6 +78,7 @@ public void setupModule(SetupContext context) { UsernamePasswordAuthenticationTokenMixin.class); context.setMixInAnnotations(BadCredentialsException.class, BadCredentialsExceptionMixin.class); context.setMixInAnnotations(OneTimeTokenAuthenticationToken.class, OneTimeTokenAuthenticationTokenMixin.class); + context.setMixInAnnotations(InvalidOneTimeTokenException.class, InvalidOneTimeTokenExceptionMixin.class); } } diff --git a/core/src/main/java/org/springframework/security/jackson2/InvalidOneTimeTokenExceptionMixin.java b/core/src/main/java/org/springframework/security/jackson2/InvalidOneTimeTokenExceptionMixin.java new file mode 100644 index 00000000000..04cbf01ab32 --- /dev/null +++ b/core/src/main/java/org/springframework/security/jackson2/InvalidOneTimeTokenExceptionMixin.java @@ -0,0 +1,61 @@ +/* + * 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.jackson2; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonTypeInfo; + +/** + * This mixin class helps in serialize/deserialize + * {@link org.springframework.security.authentication.ott.InvalidOneTimeTokenException} + * class. To use this class you need to register it with + * {@link com.fasterxml.jackson.databind.ObjectMapper}. + * + *
+ * ObjectMapper mapper = new ObjectMapper(); + * mapper.registerModule(new CoreJackson2Module()); + *+ * + * Note: This class will save TypeInfo (full class name) into a property + * called @class The cause and stackTrace are ignored in the serialization. + * + * @author seonwoo-jung + * @since 7.1 + * @see CoreJackson2Module + * @deprecated as of 7.0 in favor of + * {@code org.springframework.security.jackson.InvalidOneTimeTokenExceptionMixin} based on + * Jackson 3 + */ +@SuppressWarnings("removal") +@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY) +@JsonIgnoreProperties(ignoreUnknown = true, value = { "cause", "stackTrace", "authenticationRequest" }) +@Deprecated(forRemoval = true) +class InvalidOneTimeTokenExceptionMixin { + + /** + * Constructor used by Jackson to create + * {@link org.springframework.security.authentication.ott.InvalidOneTimeTokenException} + * object. + * @param message the detail message + */ + @JsonCreator + InvalidOneTimeTokenExceptionMixin(@JsonProperty("message") String message) { + } + +} diff --git a/core/src/test/java/org/springframework/security/jackson/InvalidOneTimeTokenExceptionMixinTests.java b/core/src/test/java/org/springframework/security/jackson/InvalidOneTimeTokenExceptionMixinTests.java new file mode 100644 index 00000000000..d93cccfd99c --- /dev/null +++ b/core/src/test/java/org/springframework/security/jackson/InvalidOneTimeTokenExceptionMixinTests.java @@ -0,0 +1,55 @@ +/* + * 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.jackson; + +import org.json.JSONException; +import org.junit.jupiter.api.Test; +import org.skyscreamer.jsonassert.JSONAssert; + +import org.springframework.security.authentication.ott.InvalidOneTimeTokenException; + +import static org.assertj.core.api.Assertions.assertThat; + +class InvalidOneTimeTokenExceptionMixinTests extends AbstractMixinTests { + + // @formatter:off + private static final String EXCEPTION_JSON = "{" + + "\"@class\": \"org.springframework.security.authentication.ott.InvalidOneTimeTokenException\"," + + "\"localizedMessage\": \"message\", " + + "\"message\": \"message\", " + + "\"suppressed\": [\"[Ljava.lang.Throwable;\",[]]" + + "}"; + // @formatter:on + + @Test + void serializeInvalidOneTimeTokenExceptionMixinTest() throws JSONException { + InvalidOneTimeTokenException exception = new InvalidOneTimeTokenException("message"); + String serializedJson = this.mapper.writeValueAsString(exception); + JSONAssert.assertEquals(EXCEPTION_JSON, serializedJson, true); + } + + @Test + void deserializeInvalidOneTimeTokenExceptionMixinTest() { + InvalidOneTimeTokenException exception = this.mapper.readValue(EXCEPTION_JSON, + InvalidOneTimeTokenException.class); + assertThat(exception).isNotNull(); + assertThat(exception.getCause()).isNull(); + assertThat(exception.getMessage()).isEqualTo("message"); + assertThat(exception.getLocalizedMessage()).isEqualTo("message"); + } + +} diff --git a/core/src/test/java/org/springframework/security/jackson2/InvalidOneTimeTokenExceptionMixinTests.java b/core/src/test/java/org/springframework/security/jackson2/InvalidOneTimeTokenExceptionMixinTests.java new file mode 100644 index 00000000000..75a807a8912 --- /dev/null +++ b/core/src/test/java/org/springframework/security/jackson2/InvalidOneTimeTokenExceptionMixinTests.java @@ -0,0 +1,58 @@ +/* + * 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.jackson2; + +import java.io.IOException; + +import com.fasterxml.jackson.core.JsonProcessingException; +import org.json.JSONException; +import org.junit.jupiter.api.Test; +import org.skyscreamer.jsonassert.JSONAssert; + +import org.springframework.security.authentication.ott.InvalidOneTimeTokenException; + +import static org.assertj.core.api.Assertions.assertThat; + +public class InvalidOneTimeTokenExceptionMixinTests extends AbstractMixinTests { + + // @formatter:off + private static final String EXCEPTION_JSON = "{" + + "\"@class\": \"org.springframework.security.authentication.ott.InvalidOneTimeTokenException\"," + + "\"localizedMessage\": \"message\", " + + "\"message\": \"message\", " + + "\"suppressed\": [\"[Ljava.lang.Throwable;\",[]]" + + "}"; + // @formatter:on + + @Test + public void serializeInvalidOneTimeTokenExceptionMixinTest() throws JsonProcessingException, JSONException { + InvalidOneTimeTokenException exception = new InvalidOneTimeTokenException("message"); + String serializedJson = this.mapper.writeValueAsString(exception); + JSONAssert.assertEquals(EXCEPTION_JSON, serializedJson, true); + } + + @Test + public void deserializeInvalidOneTimeTokenExceptionMixinTest() throws IOException { + InvalidOneTimeTokenException exception = this.mapper.readValue(EXCEPTION_JSON, + InvalidOneTimeTokenException.class); + assertThat(exception).isNotNull(); + assertThat(exception.getCause()).isNull(); + assertThat(exception.getMessage()).isEqualTo("message"); + assertThat(exception.getLocalizedMessage()).isEqualTo("message"); + } + +}