From 50568da1e58d22bd7bf7175f70f1482e87a7c1f6 Mon Sep 17 00:00:00 2001 From: Rob Winch <362503+rwinch@users.noreply.github.com> Date: Fri, 17 Oct 2025 13:31:42 -0500 Subject: [PATCH] Add Jackson 3 TestingAuthenticationToken Support Without this many of the tests fail when using Jackson 3 --- .../security/jackson/CoreJacksonModule.java | 1 + .../TestingAuthenticationTokenMixin.java | 32 +++++---- .../TestingAuthenticationTokenMixinTests.java | 72 +++++++++++++++++++ 3 files changed, 93 insertions(+), 12 deletions(-) rename {oauth2/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization => core/src/main/java/org/springframework/security}/jackson/TestingAuthenticationTokenMixin.java (52%) create mode 100644 core/src/test/java/org/springframework/security/jackson/TestingAuthenticationTokenMixinTests.java 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 58293a1797..73ecdddb62 100644 --- a/core/src/main/java/org/springframework/security/jackson/CoreJacksonModule.java +++ b/core/src/main/java/org/springframework/security/jackson/CoreJacksonModule.java @@ -107,6 +107,7 @@ public class CoreJacksonModule extends SecurityJacksonModule { context.setMixIn(FactorGrantedAuthority.class, FactorGrantedAuthorityMixin.class); context.setMixIn(User.class, UserMixin.class); context.setMixIn(UsernamePasswordAuthenticationToken.class, UsernamePasswordAuthenticationTokenMixin.class); + context.setMixIn(TestingAuthenticationToken.class, TestingAuthenticationTokenMixin.class); context.setMixIn(BadCredentialsException.class, BadCredentialsExceptionMixin.class); } diff --git a/oauth2/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/jackson/TestingAuthenticationTokenMixin.java b/core/src/main/java/org/springframework/security/jackson/TestingAuthenticationTokenMixin.java similarity index 52% rename from oauth2/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/jackson/TestingAuthenticationTokenMixin.java rename to core/src/main/java/org/springframework/security/jackson/TestingAuthenticationTokenMixin.java index bc0a70212a..1ffd231793 100644 --- a/oauth2/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/jackson/TestingAuthenticationTokenMixin.java +++ b/core/src/main/java/org/springframework/security/jackson/TestingAuthenticationTokenMixin.java @@ -14,36 +14,44 @@ * limitations under the License. */ -package org.springframework.security.oauth2.server.authorization.jackson; +package org.springframework.security.jackson; -import java.util.List; +import java.util.Collection; import com.fasterxml.jackson.annotation.JsonAutoDetect; import com.fasterxml.jackson.annotation.JsonCreator; -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonTypeInfo; -import org.springframework.security.authentication.TestingAuthenticationToken; import org.springframework.security.core.GrantedAuthority; /** - * This mixin class is used to serialize/deserialize {@link TestingAuthenticationToken}. + * This is a Jackson mixin class helps in serialize/deserialize + * {@link org.springframework.security.authentication.AnonymousAuthenticationToken} class. * - * @author Steve Riesenberg + * @author Sebastien Deleuze + * @author Jitendra Singh * @since 7.0 - * @see TestingAuthenticationToken + * @see CoreJacksonModule + * @see SecurityJacksonModules */ @JsonTypeInfo(use = JsonTypeInfo.Id.CLASS) -@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY, getterVisibility = JsonAutoDetect.Visibility.NONE, - isGetterVisibility = JsonAutoDetect.Visibility.NONE) -@JsonIgnoreProperties(value = { "authenticated" }, ignoreUnknown = true) -public class TestingAuthenticationTokenMixin { +@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY, isGetterVisibility = JsonAutoDetect.Visibility.NONE, + getterVisibility = JsonAutoDetect.Visibility.NONE, creatorVisibility = JsonAutoDetect.Visibility.ANY) +class TestingAuthenticationTokenMixin { + /** + * Constructor used by Jackson to create object of + * {@link org.springframework.security.authentication.AnonymousAuthenticationToken}. + * {@link org.springframework.security.authentication.AnonymousAuthenticationToken#AnonymousAuthenticationToken(String, Object, Collection)} + * @param principal the principal (typically a UserDetails) + * @param credentials the credentials + * @param authorities the authorities granted to the principal + */ @JsonCreator TestingAuthenticationTokenMixin(@JsonProperty("principal") Object principal, @JsonProperty("credentials") Object credentials, - @JsonProperty("authorities") List authorities) { + @JsonProperty("authorities") Collection authorities) { } } diff --git a/core/src/test/java/org/springframework/security/jackson/TestingAuthenticationTokenMixinTests.java b/core/src/test/java/org/springframework/security/jackson/TestingAuthenticationTokenMixinTests.java new file mode 100644 index 0000000000..e824628fd8 --- /dev/null +++ b/core/src/test/java/org/springframework/security/jackson/TestingAuthenticationTokenMixinTests.java @@ -0,0 +1,72 @@ +/* + * 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.junit.jupiter.api.Test; +import org.skyscreamer.jsonassert.JSONAssert; + +import org.springframework.security.authentication.TestingAuthenticationToken; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * Tests {@link TestingAuthenticationTokenMixin}. + * + * @author Rob Winch + * @since 7.0 + */ +class TestingAuthenticationTokenMixinTests extends AbstractMixinTests { + + private static final String EXPECTED_JSON = """ + { + "@class": "org.springframework.security.authentication.TestingAuthenticationToken", + "authorities": [ + "java.util.Collections$UnmodifiableRandomAccessList", + [ + { + "@class": "org.springframework.security.core.authority.SimpleGrantedAuthority", + "authority": "ROLE_A" + }, + { + "@class": "org.springframework.security.core.authority.SimpleGrantedAuthority", + "authority": "ROLE_B" + } + ] + ], + "details": null, + "authenticated": true, + "credentials": null, + "principal": "principal" + }"""; + + private TestingAuthenticationToken expectedToken = new TestingAuthenticationToken("principal", null, "ROLE_A", + "ROLE_B"); + + @Test + void serialize() throws Exception { + String json = this.mapper.writeValueAsString(this.expectedToken); + JSONAssert.assertEquals(EXPECTED_JSON, json, true); + } + + @Test + void deserialize() { + TestingAuthenticationToken actual = (TestingAuthenticationToken) this.mapper.readValue(EXPECTED_JSON, + Object.class); + assertThat(actual).isEqualTo(this.expectedToken); + } + +}