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 extends GrantedAuthority> 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);
+ }
+
+}