diff --git a/core/src/main/java/org/springframework/security/jackson/SecurityJacksonModules.java b/core/src/main/java/org/springframework/security/jackson/SecurityJacksonModules.java index 4c5b484b65..5869e9f53a 100644 --- a/core/src/main/java/org/springframework/security/jackson/SecurityJacksonModules.java +++ b/core/src/main/java/org/springframework/security/jackson/SecurityJacksonModules.java @@ -36,10 +36,9 @@ import org.springframework.util.ClassUtils; /** * This utility class will find all the Jackson modules contributed by Spring Security in - * the classpath (except {@code OAuth2AuthorizationServerJacksonModule} and - * {@code WebauthnJacksonModule}), enable automatic inclusion of type information and - * configure a {@link PolymorphicTypeValidator} that handles the validation of class - * names. + * the classpath (except {@code WebauthnJacksonModule}), enable automatic inclusion of + * type information and configure a {@link PolymorphicTypeValidator} that handles the + * validation of class names. * *
*
@@ -77,6 +76,8 @@ public final class SecurityJacksonModules {
private static final String oauth2ClientJacksonModuleClass = "org.springframework.security.oauth2.client.jackson.OAuth2ClientJacksonModule";
+ private static final String oauth2AuthorizationServerJacksonModuleClass = "org.springframework.security.oauth2.server.authorization.jackson.OAuth2AuthorizationServerJacksonModule";
+
private static final String ldapJacksonModuleClass = "org.springframework.security.ldap.jackson.LdapJacksonModule";
private static final String saml2JacksonModuleClass = "org.springframework.security.saml2.jackson.Saml2JacksonModule";
@@ -87,6 +88,8 @@ public final class SecurityJacksonModules {
private static final boolean oauth2ClientPresent;
+ private static final boolean oauth2AuthorizationServerPresent;
+
private static final boolean ldapJacksonPresent;
private static final boolean saml2JacksonPresent;
@@ -94,11 +97,12 @@ public final class SecurityJacksonModules {
private static final boolean casJacksonPresent;
static {
-
ClassLoader classLoader = SecurityJacksonModules.class.getClassLoader();
webServletPresent = ClassUtils.isPresent("jakarta.servlet.http.Cookie", classLoader);
oauth2ClientPresent = ClassUtils.isPresent("org.springframework.security.oauth2.client.OAuth2AuthorizedClient",
classLoader);
+ oauth2AuthorizationServerPresent = ClassUtils
+ .isPresent("org.springframework.security.oauth2.server.authorization.OAuth2Authorization", classLoader);
ldapJacksonPresent = ClassUtils.isPresent(ldapJacksonModuleClass, classLoader);
saml2JacksonPresent = ClassUtils.isPresent(saml2JacksonModuleClass, classLoader);
casJacksonPresent = ClassUtils.isPresent(casJacksonModuleClass, classLoader);
@@ -156,6 +160,9 @@ public final class SecurityJacksonModules {
if (oauth2ClientPresent) {
addToModulesList(loader, modules, oauth2ClientJacksonModuleClass);
}
+ if (oauth2AuthorizationServerPresent) {
+ addToModulesList(loader, modules, oauth2AuthorizationServerJacksonModuleClass);
+ }
if (ldapJacksonPresent) {
addToModulesList(loader, modules, ldapJacksonModuleClass);
}
diff --git a/docs/modules/ROOT/pages/features/integrations/jackson.adoc b/docs/modules/ROOT/pages/features/integrations/jackson.adoc
index 1e2cd49fc2..b94fa44396 100644
--- a/docs/modules/ROOT/pages/features/integrations/jackson.adoc
+++ b/docs/modules/ROOT/pages/features/integrations/jackson.adoc
@@ -86,6 +86,7 @@ The following Spring Security modules provide Jackson support:
- spring-security-core (javadoc:org.springframework.security.jackson.CoreJacksonModule[])
- spring-security-web (javadoc:org.springframework.security.web.jackson.WebJacksonModule[], javadoc:org.springframework.security.web.jackson.WebServletJacksonModule[], javadoc:org.springframework.security.web.server.jackson.WebServerJacksonModule[])
- spring-security-oauth2-client (javadoc:org.springframework.security.oauth2.client.jackson.OAuth2ClientJacksonModule[])
+- spring-security-oauth2-authorization-server (javadoc:org.springframework.security.oauth2.server.authorization.jackson.OAuth2AuthorizationServerJacksonModule[])
- spring-security-cas (javadoc:org.springframework.security.cas.jackson.CasJacksonModule[])
- spring-security-ldap (javadoc:org.springframework.security.ldap.jackson.LdapJacksonModule[])
- spring-security-saml2 (javadoc:org.springframework.security.saml2.jackson.Saml2JacksonModule[])
diff --git a/oauth2/oauth2-authorization-server/spring-security-oauth2-authorization-server.gradle b/oauth2/oauth2-authorization-server/spring-security-oauth2-authorization-server.gradle
index beb19bd536..0d19d51df5 100644
--- a/oauth2/oauth2-authorization-server/spring-security-oauth2-authorization-server.gradle
+++ b/oauth2/oauth2-authorization-server/spring-security-oauth2-authorization-server.gradle
@@ -13,9 +13,9 @@ dependencies {
api "com.nimbusds:nimbus-jose-jwt"
api 'tools.jackson.core:jackson-databind'
+ optional "com.fasterxml.jackson.core:jackson-databind"
optional "com.fasterxml.jackson.datatype:jackson-datatype-jsr310"
optional "org.springframework:spring-jdbc"
- optional "com.fasterxml.jackson.core:jackson-databind"
testImplementation project(":spring-security-test")
testImplementation project(path : ':spring-security-oauth2-jose', configuration : 'tests')
diff --git a/oauth2/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/JdbcOAuth2AuthorizationService.java b/oauth2/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/JdbcOAuth2AuthorizationService.java
index 45018582ec..1d4ee29083 100644
--- a/oauth2/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/JdbcOAuth2AuthorizationService.java
+++ b/oauth2/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/JdbcOAuth2AuthorizationService.java
@@ -68,7 +68,6 @@ import org.springframework.security.oauth2.core.oidc.OidcIdToken;
import org.springframework.security.oauth2.core.oidc.endpoint.OidcParameterNames;
import org.springframework.security.oauth2.server.authorization.client.RegisteredClient;
import org.springframework.security.oauth2.server.authorization.client.RegisteredClientRepository;
-import org.springframework.security.oauth2.server.authorization.jackson.OAuth2AuthorizationServerJacksonModule;
import org.springframework.security.oauth2.server.authorization.jackson2.OAuth2AuthorizationServerJackson2Module;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
@@ -361,7 +360,7 @@ public class JdbcOAuth2AuthorizationService implements OAuth2AuthorizationServic
/**
* Sets the {@link RowMapper} used for mapping the current row in
* {@code java.sql.ResultSet} to {@link OAuth2Authorization}. The default is
- * {@link OAuth2AuthorizationRowMapper}.
+ * {@link JsonMapperOAuth2AuthorizationRowMapper}.
* @param authorizationRowMapper the {@link RowMapper} used for mapping the current
* row in {@code ResultSet} to {@link OAuth2Authorization}
*/
@@ -373,7 +372,7 @@ public class JdbcOAuth2AuthorizationService implements OAuth2AuthorizationServic
/**
* Sets the {@code Function} used for mapping {@link OAuth2Authorization} to a
* {@code List} of {@link SqlParameterValue}. The default is
- * {@link OAuth2AuthorizationParametersMapper}.
+ * {@link JsonMapperOAuth2AuthorizationParametersMapper}.
* @param authorizationParametersMapper the {@code Function} used for mapping
* {@link OAuth2Authorization} to a {@code List} of {@link SqlParameterValue}
*/
@@ -743,10 +742,7 @@ public class JdbcOAuth2AuthorizationService implements OAuth2AuthorizationServic
static JsonMapper createJsonMapper() {
List modules = SecurityJacksonModules.getModules(Jackson3.class.getClassLoader());
- return JsonMapper.builder()
- .addModules(modules)
- .addModules(new OAuth2AuthorizationServerJacksonModule())
- .build();
+ return JsonMapper.builder().addModules(modules).build();
}
}
diff --git a/oauth2/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/jackson/OAuth2AuthorizationServerJacksonModule.java b/oauth2/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/jackson/OAuth2AuthorizationServerJacksonModule.java
index fd8b1b8d6a..ea23b1336e 100644
--- a/oauth2/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/jackson/OAuth2AuthorizationServerJacksonModule.java
+++ b/oauth2/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/jackson/OAuth2AuthorizationServerJacksonModule.java
@@ -18,13 +18,11 @@ package org.springframework.security.oauth2.server.authorization.jackson;
import java.net.URL;
-import com.fasterxml.jackson.annotation.JsonTypeInfo;
import tools.jackson.core.Version;
-import tools.jackson.databind.DefaultTyping;
-import tools.jackson.databind.cfg.MapperBuilder;
import tools.jackson.databind.jsontype.BasicPolymorphicTypeValidator;
-import org.springframework.security.jackson.CoreJacksonModule;
+import org.springframework.security.jackson.SecurityJacksonModule;
+import org.springframework.security.jackson.SecurityJacksonModules;
import org.springframework.security.oauth2.core.endpoint.OAuth2AuthorizationRequest;
import org.springframework.security.oauth2.jose.jws.MacAlgorithm;
import org.springframework.security.oauth2.jose.jws.SignatureAlgorithm;
@@ -37,20 +35,22 @@ import org.springframework.security.oauth2.server.authorization.settings.OAuth2T
* registers the following mix-in annotations:
*
*
- * - {@link OAuth2TokenExchangeActor}
+ * - {@link OAuth2TokenExchangeActorMixin}
* - {@link OAuth2AuthorizationRequestMixin}
* - {@link OAuth2TokenExchangeCompositeAuthenticationTokenMixin}
* - {@link JwsAlgorithmMixin}
* - {@link OAuth2TokenFormatMixin}
*
*
- * If not already enabled, default typing will be automatically enabled as type info is
- * required to properly serialize/deserialize objects. In order to use this module just
- * add it to your {@code JsonMapper.Builder} configuration.
+ *
+ * The recommended way to configure it is to use {@link SecurityJacksonModules} in order
+ * to enable properly automatic inclusion of type information with related validation.
*
*
+ * ClassLoader loader = getClass().getClassLoader();
* JsonMapper mapper = JsonMapper.builder()
- * .addModules(new OAuth2AuthorizationServerJacksonModule()).build;
+ * .addModules(SecurityJacksonModules.getModules(loader))
+ * .build();
*
*
* @author Sebastien Deleuze
@@ -58,7 +58,7 @@ import org.springframework.security.oauth2.server.authorization.settings.OAuth2T
* @since 7.0
*/
@SuppressWarnings("serial")
-public class OAuth2AuthorizationServerJacksonModule extends CoreJacksonModule {
+public class OAuth2AuthorizationServerJacksonModule extends SecurityJacksonModule {
public OAuth2AuthorizationServerJacksonModule() {
super(OAuth2AuthorizationServerJacksonModule.class.getName(), new Version(1, 0, 0, null, null, null));
@@ -66,7 +66,6 @@ public class OAuth2AuthorizationServerJacksonModule extends CoreJacksonModule {
@Override
public void configurePolymorphicTypeValidator(BasicPolymorphicTypeValidator.Builder builder) {
- super.configurePolymorphicTypeValidator(builder);
builder.allowIfSubType(OAuth2TokenFormat.class)
.allowIfSubType(OAuth2TokenExchangeActor.class)
.allowIfSubType(OAuth2TokenExchangeCompositeAuthenticationToken.class)
@@ -78,11 +77,6 @@ public class OAuth2AuthorizationServerJacksonModule extends CoreJacksonModule {
@Override
public void setupModule(SetupContext context) {
- super.setupModule(context);
- BasicPolymorphicTypeValidator.Builder builder = BasicPolymorphicTypeValidator.builder();
- this.configurePolymorphicTypeValidator(builder);
- ((MapperBuilder, ?>) context.getOwner()).activateDefaultTyping(builder.build(), DefaultTyping.NON_FINAL,
- JsonTypeInfo.As.PROPERTY);
context.setMixIn(OAuth2TokenExchangeActor.class, OAuth2TokenExchangeActorMixin.class);
context.setMixIn(OAuth2AuthorizationRequest.class, OAuth2AuthorizationRequestMixin.class);
context.setMixIn(OAuth2TokenExchangeCompositeAuthenticationToken.class,
diff --git a/oauth2/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/JdbcOAuth2AuthorizationServiceTests.java b/oauth2/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/JdbcOAuth2AuthorizationServiceTests.java
index 8d428a2fb2..04f7a9a310 100644
--- a/oauth2/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/JdbcOAuth2AuthorizationServiceTests.java
+++ b/oauth2/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/JdbcOAuth2AuthorizationServiceTests.java
@@ -16,6 +16,7 @@
package org.springframework.security.oauth2.server.authorization;
+import java.security.Principal;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Timestamp;
@@ -45,6 +46,7 @@ import org.springframework.jdbc.core.SqlParameterValue;
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabase;
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder;
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType;
+import org.springframework.security.authentication.TestingAuthenticationToken;
import org.springframework.security.jackson.SecurityJacksonModules;
import org.springframework.security.oauth2.core.AuthorizationGrantType;
import org.springframework.security.oauth2.core.OAuth2AccessToken;
@@ -58,6 +60,7 @@ import org.springframework.security.oauth2.core.oidc.endpoint.OidcParameterNames
import org.springframework.security.oauth2.server.authorization.client.RegisteredClient;
import org.springframework.security.oauth2.server.authorization.client.RegisteredClientRepository;
import org.springframework.security.oauth2.server.authorization.client.TestRegisteredClients;
+import org.springframework.security.web.authentication.WebAuthenticationDetails;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
@@ -227,10 +230,11 @@ public class JdbcOAuth2AuthorizationServiceTests {
.build();
RowMapper authorizationRowMapper = spy(
- new JdbcOAuth2AuthorizationService.OAuth2AuthorizationRowMapper(this.registeredClientRepository));
+ new JdbcOAuth2AuthorizationService.JsonMapperOAuth2AuthorizationRowMapper(
+ this.registeredClientRepository));
this.authorizationService.setAuthorizationRowMapper(authorizationRowMapper);
Function> authorizationParametersMapper = spy(
- new JdbcOAuth2AuthorizationService.OAuth2AuthorizationParametersMapper());
+ new JdbcOAuth2AuthorizationService.JsonMapperOAuth2AuthorizationParametersMapper());
this.authorizationService.setAuthorizationParametersMapper(authorizationParametersMapper);
this.authorizationService.save(originalAuthorization);
@@ -461,6 +465,28 @@ public class JdbcOAuth2AuthorizationServiceTests {
assertThat(result).isNull();
}
+ // gh-18102
+ @Test
+ public void findByTokenWhenPrincipalHasWebAuthenticationDetailsThenDeserializes() {
+ given(this.registeredClientRepository.findById(eq(REGISTERED_CLIENT.getId()))).willReturn(REGISTERED_CLIENT);
+
+ String state = "state";
+ TestingAuthenticationToken principal = new TestingAuthenticationToken(PRINCIPAL_NAME, "credentials");
+ principal.setDetails(new WebAuthenticationDetails("remoteAddress", "sessionId"));
+
+ OAuth2Authorization authorization = OAuth2Authorization.withRegisteredClient(REGISTERED_CLIENT)
+ .id(ID)
+ .principalName(PRINCIPAL_NAME)
+ .authorizationGrantType(AUTHORIZATION_GRANT_TYPE)
+ .attribute(OAuth2ParameterNames.STATE, state)
+ .attribute(Principal.class.getName(), principal)
+ .build();
+ this.authorizationService.save(authorization);
+
+ OAuth2Authorization result = this.authorizationService.findByToken(state, STATE_TOKEN_TYPE);
+ assertThat(authorization).isEqualTo(result);
+ }
+
@Test
public void tableDefinitionWhenCustomThenAbleToOverride() {
given(this.registeredClientRepository.findById(eq(REGISTERED_CLIENT.getId()))).willReturn(REGISTERED_CLIENT);
diff --git a/oauth2/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/jackson/OAuth2AuthorizationServerJacksonModuleTests.java b/oauth2/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/jackson/OAuth2AuthorizationServerJacksonModuleTests.java
index 00b3cb8662..baa8b47cd4 100644
--- a/oauth2/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/jackson/OAuth2AuthorizationServerJacksonModuleTests.java
+++ b/oauth2/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/jackson/OAuth2AuthorizationServerJacksonModuleTests.java
@@ -27,20 +27,20 @@ import tools.jackson.databind.json.JsonMapper;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
+import org.springframework.security.jackson.SecurityJacksonModules;
import org.springframework.security.oauth2.jose.jws.MacAlgorithm;
import org.springframework.security.oauth2.jwt.JwtClaimNames;
import org.springframework.security.oauth2.server.authorization.OAuth2Authorization;
import org.springframework.security.oauth2.server.authorization.TestOAuth2Authorizations;
import org.springframework.security.oauth2.server.authorization.authentication.OAuth2TokenExchangeActor;
import org.springframework.security.oauth2.server.authorization.authentication.OAuth2TokenExchangeCompositeAuthenticationToken;
-import org.springframework.security.oauth2.server.authorization.jackson2.OAuth2AuthorizationServerJackson2Module;
import org.springframework.security.oauth2.server.authorization.settings.ClientSettings;
import org.springframework.security.oauth2.server.authorization.settings.TokenSettings;
import static org.assertj.core.api.Assertions.assertThat;
/**
- * Tests for {@link OAuth2AuthorizationServerJackson2Module}.
+ * Tests for {@link OAuth2AuthorizationServerJacksonModule}.
*
* @author Steve Riesenberg
* @author Joe Grandja
@@ -55,7 +55,9 @@ public class OAuth2AuthorizationServerJacksonModuleTests {
@BeforeEach
public void setup() {
- this.mapper = JsonMapper.builder().addModules(new OAuth2AuthorizationServerJacksonModule()).build();
+ this.mapper = JsonMapper.builder()
+ .addModules(SecurityJacksonModules.getModules(getClass().getClassLoader()))
+ .build();
}
@Test