Fix OAuth2AuthorizationServerJacksonModule type validator configuration
Closes gh-18102
This commit is contained in:
+12
-5
@@ -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.
|
||||
*
|
||||
* <p>
|
||||
* <pre>
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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[])
|
||||
|
||||
+1
-1
@@ -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')
|
||||
|
||||
+3
-7
@@ -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<JacksonModule> modules = SecurityJacksonModules.getModules(Jackson3.class.getClassLoader());
|
||||
return JsonMapper.builder()
|
||||
.addModules(modules)
|
||||
.addModules(new OAuth2AuthorizationServerJacksonModule())
|
||||
.build();
|
||||
return JsonMapper.builder().addModules(modules).build();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+10
-16
@@ -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:
|
||||
*
|
||||
* <ul>
|
||||
* <li>{@link OAuth2TokenExchangeActor}</li>
|
||||
* <li>{@link OAuth2TokenExchangeActorMixin}</li>
|
||||
* <li>{@link OAuth2AuthorizationRequestMixin}</li>
|
||||
* <li>{@link OAuth2TokenExchangeCompositeAuthenticationTokenMixin}</li>
|
||||
* <li>{@link JwsAlgorithmMixin}</li>
|
||||
* <li>{@link OAuth2TokenFormatMixin}</li>
|
||||
* </ul>
|
||||
*
|
||||
* 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.
|
||||
* <p>
|
||||
* The recommended way to configure it is to use {@link SecurityJacksonModules} in order
|
||||
* to enable properly automatic inclusion of type information with related validation.
|
||||
*
|
||||
* <pre>
|
||||
* ClassLoader loader = getClass().getClassLoader();
|
||||
* JsonMapper mapper = JsonMapper.builder()
|
||||
* .addModules(new OAuth2AuthorizationServerJacksonModule()).build;
|
||||
* .addModules(SecurityJacksonModules.getModules(loader))
|
||||
* .build();
|
||||
* </pre>
|
||||
*
|
||||
* @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,
|
||||
|
||||
+28
-2
@@ -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<OAuth2Authorization> authorizationRowMapper = spy(
|
||||
new JdbcOAuth2AuthorizationService.OAuth2AuthorizationRowMapper(this.registeredClientRepository));
|
||||
new JdbcOAuth2AuthorizationService.JsonMapperOAuth2AuthorizationRowMapper(
|
||||
this.registeredClientRepository));
|
||||
this.authorizationService.setAuthorizationRowMapper(authorizationRowMapper);
|
||||
Function<OAuth2Authorization, List<SqlParameterValue>> 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);
|
||||
|
||||
+5
-3
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user