-
Notifications
You must be signed in to change notification settings - Fork 6k
Add Allow List to Jackson Support #4370
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
Comments
org.springframework.security.authentication.BadCredentialsException is not whitelisted. 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 #4370 for details; nested exception is java. |
Since the error message points to this issue, can it please get a link to documentation on enabling default typing? |
Hi. i have same issue and cant find how to enable default typing. i really appreciate if you provide a link or something else that says how to do it. |
To (de)serialize a @Bean
public ObjectMapper objectMapper() {
ObjectMapper mapper = new ObjectMapper()
mapper.registerModule(new CoreJackson2Module());
// ... your other configuration
return mapper;
} This calls |
Good |
I am getting the following error when I try to deserialize the OAuth2AuthenticationToken |
Okta includes a "ver" claim in the ID tokens it issues that gets serialized to json, as follows: { "@Class": "java.util.Collections$UnmodifiableMap", "ver": [ "java.lang.Long", 1 ] } This claim is added by Okta automatically (see https://developer.okta.com/docs/reference/api/oidc/#id-token). Spring Authorization Server encounters an error when attempting to deserialize this claim from Okta, as follows: 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 spring-projects/spring-security#4370 for details 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 spring-projects/spring-security#4370 for details at org.springframework.security.jackson2.SecurityJackson2Modules$AllowlistTypeIdResolver.typeFromId(SecurityJackson2Modules.java:253) The issue at spring-projects#567 has a similar symptom, though this situation would be encountered by any project wanting to do OpenID Connect with Okta. I thus recommend a general fix rather than a project-specific fix as recommended at spring-projects#397. This commit defines a mixin that doesn't alter the json formatting but does instruct SecurityJackson2Modules.AllowlistTypeIdResolver to permit the deseralization of that Okta claim. For broader context, below is an example of what is stored by Spring Authorization Server in the attributes column of the oauth2_authorization table. { "@Class": "java.util.Collections$UnmodifiableMap", "org.springframework.security.oauth2.core.endpoint.OAuth2AuthorizationRequest": { "@Class": "org.springframework.security.oauth2.core.endpoint.OAuth2AuthorizationRequest", "authorizationUri": "http://localhost:5000/oauth2/authorize", "authorizationGrantType": { "value": "authorization_code" }, "responseType": { "value": "code" }, "clientId": "login-acceptance-test-client", "redirectUri": "http://127.0.0.1:5000/login-acceptance-test-client", "scopes": [ "java.util.Collections$UnmodifiableSet", [ "openid" ] ], "state": "foo", "additionalParameters": { "@Class": "java.util.Collections$UnmodifiableMap" }, "authorizationRequestUri": "http://localhost:5000/oauth2/authorize?response_type=code&client_id=login-acceptance-test-client&scope=openid&state=foo&redirect_uri=http://127.0.0.1:5000/login-acceptance-test-client", "attributes": { "@Class": "java.util.Collections$UnmodifiableMap" } }, "java.security.Principal": { "@Class": "org.springframework.security.oauth2.client.authentication.OAuth2AuthenticationToken", "principal": { "@Class": "org.springframework.security.oauth2.core.oidc.user.DefaultOidcUser", "authorities": [ "java.util.Collections$UnmodifiableSet", [ { "@Class": "org.springframework.security.oauth2.core.oidc.user.OidcUserAuthority", "authority": "ROLE_USER", "idToken": { "@Class": "org.springframework.security.oauth2.core.oidc.OidcIdToken", "tokenValue": "actualTokenValueRemoved", "issuedAt": 1652411922.000000000, "expiresAt": 1652415522.000000000, "claims": { "@Class": "java.util.Collections$UnmodifiableMap", "at_hash": "X4TpvHXTMw3kaBMRas-H6A", "sub": "00u4zn2e0w8cRRFv75d1", "ver": [ "java.lang.Long", 1 ], "amr": [ "java.util.ArrayList", [ "pwd" ] ], "iss": [ "java.net.URL", "https://dev-231911394952.okta.com" ], "preferred_username": "login.at.okta.public.local", "nonce": "pWQDfOxvpslr_FWiTqHlIRdCiT5Sfq-PWvBmSyrDki0", "aud": [ "java.util.ArrayList", [ "0oa4varwxxjIMcDph5d7" ] ], "idp": "00otba6t5x5dSt78H5d6", "auth_time": [ "java.time.Instant", 1652411920.000000000 ], "name": "login at okta public local test", "exp": [ "java.time.Instant", 1652415522.000000000 ], "iat": [ "java.time.Instant", 1652411922.000000000 ], "email": "[email protected]", "jti": "ID.IfAKG8WvCxOy023DLl6I-WY-4pHgxMJZv1F79rqAtYM" } }, "userInfo": { "@Class": "org.springframework.security.oauth2.core.oidc.OidcUserInfo", "claims": { "@Class": "java.util.Collections$UnmodifiableMap", "sub": "00u4zn2e0w8cRRFv75d1", "zoneinfo": "America/Los_Angeles", "email_verified": true, "updated_at": [ "java.time.Instant", 1652216788.000000000 ], "name": "login at okta public local test", "preferred_username": "login.at.okta.public.local", "locale": "en_US", "given_name": "login at okta public local", "family_name": "test", "email": "[email protected]" } } }, { "@Class": "org.springframework.security.core.authority.SimpleGrantedAuthority", "authority": "SCOPE_email" }, { "@Class": "org.springframework.security.core.authority.SimpleGrantedAuthority", "authority": "SCOPE_openid" }, { "@Class": "org.springframework.security.core.authority.SimpleGrantedAuthority", "authority": "SCOPE_phone" }, { "@Class": "org.springframework.security.core.authority.SimpleGrantedAuthority", "authority": "SCOPE_profile" } ] ], "idToken": { "@Class": "org.springframework.security.oauth2.core.oidc.OidcIdToken", "tokenValue": "actualTokenValueRemoved", "issuedAt": 1652411922.000000000, "expiresAt": 1652415522.000000000, "claims": { "@Class": "java.util.Collections$UnmodifiableMap", "at_hash": "X4TpvHXTMw3kaBMRas-H6A", "sub": "00u4zn2e0w8cRRFv75d1", "ver": [ "java.lang.Long", 1 ], "amr": [ "java.util.ArrayList", [ "pwd" ] ], "iss": [ "java.net.URL", "https://dev-231911394952.okta.com" ], "preferred_username": "login.at.okta.public.local", "nonce": "pWQDfOxvpslr_FWiTqHlIRdCiT5Sfq-PWvBmSyrDki0", "aud": [ "java.util.ArrayList", [ "0oa4varwxxjIMcDph5d7" ] ], "idp": "00otba6t5x5dSt78H5d6", "auth_time": [ "java.time.Instant", 1652411920.000000000 ], "name": "login at okta public local test", "exp": [ "java.time.Instant", 1652415522.000000000 ], "iat": [ "java.time.Instant", 1652411922.000000000 ], "email": "[email protected]", "jti": "ID.IfAKG8WvCxOy023DLl6I-WY-4pHgxMJZv1F79rqAtYM" } }, "userInfo": { "@Class": "org.springframework.security.oauth2.core.oidc.OidcUserInfo", "claims": { "@Class": "java.util.Collections$UnmodifiableMap", "sub": "00u4zn2e0w8cRRFv75d1", "zoneinfo": "America/Los_Angeles", "email_verified": true, "updated_at": [ "java.time.Instant", 1652216788.000000000 ], "name": "login at okta public local test", "preferred_username": "login.at.okta.public.local", "locale": "en_US", "given_name": "login at okta public local", "family_name": "test", "email": "[email protected]" } }, "nameAttributeKey": "sub" }, "authorities": [ "java.util.Collections$UnmodifiableRandomAccessList", [ { "@Class": "org.springframework.security.oauth2.core.oidc.user.OidcUserAuthority", "authority": "ROLE_USER", "idToken": { "@Class": "org.springframework.security.oauth2.core.oidc.OidcIdToken", "tokenValue": "actualTokenValueRemoved", "issuedAt": 1652411922.000000000, "expiresAt": 1652415522.000000000, "claims": { "@Class": "java.util.Collections$UnmodifiableMap", "at_hash": "X4TpvHXTMw3kaBMRas-H6A", "sub": "00u4zn2e0w8cRRFv75d1", "ver": [ "java.lang.Long", 1 ], "amr": [ "java.util.ArrayList", [ "pwd" ] ], "iss": [ "java.net.URL", "https://dev-231911394952.okta.com" ], "preferred_username": "login.at.okta.public.local", "nonce": "pWQDfOxvpslr_FWiTqHlIRdCiT5Sfq-PWvBmSyrDki0", "aud": [ "java.util.ArrayList", [ "0oa4varwxxjIMcDph5d7" ] ], "idp": "00otba6t5x5dSt78H5d6", "auth_time": [ "java.time.Instant", 1652411920.000000000 ], "name": "login at okta public local test", "exp": [ "java.time.Instant", 1652415522.000000000 ], "iat": [ "java.time.Instant", 1652411922.000000000 ], "email": "[email protected]", "jti": "ID.IfAKG8WvCxOy023DLl6I-WY-4pHgxMJZv1F79rqAtYM" } }, "userInfo": { "@Class": "org.springframework.security.oauth2.core.oidc.OidcUserInfo", "claims": { "@Class": "java.util.Collections$UnmodifiableMap", "sub": "00u4zn2e0w8cRRFv75d1", "zoneinfo": "America/Los_Angeles", "email_verified": true, "updated_at": [ "java.time.Instant", 1652216788.000000000 ], "name": "login at okta public local test", "preferred_username": "login.at.okta.public.local", "locale": "en_US", "given_name": "login at okta public local", "family_name": "test", "email": "[email protected]" } } }, { "@Class": "org.springframework.security.core.authority.SimpleGrantedAuthority", "authority": "SCOPE_email" }, { "@Class": "org.springframework.security.core.authority.SimpleGrantedAuthority", "authority": "SCOPE_openid" }, { "@Class": "org.springframework.security.core.authority.SimpleGrantedAuthority", "authority": "SCOPE_phone" }, { "@Class": "org.springframework.security.core.authority.SimpleGrantedAuthority", "authority": "SCOPE_profile" } ] ], "authorizedClientRegistrationId": "oktaDev", "details": { "@Class": "org.springframework.security.web.authentication.WebAuthenticationDetails", "remoteAddress": "127.0.0.1", "sessionId": "A8634EA2537A251E8B3D22A5CC4A6E3D" } }, "org.springframework.security.oauth2.server.authorization.OAuth2Authorization.AUTHORIZED_SCOPE": [ "java.util.Collections$UnmodifiableSet", [ "openid" ] ] }
{ |
I have the same issue too. Has there been a fix for this? |
The same happens in Kotlin projects, e.g. |
I am getting this error when attempt to generate refresh token. Using Spring Boot authorization server v3 |
my solution for OAuth2AuthorizationService config. @JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY, property = "@class")
public abstract static class SynchronizedSetMixin {
}
@Bean
public OAuth2AuthorizationService authorizationService(JdbcTemplate jdbcTemplate,
RegisteredClientRepository registeredClientRepository) {
JdbcOAuth2AuthorizationService.OAuth2AuthorizationRowMapper rowMapper =
new JdbcOAuth2AuthorizationService.OAuth2AuthorizationRowMapper(registeredClientRepository);
JdbcOAuth2AuthorizationService.OAuth2AuthorizationParametersMapper oAuth2AuthorizationParametersMapper =
new JdbcOAuth2AuthorizationService.OAuth2AuthorizationParametersMapper();
JdbcOAuth2AuthorizationService authorizationService =
new JdbcOAuth2AuthorizationService(jdbcTemplate, registeredClientRepository);
ObjectMapper objectMapper = new ObjectMapper();
ClassLoader classLoader = JdbcOAuth2AuthorizationService.class.getClassLoader();
List<Module> securityModules = SecurityJackson2Modules.getModules(classLoader);
objectMapper.registerModules(securityModules);
objectMapper.registerModule(new OAuth2AuthorizationServerJackson2Module());
objectMapper.addMixIn(Collections.synchronizedSet(new HashSet<>()).getClass(), SynchronizedSetMixin.class);
rowMapper.setObjectMapper(objectMapper);
oAuth2AuthorizationParametersMapper.setObjectMapper(objectMapper);
authorizationService.setAuthorizationRowMapper(rowMapper);
authorizationService.setAuthorizationParametersMapper(oAuth2AuthorizationParametersMapper);
return authorizationService;
} |
The class with java.util.ImmutableCollections$List12 and name of java.util.ImmutableCollections$List12 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 #4370 for details??? 所以这个是什么情况?
} ` ` @JsonTypeInfo(use = JsonTypeInfo.Id.CLASS)
} ` |
The class with com.example.authservice.security.models.CustomSecurityUserDetails and name of com.example.authservice.security.models.CustomSecurityUserDetails is not in the allowlist. My Solution which worked for me was to create Deserializer for the class @JsonTypeInfo(
use = JsonTypeInfo.Id.CLASS,
include = JsonTypeInfo.As.PROPERTY
)
@JsonDeserialize(
using = CustomSecurityUserDeserializer.class
)
@JsonAutoDetect(
fieldVisibility = JsonAutoDetect.Visibility.ANY,
getterVisibility = JsonAutoDetect.Visibility.NONE,
isGetterVisibility = JsonAutoDetect.Visibility.NONE
)
@JsonIgnoreProperties(
ignoreUnknown = true
)
public class CustomSecurityUserDetails implements UserDetails {
.....
.....
} |
… 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 spring-projects/spring-security#4370 for details (through reference chain: java.util.HashMap["lastAccessedTime"])
Summary
There are some performance optimizations we can provide for jackson integration
The text was updated successfully, but these errors were encountered: