Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Fix deserialize incompatibility with Okta ver claim
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": "login.at.okta.public.local@example.com", "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": "login.at.okta.public.local@example.com" } } }, { "@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": "login.at.okta.public.local@example.com", "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": "login.at.okta.public.local@example.com" } }, "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": "login.at.okta.public.local@example.com", "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": "login.at.okta.public.local@example.com" } } }, { "@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" ] ] }
- Loading branch information