Browse Source

Remove JdbcOAuth2AuthorizationService.Mapper

- We should not introduce an unnecessary public API
  - It would need to be removed when Jackson 2 support was removed, but
    was required to configure Jackson 3 support
  - There are already existing interfaces that could be used
- OAuth2AuthorizationRowMapper & OAuth2AuthorizationParametersMapper had
  unnecessary breaking changes by removing getter/setter for ObjectMapper
- To prevent NoClassDefFoundErrors all optional (Jackson) dependencies
  need to be on different classes & we wish to preserve the existing
  accessors for ObjectMapper which is this uses subclasses
- With added TestAuthenticationTokenMixin support, no need to explicitly
  add it in tests
Rob Winch 5 days ago
parent
commit
5e851e0b26

+ 1 - 28
config/src/test/java/org/springframework/security/config/annotation/web/configurers/oauth2/server/authorization/JwkSetTests.java

@@ -24,7 +24,6 @@ import org.junit.jupiter.api.AfterEach;
 import org.junit.jupiter.api.BeforeAll;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.extension.ExtendWith;
-import tools.jackson.databind.json.JsonMapper;
 
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.context.annotation.Bean;
@@ -35,7 +34,6 @@ import org.springframework.jdbc.core.JdbcTemplate;
 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.config.annotation.web.configuration.EnableWebSecurity;
 import org.springframework.security.config.annotation.web.configuration.OAuth2AuthorizationServerConfiguration;
 import org.springframework.security.config.test.SpringTestContext;
@@ -45,7 +43,6 @@ import org.springframework.security.oauth2.server.authorization.JdbcOAuth2Author
 import org.springframework.security.oauth2.server.authorization.OAuth2AuthorizationService;
 import org.springframework.security.oauth2.server.authorization.client.JdbcRegisteredClientRepository;
 import org.springframework.security.oauth2.server.authorization.client.RegisteredClientRepository;
-import org.springframework.security.oauth2.server.authorization.jackson2.TestingAuthenticationTokenMixin;
 import org.springframework.security.oauth2.server.authorization.settings.AuthorizationServerSettings;
 import org.springframework.test.web.servlet.MockMvc;
 
@@ -142,11 +139,7 @@ public class JwkSetTests {
 		@Bean
 		OAuth2AuthorizationService authorizationService(JdbcOperations jdbcOperations,
 				RegisteredClientRepository registeredClientRepository) {
-			JdbcOAuth2AuthorizationService authorizationService = new JdbcOAuth2AuthorizationService(jdbcOperations,
-					registeredClientRepository);
-			authorizationService.setAuthorizationRowMapper(new RowMapper(registeredClientRepository));
-			authorizationService.setAuthorizationParametersMapper(new ParametersMapper());
-			return authorizationService;
+			return new JdbcOAuth2AuthorizationService(jdbcOperations, registeredClientRepository);
 		}
 
 		@Bean
@@ -164,26 +157,6 @@ public class JwkSetTests {
 			return jwkSource;
 		}
 
-		static class RowMapper extends JdbcOAuth2AuthorizationService.OAuth2AuthorizationRowMapper {
-
-			RowMapper(RegisteredClientRepository registeredClientRepository) {
-				super(registeredClientRepository);
-				setMapper(new JdbcOAuth2AuthorizationService.JacksonDelegate(JsonMapper.builder()
-					.addMixIn(TestingAuthenticationToken.class, TestingAuthenticationTokenMixin.class)));
-			}
-
-		}
-
-		static class ParametersMapper extends JdbcOAuth2AuthorizationService.OAuth2AuthorizationParametersMapper {
-
-			ParametersMapper() {
-				super();
-				setMapper(new JdbcOAuth2AuthorizationService.JacksonDelegate(JsonMapper.builder()
-					.addMixIn(TestingAuthenticationToken.class, TestingAuthenticationTokenMixin.class)));
-			}
-
-		}
-
 	}
 
 	@EnableWebSecurity

+ 1 - 27
config/src/test/java/org/springframework/security/config/annotation/web/configurers/oauth2/server/authorization/OAuth2AuthorizationCodeGrantTests.java

@@ -46,7 +46,6 @@ import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.extension.ExtendWith;
 import org.mockito.ArgumentCaptor;
-import tools.jackson.databind.json.JsonMapper;
 
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.context.annotation.Bean;
@@ -117,7 +116,6 @@ import org.springframework.security.oauth2.server.authorization.client.JdbcRegis
 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.oauth2.server.authorization.jackson2.TestingAuthenticationTokenMixin;
 import org.springframework.security.oauth2.server.authorization.settings.AuthorizationServerSettings;
 import org.springframework.security.oauth2.server.authorization.settings.ClientSettings;
 import org.springframework.security.oauth2.server.authorization.token.DelegatingOAuth2TokenGenerator;
@@ -1240,11 +1238,7 @@ public class OAuth2AuthorizationCodeGrantTests {
 		@Bean
 		OAuth2AuthorizationService authorizationService(JdbcOperations jdbcOperations,
 				RegisteredClientRepository registeredClientRepository) {
-			JdbcOAuth2AuthorizationService authorizationService = new JdbcOAuth2AuthorizationService(jdbcOperations,
-					registeredClientRepository);
-			authorizationService.setAuthorizationRowMapper(new RowMapper(registeredClientRepository));
-			authorizationService.setAuthorizationParametersMapper(new ParametersMapper());
-			return authorizationService;
+			return new JdbcOAuth2AuthorizationService(jdbcOperations, registeredClientRepository);
 		}
 
 		@Bean
@@ -1297,26 +1291,6 @@ public class OAuth2AuthorizationCodeGrantTests {
 			return NoOpPasswordEncoder.getInstance();
 		}
 
-		static class RowMapper extends JdbcOAuth2AuthorizationService.OAuth2AuthorizationRowMapper {
-
-			RowMapper(RegisteredClientRepository registeredClientRepository) {
-				super(registeredClientRepository);
-				setMapper(new JdbcOAuth2AuthorizationService.JacksonDelegate(JsonMapper.builder()
-					.addMixIn(TestingAuthenticationToken.class, TestingAuthenticationTokenMixin.class)));
-			}
-
-		}
-
-		static class ParametersMapper extends JdbcOAuth2AuthorizationService.OAuth2AuthorizationParametersMapper {
-
-			ParametersMapper() {
-				super();
-				setMapper(new JdbcOAuth2AuthorizationService.JacksonDelegate(JsonMapper.builder()
-					.addMixIn(TestingAuthenticationToken.class, TestingAuthenticationTokenMixin.class)));
-			}
-
-		}
-
 	}
 
 	@EnableWebSecurity

+ 1 - 28
config/src/test/java/org/springframework/security/config/annotation/web/configurers/oauth2/server/authorization/OAuth2ClientCredentialsGrantTests.java

@@ -40,7 +40,6 @@ import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.extension.ExtendWith;
 import org.mockito.ArgumentCaptor;
-import tools.jackson.databind.json.JsonMapper;
 
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.context.annotation.Bean;
@@ -53,7 +52,6 @@ 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.AuthenticationProvider;
-import org.springframework.security.authentication.TestingAuthenticationToken;
 import org.springframework.security.config.annotation.web.builders.HttpSecurity;
 import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
 import org.springframework.security.config.annotation.web.configuration.OAuth2AuthorizationServerConfiguration;
@@ -94,7 +92,6 @@ import org.springframework.security.oauth2.server.authorization.client.JdbcRegis
 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.oauth2.server.authorization.jackson2.TestingAuthenticationTokenMixin;
 import org.springframework.security.oauth2.server.authorization.settings.AuthorizationServerSettings;
 import org.springframework.security.oauth2.server.authorization.settings.ClientSettings;
 import org.springframework.security.oauth2.server.authorization.token.JwtEncodingContext;
@@ -534,11 +531,7 @@ public class OAuth2ClientCredentialsGrantTests {
 		@Bean
 		OAuth2AuthorizationService authorizationService(JdbcOperations jdbcOperations,
 				RegisteredClientRepository registeredClientRepository) {
-			JdbcOAuth2AuthorizationService authorizationService = new JdbcOAuth2AuthorizationService(jdbcOperations,
-					registeredClientRepository);
-			authorizationService.setAuthorizationRowMapper(new RowMapper(registeredClientRepository));
-			authorizationService.setAuthorizationParametersMapper(new ParametersMapper());
-			return authorizationService;
+			return new JdbcOAuth2AuthorizationService(jdbcOperations, registeredClientRepository);
 		}
 
 		@Bean
@@ -570,26 +563,6 @@ public class OAuth2ClientCredentialsGrantTests {
 			return NoOpPasswordEncoder.getInstance();
 		}
 
-		static class RowMapper extends JdbcOAuth2AuthorizationService.OAuth2AuthorizationRowMapper {
-
-			RowMapper(RegisteredClientRepository registeredClientRepository) {
-				super(registeredClientRepository);
-				setMapper(new JdbcOAuth2AuthorizationService.JacksonDelegate(JsonMapper.builder()
-					.addMixIn(TestingAuthenticationToken.class, TestingAuthenticationTokenMixin.class)));
-			}
-
-		}
-
-		static class ParametersMapper extends JdbcOAuth2AuthorizationService.OAuth2AuthorizationParametersMapper {
-
-			ParametersMapper() {
-				super();
-				setMapper(new JdbcOAuth2AuthorizationService.JacksonDelegate(JsonMapper.builder()
-					.addMixIn(TestingAuthenticationToken.class, TestingAuthenticationTokenMixin.class)));
-			}
-
-		}
-
 	}
 
 	@EnableWebSecurity

+ 1 - 28
config/src/test/java/org/springframework/security/config/annotation/web/configurers/oauth2/server/authorization/OAuth2RefreshTokenGrantTests.java

@@ -39,7 +39,6 @@ import org.junit.jupiter.api.AfterEach;
 import org.junit.jupiter.api.BeforeAll;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.extension.ExtendWith;
-import tools.jackson.databind.json.JsonMapper;
 
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.context.annotation.Bean;
@@ -57,7 +56,6 @@ import org.springframework.lang.Nullable;
 import org.springframework.mock.http.client.MockClientHttpResponse;
 import org.springframework.mock.web.MockHttpServletResponse;
 import org.springframework.security.authentication.AuthenticationProvider;
-import org.springframework.security.authentication.TestingAuthenticationToken;
 import org.springframework.security.config.annotation.web.builders.HttpSecurity;
 import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
 import org.springframework.security.config.annotation.web.configuration.OAuth2AuthorizationServerConfiguration;
@@ -99,7 +97,6 @@ import org.springframework.security.oauth2.server.authorization.client.JdbcRegis
 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.oauth2.server.authorization.jackson2.TestingAuthenticationTokenMixin;
 import org.springframework.security.oauth2.server.authorization.token.JwtEncodingContext;
 import org.springframework.security.oauth2.server.authorization.token.OAuth2TokenCustomizer;
 import org.springframework.security.web.SecurityFilterChain;
@@ -468,11 +465,7 @@ public class OAuth2RefreshTokenGrantTests {
 		@Bean
 		OAuth2AuthorizationService authorizationService(JdbcOperations jdbcOperations,
 				RegisteredClientRepository registeredClientRepository) {
-			JdbcOAuth2AuthorizationService authorizationService = new JdbcOAuth2AuthorizationService(jdbcOperations,
-					registeredClientRepository);
-			authorizationService.setAuthorizationRowMapper(new RowMapper(registeredClientRepository));
-			authorizationService.setAuthorizationParametersMapper(new ParametersMapper());
-			return authorizationService;
+			return new JdbcOAuth2AuthorizationService(jdbcOperations, registeredClientRepository);
 		}
 
 		@Bean
@@ -513,26 +506,6 @@ public class OAuth2RefreshTokenGrantTests {
 			return NoOpPasswordEncoder.getInstance();
 		}
 
-		static class RowMapper extends JdbcOAuth2AuthorizationService.OAuth2AuthorizationRowMapper {
-
-			RowMapper(RegisteredClientRepository registeredClientRepository) {
-				super(registeredClientRepository);
-				setMapper(new JdbcOAuth2AuthorizationService.JacksonDelegate(JsonMapper.builder()
-					.addMixIn(TestingAuthenticationToken.class, TestingAuthenticationTokenMixin.class)));
-			}
-
-		}
-
-		static class ParametersMapper extends JdbcOAuth2AuthorizationService.OAuth2AuthorizationParametersMapper {
-
-			ParametersMapper() {
-				super();
-				setMapper(new JdbcOAuth2AuthorizationService.JacksonDelegate(JsonMapper.builder()
-					.addMixIn(TestingAuthenticationToken.class, TestingAuthenticationTokenMixin.class)));
-			}
-
-		}
-
 	}
 
 	@EnableWebSecurity

+ 1 - 28
config/src/test/java/org/springframework/security/config/annotation/web/configurers/oauth2/server/authorization/OAuth2TokenIntrospectionTests.java

@@ -35,7 +35,6 @@ import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.extension.ExtendWith;
 import org.mockito.ArgumentCaptor;
-import tools.jackson.databind.json.JsonMapper;
 
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.context.annotation.Bean;
@@ -52,7 +51,6 @@ import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType;
 import org.springframework.mock.http.client.MockClientHttpResponse;
 import org.springframework.mock.web.MockHttpServletResponse;
 import org.springframework.security.authentication.AuthenticationProvider;
-import org.springframework.security.authentication.TestingAuthenticationToken;
 import org.springframework.security.config.annotation.web.builders.HttpSecurity;
 import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
 import org.springframework.security.config.annotation.web.configuration.OAuth2AuthorizationServerConfiguration;
@@ -88,7 +86,6 @@ import org.springframework.security.oauth2.server.authorization.client.Registere
 import org.springframework.security.oauth2.server.authorization.client.RegisteredClientRepository;
 import org.springframework.security.oauth2.server.authorization.client.TestRegisteredClients;
 import org.springframework.security.oauth2.server.authorization.http.converter.OAuth2TokenIntrospectionHttpMessageConverter;
-import org.springframework.security.oauth2.server.authorization.jackson2.TestingAuthenticationTokenMixin;
 import org.springframework.security.oauth2.server.authorization.settings.AuthorizationServerSettings;
 import org.springframework.security.oauth2.server.authorization.settings.ClientSettings;
 import org.springframework.security.oauth2.server.authorization.settings.OAuth2TokenFormat;
@@ -508,11 +505,7 @@ public class OAuth2TokenIntrospectionTests {
 		@Bean
 		OAuth2AuthorizationService authorizationService(JdbcOperations jdbcOperations,
 				RegisteredClientRepository registeredClientRepository) {
-			JdbcOAuth2AuthorizationService authorizationService = new JdbcOAuth2AuthorizationService(jdbcOperations,
-					registeredClientRepository);
-			authorizationService.setAuthorizationRowMapper(new RowMapper(registeredClientRepository));
-			authorizationService.setAuthorizationParametersMapper(new ParametersMapper());
-			return authorizationService;
+			return new JdbcOAuth2AuthorizationService(jdbcOperations, registeredClientRepository);
 		}
 
 		@Bean
@@ -550,26 +543,6 @@ public class OAuth2TokenIntrospectionTests {
 			return NoOpPasswordEncoder.getInstance();
 		}
 
-		static class RowMapper extends JdbcOAuth2AuthorizationService.OAuth2AuthorizationRowMapper {
-
-			RowMapper(RegisteredClientRepository registeredClientRepository) {
-				super(registeredClientRepository);
-				setMapper(new JdbcOAuth2AuthorizationService.JacksonDelegate(JsonMapper.builder()
-					.addMixIn(TestingAuthenticationToken.class, TestingAuthenticationTokenMixin.class)));
-			}
-
-		}
-
-		static class ParametersMapper extends JdbcOAuth2AuthorizationService.OAuth2AuthorizationParametersMapper {
-
-			ParametersMapper() {
-				super();
-				setMapper(new JdbcOAuth2AuthorizationService.JacksonDelegate(JsonMapper.builder()
-					.addMixIn(TestingAuthenticationToken.class, TestingAuthenticationTokenMixin.class)));
-			}
-
-		}
-
 	}
 
 	@EnableWebSecurity

+ 1 - 28
config/src/test/java/org/springframework/security/config/annotation/web/configurers/oauth2/server/authorization/OAuth2TokenRevocationTests.java

@@ -31,7 +31,6 @@ import org.junit.jupiter.api.BeforeAll;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.extension.ExtendWith;
 import org.mockito.ArgumentCaptor;
-import tools.jackson.databind.json.JsonMapper;
 
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.context.annotation.Bean;
@@ -44,7 +43,6 @@ 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.AuthenticationProvider;
-import org.springframework.security.authentication.TestingAuthenticationToken;
 import org.springframework.security.config.annotation.web.builders.HttpSecurity;
 import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
 import org.springframework.security.config.annotation.web.configuration.OAuth2AuthorizationServerConfiguration;
@@ -72,7 +70,6 @@ import org.springframework.security.oauth2.server.authorization.client.JdbcRegis
 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.oauth2.server.authorization.jackson2.TestingAuthenticationTokenMixin;
 import org.springframework.security.oauth2.server.authorization.settings.AuthorizationServerSettings;
 import org.springframework.security.oauth2.server.authorization.web.authentication.OAuth2TokenRevocationAuthenticationConverter;
 import org.springframework.security.web.SecurityFilterChain;
@@ -317,11 +314,7 @@ public class OAuth2TokenRevocationTests {
 		@Bean
 		OAuth2AuthorizationService authorizationService(JdbcOperations jdbcOperations,
 				RegisteredClientRepository registeredClientRepository) {
-			JdbcOAuth2AuthorizationService authorizationService = new JdbcOAuth2AuthorizationService(jdbcOperations,
-					registeredClientRepository);
-			authorizationService.setAuthorizationRowMapper(new RowMapper(registeredClientRepository));
-			authorizationService.setAuthorizationParametersMapper(new ParametersMapper());
-			return authorizationService;
+			return new JdbcOAuth2AuthorizationService(jdbcOperations, registeredClientRepository);
 		}
 
 		@Bean
@@ -348,26 +341,6 @@ public class OAuth2TokenRevocationTests {
 			return NoOpPasswordEncoder.getInstance();
 		}
 
-		static class RowMapper extends JdbcOAuth2AuthorizationService.OAuth2AuthorizationRowMapper {
-
-			RowMapper(RegisteredClientRepository registeredClientRepository) {
-				super(registeredClientRepository);
-				setMapper(new JdbcOAuth2AuthorizationService.JacksonDelegate(JsonMapper.builder()
-					.addMixIn(TestingAuthenticationToken.class, TestingAuthenticationTokenMixin.class)));
-			}
-
-		}
-
-		static class ParametersMapper extends JdbcOAuth2AuthorizationService.OAuth2AuthorizationParametersMapper {
-
-			ParametersMapper() {
-				super();
-				setMapper(new JdbcOAuth2AuthorizationService.JacksonDelegate(JsonMapper.builder()
-					.addMixIn(TestingAuthenticationToken.class, TestingAuthenticationTokenMixin.class)));
-			}
-
-		}
-
 	}
 
 	@EnableWebSecurity

+ 1 - 28
config/src/test/java/org/springframework/security/config/annotation/web/configurers/oauth2/server/authorization/OidcTests.java

@@ -36,7 +36,6 @@ import org.junit.jupiter.api.AfterEach;
 import org.junit.jupiter.api.BeforeAll;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.extension.ExtendWith;
-import tools.jackson.databind.json.JsonMapper;
 
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.context.annotation.Bean;
@@ -53,7 +52,6 @@ import org.springframework.lang.Nullable;
 import org.springframework.mock.http.client.MockClientHttpResponse;
 import org.springframework.mock.web.MockHttpServletResponse;
 import org.springframework.mock.web.MockHttpSession;
-import org.springframework.security.authentication.TestingAuthenticationToken;
 import org.springframework.security.config.Customizer;
 import org.springframework.security.config.annotation.web.builders.HttpSecurity;
 import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
@@ -91,7 +89,6 @@ import org.springframework.security.oauth2.server.authorization.client.JdbcRegis
 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.oauth2.server.authorization.jackson2.TestingAuthenticationTokenMixin;
 import org.springframework.security.oauth2.server.authorization.settings.AuthorizationServerSettings;
 import org.springframework.security.oauth2.server.authorization.token.DelegatingOAuth2TokenGenerator;
 import org.springframework.security.oauth2.server.authorization.token.JwtEncodingContext;
@@ -632,11 +629,7 @@ public class OidcTests {
 		@Bean
 		OAuth2AuthorizationService authorizationService(JdbcOperations jdbcOperations,
 				RegisteredClientRepository registeredClientRepository) {
-			JdbcOAuth2AuthorizationService authorizationService = new JdbcOAuth2AuthorizationService(jdbcOperations,
-					registeredClientRepository);
-			authorizationService.setAuthorizationRowMapper(new RowMapper(registeredClientRepository));
-			authorizationService.setAuthorizationParametersMapper(new ParametersMapper());
-			return authorizationService;
+			return new JdbcOAuth2AuthorizationService(jdbcOperations, registeredClientRepository);
 		}
 
 		@Bean
@@ -692,26 +685,6 @@ public class OidcTests {
 			return sessionRegistry;
 		}
 
-		static class RowMapper extends JdbcOAuth2AuthorizationService.OAuth2AuthorizationRowMapper {
-
-			RowMapper(RegisteredClientRepository registeredClientRepository) {
-				super(registeredClientRepository);
-				setMapper(new JdbcOAuth2AuthorizationService.JacksonDelegate(JsonMapper.builder()
-					.addMixIn(TestingAuthenticationToken.class, TestingAuthenticationTokenMixin.class)));
-			}
-
-		}
-
-		static class ParametersMapper extends JdbcOAuth2AuthorizationService.OAuth2AuthorizationParametersMapper {
-
-			ParametersMapper() {
-				super();
-				setMapper(new JdbcOAuth2AuthorizationService.JacksonDelegate(JsonMapper.builder()
-					.addMixIn(TestingAuthenticationToken.class, TestingAuthenticationTokenMixin.class)));
-			}
-
-		}
-
 	}
 
 	@EnableWebSecurity

+ 1 - 0
etc/checkstyle/checkstyle-suppressions.xml

@@ -24,6 +24,7 @@
 	<suppress files="EnableWebFluxSecurityTests\.java" checks="SpringMethodVisibility"/>
 	<suppress files="ExpressionBasedPreInvocationAdviceTests\.java" checks="SpringMethodVisibility"/>
 	<suppress files="Jsr250MethodSecurityMetadataSourceTests\.java" checks="SpringMethodVisibility"/>
+	<suppress files="JdbcOAuth2AuthorizationService\.java" checks="SpringMethodVisibility"/>
 	<suppress files="MapBasedMethodSecurityMetadataSourceTests\.java" checks="SpringMethodVisibility"/>
 	<suppress files="OAuth2ResourceServerBeanDefinitionParserTests\.java" checks="SpringMethodVisibility"/>
 	<suppress files="ObjectIdentityImplTests\.java" checks="SpringMethodVisibility"/>

+ 174 - 109
oauth2/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/JdbcOAuth2AuthorizationService.java

@@ -71,7 +71,6 @@ import org.springframework.security.oauth2.server.authorization.client.Registere
 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.ClassUtils;
 import org.springframework.util.CollectionUtils;
 import org.springframework.util.StringUtils;
 
@@ -245,11 +244,11 @@ public class JdbcOAuth2AuthorizationService implements OAuth2AuthorizationServic
 		Assert.notNull(lobHandler, "lobHandler cannot be null");
 		this.jdbcOperations = jdbcOperations;
 		this.lobHandler = lobHandler;
-		OAuth2AuthorizationRowMapper authorizationRowMapper = new OAuth2AuthorizationRowMapper(
+		JsonMapperOAuth2AuthorizationRowMapper authorizationRowMapper = new JsonMapperOAuth2AuthorizationRowMapper(
 				registeredClientRepository);
 		authorizationRowMapper.setLobHandler(lobHandler);
 		this.authorizationRowMapper = authorizationRowMapper;
-		this.authorizationParametersMapper = new OAuth2AuthorizationParametersMapper();
+		this.authorizationParametersMapper = new JsonMapperOAuth2AuthorizationParametersMapper();
 		initColumnMetadata(jdbcOperations);
 	}
 
@@ -467,18 +466,86 @@ public class JdbcOAuth2AuthorizationService implements OAuth2AuthorizationServic
 
 	/**
 	 * The default {@link RowMapper} that maps the current row in
-	 * {@code java.sql.ResultSet} to {@link OAuth2Authorization}.
+	 * {@code java.sql.ResultSet} to {@link OAuth2Authorization} using Jackson 3's
+	 * {@link JsonMapper} to read all {@code Map<String,Object>} within the result.
+	 *
+	 * @author Rob Winch
+	 * @since 7.0
 	 */
-	public static class OAuth2AuthorizationRowMapper implements RowMapper<OAuth2Authorization> {
+	public static class JsonMapperOAuth2AuthorizationRowMapper extends AbstractOAuth2AuthorizationRowMapper {
 
-		private final RegisteredClientRepository registeredClientRepository;
+		private final JsonMapper jsonMapper;
 
-		private LobHandler lobHandler = new DefaultLobHandler();
+		public JsonMapperOAuth2AuthorizationRowMapper(RegisteredClientRepository registeredClientRepository) {
+			this(registeredClientRepository, Jackson3.createJsonMapper());
+		}
+
+		public JsonMapperOAuth2AuthorizationRowMapper(RegisteredClientRepository registeredClientRepository,
+				JsonMapper jsonMapper) {
+			super(registeredClientRepository);
+			this.jsonMapper = jsonMapper;
+		}
+
+		@Override
+		Map<String, Object> readValue(String data) {
+			final ParameterizedTypeReference<Map<String, Object>> typeReference = new ParameterizedTypeReference<>() {
+			};
+			tools.jackson.databind.JavaType javaType = this.jsonMapper.getTypeFactory()
+				.constructType(typeReference.getType());
+			return this.jsonMapper.readValue(data, javaType);
+		}
 
-		private Mapper mapper = (ClassUtils.isPresent("tools.jackson.databind.json.JsonMapper",
-				OAuth2AuthorizationRowMapper.class.getClassLoader())) ? new JacksonDelegate() : new Jackson2Delegate();
+	}
+
+	/**
+	 * A {@link RowMapper} that maps the current row in {@code java.sql.ResultSet} to
+	 * {@link OAuth2Authorization} using Jackson 2's {@link ObjectMapper}.
+	 *
+	 * @deprecated Use {@link JsonMapperOAuth2AuthorizationRowMapper} to switch to Jackson
+	 * 3.
+	 */
+	@Deprecated(forRemoval = true, since = "7.0")
+	public static class OAuth2AuthorizationRowMapper extends AbstractOAuth2AuthorizationRowMapper {
+
+		private ObjectMapper objectMapper = Jackson2.createObjectMapper();
 
 		public OAuth2AuthorizationRowMapper(RegisteredClientRepository registeredClientRepository) {
+			super(registeredClientRepository);
+		}
+
+		public final void setObjectMapper(ObjectMapper objectMapper) {
+			Assert.notNull(objectMapper, "objectMapper cannot be null");
+			this.objectMapper = objectMapper;
+		}
+
+		protected ObjectMapper getObjectMapper() {
+			return this.objectMapper;
+		}
+
+		@Override
+		Map<String, Object> readValue(String data) throws JsonProcessingException {
+			final ParameterizedTypeReference<Map<String, Object>> typeReference = new ParameterizedTypeReference<>() {
+			};
+			com.fasterxml.jackson.databind.JavaType javaType = this.objectMapper.getTypeFactory()
+				.constructType(typeReference.getType());
+			return this.objectMapper.readValue(data, javaType);
+		}
+
+	}
+
+	/**
+	 * The base {@link RowMapper} that maps the current row in {@code java.sql.ResultSet}
+	 * to {@link OAuth2Authorization}. This is extracted to a distinct class so that
+	 * {@link OAuth2AuthorizationRowMapper} can be deprecated in favor of
+	 * {@link JsonMapperOAuth2AuthorizationRowMapper}.
+	 */
+	private abstract static class AbstractOAuth2AuthorizationRowMapper implements RowMapper<OAuth2Authorization> {
+
+		private final RegisteredClientRepository registeredClientRepository;
+
+		private LobHandler lobHandler = new DefaultLobHandler();
+
+		AbstractOAuth2AuthorizationRowMapper(RegisteredClientRepository registeredClientRepository) {
 			Assert.notNull(registeredClientRepository, "registeredClientRepository cannot be null");
 			this.registeredClientRepository = registeredClientRepository;
 		}
@@ -625,11 +692,6 @@ public class JdbcOAuth2AuthorizationService implements OAuth2AuthorizationServic
 			this.lobHandler = lobHandler;
 		}
 
-		public final void setMapper(Mapper mapper) {
-			Assert.notNull(mapper, "objectMapper cannot be null");
-			this.mapper = mapper;
-		}
-
 		protected final RegisteredClientRepository getRegisteredClientRepository() {
 			return this.registeredClientRepository;
 		}
@@ -638,33 +700,116 @@ public class JdbcOAuth2AuthorizationService implements OAuth2AuthorizationServic
 			return this.lobHandler;
 		}
 
-		protected final Mapper getMapper() {
-			return this.mapper;
-		}
-
 		private Map<String, Object> parseMap(String data) {
 			try {
-				return this.mapper.readValue(data, new ParameterizedTypeReference<>() {
-				});
+				return readValue(data);
 			}
 			catch (Exception ex) {
 				throw new IllegalArgumentException(ex.getMessage(), ex);
 			}
 		}
 
+		abstract Map<String, Object> readValue(String data) throws Exception;
+
+	}
+
+	/**
+	 * Nested class to protect from getting {@link NoClassDefFoundError} when Jackson 2 is
+	 * not on the classpath.
+	 *
+	 * @deprecated This is used to allow transition to Jackson 3. Use {@link Jackson3}
+	 * instead.
+	 */
+	@Deprecated(forRemoval = true, since = "7.0")
+	private static final class Jackson2 {
+
+		static ObjectMapper createObjectMapper() {
+			ObjectMapper objectMapper = new ObjectMapper();
+			ClassLoader classLoader = Jackson2.class.getClassLoader();
+			List<Module> securityModules = SecurityJackson2Modules.getModules(classLoader);
+			objectMapper.registerModules(securityModules);
+			objectMapper.registerModule(new OAuth2AuthorizationServerJackson2Module());
+			return objectMapper;
+		}
+
+	}
+
+	/**
+	 * Nested class used to get a common default instance of {@link JsonMapper}. It is in
+	 * a nested class to protect from getting {@link NoClassDefFoundError} when Jackson 3
+	 * is not on the classpath.
+	 */
+	private static final class Jackson3 {
+
+		static JsonMapper createJsonMapper() {
+			List<JacksonModule> modules = SecurityJacksonModules.getModules(Jackson3.class.getClassLoader());
+			return JsonMapper.builder()
+				.addModules(modules)
+				.addModules(new OAuth2AuthorizationServerJacksonModule())
+				.build();
+		}
+
+	}
+
+	/**
+	 * @deprecated Use {@link JsonMapperOAuth2AuthorizationParametersMapper} to migrate to
+	 * Jackson 3.
+	 */
+	@Deprecated(forRemoval = true, since = "7.0")
+	public static class OAuth2AuthorizationParametersMapper extends AbstractOAuth2AuthorizationParametersMapper {
+
+		private ObjectMapper objectMapper = Jackson2.createObjectMapper();
+
+		@Override
+		String writeValueAsString(Map<String, Object> data) throws JsonProcessingException {
+			return this.objectMapper.writeValueAsString(data);
+		}
+
+		protected final ObjectMapper getObjectMapper() {
+			return this.objectMapper;
+		}
+
+		public final void setObjectMapper(ObjectMapper objectMapper) {
+			Assert.notNull(objectMapper, "objectMapper cannot be null");
+			this.objectMapper = objectMapper;
+		}
+
 	}
 
 	/**
 	 * The default {@code Function} that maps {@link OAuth2Authorization} to a
-	 * {@code List} of {@link SqlParameterValue}.
+	 * {@code List} of {@link SqlParameterValue} using an instance of Jackson 3's
+	 * {@link JsonMapper}.
 	 */
