Skip to content

Allow java.lang.Long in whitelist for Jackson security #12294

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
mvitz opened this issue Nov 25, 2022 · 10 comments
Closed

Allow java.lang.Long in whitelist for Jackson security #12294

mvitz opened this issue Nov 25, 2022 · 10 comments
Assignees
Labels
status: declined A suggestion or change that we don't feel we should currently apply type: enhancement A general enhancement

Comments

@mvitz
Copy link
Contributor

mvitz commented Nov 25, 2022

Expected Behavior

When using spring-security-oauth2-client in combination with spring-session-data-redis and enabling JSON serializing via

@Bean
public RedisSerializer<Object> springSessionDefaultRedisSerializer() {
    var om = new ObjectMapper();
    om.registerModules(SecurityJackson2Modules.getModules(loader));
    return new GenericJackson2JsonRedisSerializer(om);
}

the session should be successfully deserialized when containing a type of java.lang.Long.

Current Behavior

The deserialization fails with the exception:

org.springframework.data.redis.serializer.SerializationException: Could not read JSON: The class with java.lang.Long and name of java.lang.Long is not in the allowlist. If you believe this class is safe to deserialize, please provide an explicit mapping using Jackson annotations or by providing a Mixin. If the serialization is only done by a trusted source, you can also enable default typing. See https://github.com/spring-projects/spring-security/issues/4370 for details (through reference chain: org.springframework.security.core.context.SecurityContextImpl["authentication"]->org.springframework.security.oauth2.client.authentication.OAuth2AuthenticationToken["principal"]->org.springframework.security.oauth2.core.oidc.user.DefaultOidcUser["authorities"]->org.springframework.security.oauth2.core.oidc.user.OidcUserAuthority["idToken"]->org.springframework.security.oauth2.core.oidc.OidcIdToken["claims"])

Context

At least our Okta returns a claim ver with a java.lang.Long of 1. When persisting the spring-security session with spring-session as JSON within redis this is serialized as

...
                "ver": [
                  "java.lang.Long",
                  1
                ],
...

and can not be deserialized because java.lang.Long is not within the allow list.

As a workaround, I can fall back to storing the session not as JSON.

@mvitz mvitz added status: waiting-for-triage An issue we've not yet triaged type: enhancement A general enhancement labels Nov 25, 2022
@TolstovM
Copy link

TolstovM commented Jan 24, 2023

Hello!
As a workaround you can create LongMixin
public abstract class LongMixin { }
and add it to your objectMapper

mapper.addMixIn(Long.class, LongMixin.class);

It works fine for me.

@TolstovM
Copy link

I've added PR, which would fix this issue #12584

@marcusdacoregio
Copy link
Contributor

I think that this is related to spring-projects/spring-session#2227

@TolstovM
Copy link

@marcusdacoregio Yep, it is

@marcusdacoregio
Copy link
Contributor

Hi @mvitz, which version of Spring Security and Spring Session are you using?

@marcusdacoregio marcusdacoregio added the status: waiting-for-feedback We need additional information before we can continue label Jan 30, 2023
@marcusdacoregio marcusdacoregio self-assigned this Jan 30, 2023
@marcusdacoregio marcusdacoregio removed the status: waiting-for-triage An issue we've not yet triaged label Jan 30, 2023
@mvitz
Copy link
Contributor Author

mvitz commented Jan 31, 2023

I think I was playing around with Spring Boot 3.0.0 which would resolve to:

  • Spring Security: 6.0.0
  • Spring Session: 3.0.0

@spring-projects-issues spring-projects-issues added status: feedback-provided Feedback has been provided and removed status: waiting-for-feedback We need additional information before we can continue labels Jan 31, 2023
@mvitz
Copy link
Contributor Author

mvitz commented Jan 31, 2023

After upgrading to Boot 3.0.2 (including 6.0.1) the same exception keeps occuring.

@gustavovitor
Copy link

The same issue it happens using spring-session-jdbc:

Caused by: java.lang.IllegalArgumentException: The class with java.lang.Long and name of java.lang.Long is not in the allowlist. If you believe this class is safe to deserialize, please provide an explicit mapping using Jackson annotations or by providing a Mixin. If the serialization is only done by a trusted source, you can also enable default typing. See https://github.com/spring-projects/spring-security/issues/4370 for details
	at org.springframework.security.jackson2.SecurityJackson2Modules$AllowlistTypeIdResolver.typeFromId(SecurityJackson2Modules.java:265) ~[spring-security-core-6.0.1.jar:6.0.1]
	at com.fasterxml.jackson.databind.jsontype.impl.TypeDeserializerBase._findDeserializer(TypeDeserializerBase.java:159) ~[jackson-databind-2.14.1.jar:2.14.1]
	at com.fasterxml.jackson.databind.jsontype.impl.AsArrayTypeDeserializer._deserialize(AsArrayTypeDeserializer.java:97) ~[jackson-databind-2.14.1.jar:2.14.1]
	at com.fasterxml.jackson.databind.jsontype.impl.AsArrayTypeDeserializer.deserializeTypedFromArray(AsArrayTypeDeserializer.java:53) ~[jackson-databind-2.14.1.jar:2.14.1]
	at com.fasterxml.jackson.databind.jsontype.impl.AsPropertyTypeDeserializer.deserializeTypedFromAny(AsPropertyTypeDeserializer.java:211) ~[jackson-databind-2.14.1.jar:2.14.1]
	at com.fasterxml.jackson.databind.deser.std.UntypedObjectDeserializerNR.deserializeWithType(UntypedObjectDeserializerNR.java:115) ~[jackson-databind-2.14.1.jar:2.14.1]
	at com.fasterxml.jackson.databind.deser.impl.TypeWrappedDeserializer.deserialize(TypeWrappedDeserializer.java:74) ~[jackson-databind-2.14.1.jar:2.14.1]
	at com.fasterxml.jackson.databind.deser.DefaultDeserializationContext.readRootValue(DefaultDeserializationContext.java:323) ~[jackson-databind-2.14.1.jar:2.14.1]
	at com.fasterxml.jackson.databind.ObjectMapper._readValue(ObjectMapper.java:4706) ~[jackson-databind-2.14.1.jar:2.14.1]
	at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:2879) ~[jackson-databind-2.14.1.jar:2.14.1]
	at org.springframework.security.oauth2.server.authorization.jackson2.UnmodifiableMapDeserializer.deserialize(UnmodifiableMapDeserializer.java:47) ~[spring-security-oauth2-authorization-server-1.0.0.jar:1.0.0]
	at org.springframework.security.oauth2.server.authorization.jackson2.UnmodifiableMapDeserializer.deserialize(UnmodifiableMapDeserializer.java:37) ~[spring-security-oauth2-authorization-server-1.0.0.jar:1.0.0]
	at com.fasterxml.jackson.databind.jsontype.impl.AsPropertyTypeDeserializer._deserializeTypedForId(AsPropertyTypeDeserializer.java:144) ~[jackson-databind-2.14.1.jar:2.14.1]
	at com.fasterxml.jackson.databind.jsontype.impl.AsPropertyTypeDeserializer.deserializeTypedFromObject(AsPropertyTypeDeserializer.java:110) ~[jackson-databind-2.14.1.jar:2.14.1]
	at com.fasterxml.jackson.databind.jsontype.impl.AsPropertyTypeDeserializer.deserializeTypedFromAny(AsPropertyTypeDeserializer.java:213) ~[jackson-databind-2.14.1.jar:2.14.1]
	at com.fasterxml.jackson.databind.deser.std.UntypedObjectDeserializerNR.deserializeWithType(UntypedObjectDeserializerNR.java:115) ~[jackson-databind-2.14.1.jar:2.14.1]
	at com.fasterxml.jackson.databind.deser.impl.TypeWrappedDeserializer.deserialize(TypeWrappedDeserializer.java:74) ~[jackson-databind-2.14.1.jar:2.14.1]
	at com.fasterxml.jackson.databind.deser.DefaultDeserializationContext.readRootValue(DefaultDeserializationContext.java:323) ~[jackson-databind-2.14.1.jar:2.14.1]
	at com.fasterxml.jackson.databind.ObjectMapper._readValue(ObjectMapper.java:4706) ~[jackson-databind-2.14.1.jar:2.14.1]
	at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:2879) ~[jackson-databind-2.14.1.jar:2.14.1]
	at org.springframework.security.oauth2.server.authorization.jackson2.UnmodifiableMapDeserializer.deserialize(UnmodifiableMapDeserializer.java:47) ~[spring-security-oauth2-authorization-server-1.0.0.jar:1.0.0]
	at org.springframework.security.oauth2.server.authorization.jackson2.UnmodifiableMapDeserializer.deserialize(UnmodifiableMapDeserializer.java:37) ~[spring-security-oauth2-authorization-server-1.0.0.jar:1.0.0]
	at com.fasterxml.jackson.databind.jsontype.impl.AsPropertyTypeDeserializer._deserializeTypedForId(AsPropertyTypeDeserializer.java:144) ~[jackson-databind-2.14.1.jar:2.14.1]
	at com.fasterxml.jackson.databind.jsontype.impl.AsPropertyTypeDeserializer.deserializeTypedFromObject(AsPropertyTypeDeserializer.java:110) ~[jackson-databind-2.14.1.jar:2.14.1]
	at com.fasterxml.jackson.databind.deser.std.MapDeserializer.deserializeWithType(MapDeserializer.java:492) ~[jackson-databind-2.14.1.jar:2.14.1]
	at com.fasterxml.jackson.databind.deser.impl.TypeWrappedDeserializer.deserialize(TypeWrappedDeserializer.java:74) ~[jackson-databind-2.14.1.jar:2.14.1]
	at com.fasterxml.jackson.databind.deser.DefaultDeserializationContext.readRootValue(DefaultDeserializationContext.java:323) ~[jackson-databind-2.14.1.jar:2.14.1]
	at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4730) ~[jackson-databind-2.14.1.jar:2.14.1]
	at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3677) ~[jackson-databind-2.14.1.jar:2.14.1]
	at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3660) ~[jackson-databind-2.14.1.jar:2.14.1]
	at org.springframework.security.oauth2.server.authorization.JdbcOAuth2AuthorizationService$OAuth2AuthorizationRowMapper.parseMap(JdbcOAuth2AuthorizationService.java:465) ~[spring-security-oauth2-authorization-server-1.0.0.jar:1.0.0]
	... 108 common frames omitted

@gustavovitor
Copy link

I don't know if collaborators team will be accept any pull request to solve it, but, we can implement our own RowMapper to solve it directly: https://stackoverflow.com/questions/72413823/spring-authorization-server-use-exit-model-for-user

This approach is elegant because we can map other classes such as a custom UserDetails.

@marcusdacoregio
Copy link
Contributor

Hi everyone, since this is an issue that is related to Spring Session, I'll close this as superseded by spring-projects/spring-session#2305. I'll prioritize that issue for the next minor release in Spring Session, so please subscribe to it and try the solution when it is out.

@marcusdacoregio marcusdacoregio added status: declined A suggestion or change that we don't feel we should currently apply and removed status: feedback-provided Feedback has been provided labels May 30, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
status: declined A suggestion or change that we don't feel we should currently apply type: enhancement A general enhancement
Projects
None yet
Development

No branches or pull requests

5 participants