-	public static class OAuth2AuthorizationParametersMapper
-			implements Function<OAuth2Authorization, List<SqlParameterValue>> {
+	public static final class JsonMapperOAuth2AuthorizationParametersMapper
+			extends AbstractOAuth2AuthorizationParametersMapper {
+
+		private final JsonMapper mapper;
+
+		public JsonMapperOAuth2AuthorizationParametersMapper() {
+			this(Jackson3.createJsonMapper());
+		}
+
+		public JsonMapperOAuth2AuthorizationParametersMapper(JsonMapper mapper) {
+			Assert.notNull(mapper, "mapper cannot be null");
+			this.mapper = mapper;
+		}
 
-		private Mapper mapper = (ClassUtils.isPresent("tools.jackson.databind.json.JsonMapper",
-				OAuth2AuthorizationRowMapper.class.getClassLoader())) ? new JacksonDelegate() : new Jackson2Delegate();
+		@Override
+		String writeValueAsString(Map<String, Object> data) throws Exception {
+			return this.mapper.writeValueAsString(data);
+		}
 
-		public OAuth2AuthorizationParametersMapper() {
+	}
+
+	/**
+	 * The base {@code Function} that maps {@link OAuth2Authorization} to a {@code List}
+	 * of {@link SqlParameterValue}.
+	 */
+	private abstract static class AbstractOAuth2AuthorizationParametersMapper
+			implements Function<OAuth2Authorization, List<SqlParameterValue>> {
+
+		protected AbstractOAuth2AuthorizationParametersMapper() {
 		}
 
 		@Override
@@ -736,15 +881,6 @@ public class JdbcOAuth2AuthorizationService implements OAuth2AuthorizationServic
 			return parameters;
 		}
 
-		public final void setMapper(Mapper mapper) {
-			Assert.notNull(mapper, "mapper cannot be null");
-			this.mapper = mapper;
-		}
-
-		protected final Mapper getMapper() {
-			return this.mapper;
-		}
-
 		private <T extends OAuth2Token> List<SqlParameterValue> toSqlParameterList(String tokenColumnName,
 				String tokenMetadataColumnName, OAuth2Authorization.Token<T> token) {
 
@@ -773,13 +909,15 @@ public class JdbcOAuth2AuthorizationService implements OAuth2AuthorizationServic
 
 		private String writeMap(Map<String, Object> data) {
 			try {
-				return this.mapper.writeValueAsString(data);
+				return writeValueAsString(data);
 			}
 			catch (Exception ex) {
 				throw new IllegalArgumentException(ex.getMessage(), ex);
 			}
 		}
 
+		abstract String writeValueAsString(Map<String, Object> data) throws Exception;
+
 	}
 
 	private static final class LobCreatorArgumentPreparedStatementSetter extends ArgumentPreparedStatementSetter {
@@ -850,77 +988,4 @@ public class JdbcOAuth2AuthorizationService implements OAuth2AuthorizationServic
 
 	}
 
-	public interface Mapper {
-
-		String writeValueAsString(Object data);
-
-		<T> T readValue(String value, ParameterizedTypeReference<T> typeReference);
-
-	}
-
-	@SuppressWarnings("removal")
-	public static class Jackson2Delegate implements Mapper {
-
-		private final ObjectMapper objectMapper = new ObjectMapper();
-
-		public Jackson2Delegate() {
-			ClassLoader classLoader = Jackson2Delegate.class.getClassLoader();
-			List<Module> securityModules = SecurityJackson2Modules.getModules(classLoader);
-			this.objectMapper.registerModules(securityModules);
-			this.objectMapper.registerModule(new OAuth2AuthorizationServerJackson2Module());
-		}
-
-		@Override
-		public String writeValueAsString(Object data) {
-			try {
-				return this.objectMapper.writeValueAsString(data);
-			}
-			catch (JsonProcessingException ex) {
-				throw new IllegalArgumentException(ex.getMessage(), ex);
-			}
-		}
-
-		@Override
-		public <T> T readValue(String value, ParameterizedTypeReference<T> typeReference) {
-			try {
-				com.fasterxml.jackson.databind.JavaType javaType = this.objectMapper.getTypeFactory()
-					.constructType(typeReference.getType());
-				return this.objectMapper.readValue(value, javaType);
-			}
-			catch (JsonProcessingException ex) {
-				throw new IllegalArgumentException(ex.getMessage(), ex);
-			}
-		}
-
-	}
-
-	public static class JacksonDelegate implements Mapper {
-
-		private final JsonMapper jsonMapper;
-
-		public JacksonDelegate() {
-			this(JsonMapper.builder());
-		}
-
-		public JacksonDelegate(JsonMapper.Builder builder) {
-			List<JacksonModule> modules = SecurityJacksonModules.getModules(getClass().getClassLoader());
-			this.jsonMapper = builder.addModules(modules)
-				.addModules(new OAuth2AuthorizationServerJacksonModule())
-				.build();
-		}
-
-		@Override
-		public String writeValueAsString(Object data) {
-			return this.jsonMapper.writeValueAsString(data);
-		}
-
-		@Override
-		public <T> T readValue(String value, ParameterizedTypeReference<T> typeReference) {
-			tools.jackson.databind.JavaType javaType = this.jsonMapper.getTypeFactory()
-				.constructType(typeReference.getType());
-			return this.jsonMapper.readValue(value, javaType);
-		}
-
-	}
-
 }

+ 16 - 3
oauth2/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/JdbcOAuth2AuthorizationServiceTests.java

@@ -32,8 +32,9 @@ import java.util.function.Function;
 import org.junit.jupiter.api.AfterEach;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
+import tools.jackson.core.type.TypeReference;
+import tools.jackson.databind.json.JsonMapper;
 
-import org.springframework.core.ParameterizedTypeReference;
 import org.springframework.dao.DataRetrievalFailureException;
 import org.springframework.jdbc.core.ArgumentPreparedStatementSetter;
 import org.springframework.jdbc.core.JdbcOperations;
@@ -44,6 +45,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.jackson.SecurityJacksonModules;
 import org.springframework.security.oauth2.core.AuthorizationGrantType;
 import org.springframework.security.oauth2.core.OAuth2AccessToken;
 import org.springframework.security.oauth2.core.OAuth2DeviceCode;
@@ -526,6 +528,12 @@ public class JdbcOAuth2AuthorizationServiceTests {
 		// @formatter:on
 	}
 
+	private static JsonMapper createSecurityMapper() {
+		return JsonMapper.builder()
+			.addModules(SecurityJacksonModules.getModules(JdbcOAuth2AuthorizationServiceTests.class.getClassLoader()))
+			.build();
+	}
+
 	private static final class CustomJdbcOAuth2AuthorizationService extends JdbcOAuth2AuthorizationService {
 
 		// @formatter:off
@@ -626,8 +634,11 @@ public class JdbcOAuth2AuthorizationServiceTests {
 		private static final class CustomOAuth2AuthorizationRowMapper
 				extends JdbcOAuth2AuthorizationService.OAuth2AuthorizationRowMapper {
 
+			private JsonMapper mapper;
+
 			private CustomOAuth2AuthorizationRowMapper(RegisteredClientRepository registeredClientRepository) {
 				super(registeredClientRepository);
+				this.mapper = createSecurityMapper();
 			}
 
 			@Override
@@ -747,7 +758,7 @@ public class JdbcOAuth2AuthorizationServiceTests {
 
 			private Map<String, Object> parseMap(String data) {
 				try {
-					return getMapper().readValue(data, new ParameterizedTypeReference<>() {
+					return this.mapper.readValue(data, new TypeReference<>() {
 					});
 				}
 				catch (Exception ex) {
@@ -760,6 +771,8 @@ public class JdbcOAuth2AuthorizationServiceTests {
 		private static final class CustomOAuth2AuthorizationParametersMapper
 				extends JdbcOAuth2AuthorizationService.OAuth2AuthorizationParametersMapper {
 
+			private final JsonMapper mapper = createSecurityMapper();
+
 			@Override
 			public List<SqlParameterValue> apply(OAuth2Authorization authorization) {
 				List<SqlParameterValue> parameters = new ArrayList<>();
@@ -852,7 +865,7 @@ public class JdbcOAuth2AuthorizationServiceTests {
 
 			private String writeMap(Map<String, Object> data) {
 				try {
-					return getMapper().writeValueAsString(data);
+					return this.mapper.writeValueAsString(data);
 				}
 				catch (Exception ex) {
 					throw new IllegalArgumentException(ex.getMessage(), ex);