Skip to content
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

Access token with custom claims having value Long is throwing error: The class with java.lang.Long and name of java.lang.Long is not in the allowlist. #567

Closed
Ravis22 opened this issue Jan 5, 2022 · 2 comments
Assignees
Labels
status: duplicate A duplicate of another issue

Comments

@Ravis22
Copy link

Ravis22 commented Jan 5, 2022

Describe the bug
Custom access token with claim having value as Long is not getting revoked as during deserialization of access token object mapper throws error.

To Reproduce
User this access token to verify the deserialisation is failing
{"@Class":"java.util.Collections$UnmodifiableMap","metadata.token.claims":{"@Class":"java.util.Collections$UnmodifiableMap","sub":"535","user-authorities":["java.util.ArrayList",["ROLE_AUTHENTICATED"]],"iss":["java.net.URL","http://xxxxxxxl"],"userId":["java.lang.Long",535],"aud":["java.util.Collections$SingletonList",["messaging-client"]],"nbf":["java.time.Instant",1641370496.488606000],"permissions":["java.util.HashSet",[]],"scope":["java.util.Collections$UnmodifiableSet",["message.read"]],"name":"abcd","exp":["java.time.Instant",1641374096.488606000],"iat":["java.time.Instant",1641370496.488606000],"email":"abcd@gmail.com"},"metadata.token.invalidated":false}

Expected behavior
Access token should be properly deserialized and access token should be revoked.

Exception:

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.oauth2.server.authorization.JdbcOAuth2AuthorizationService$OAuth2AuthorizationRowMapper.parseMap(JdbcOAuth2AuthorizationService.java:441)
at org.springframework.security.oauth2.server.authorization.JdbcOAuth2AuthorizationService$OAuth2AuthorizationRowMapper.mapRow(JdbcOAuth2AuthorizationService.java:370)
at org.springframework.security.oauth2.server.authorization.JdbcOAuth2AuthorizationService$OAuth2AuthorizationRowMapper.mapRow(JdbcOAuth2AuthorizationService.java:308)
at org.springframework.jdbc.core.RowMapperResultSetExtractor.extractData(RowMapperResultSetExtractor.java:94)
at org.springframework.jdbc.core.RowMapperResultSetExtractor.extractData(RowMapperResultSetExtractor.java:61)
at org.springframework.jdbc.core.JdbcTemplate$1.doInPreparedStatement(JdbcTemplate.java:723)
at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:651)
at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:713)
at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:744)
at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:799)
at org.springframework.security.oauth2.server.authorization.JdbcOAuth2AuthorizationService.findBy(JdbcOAuth2AuthorizationService.java:257)
at org.springframework.security.oauth2.server.authorization.JdbcOAuth2AuthorizationService.findByToken(JdbcOAuth2AuthorizationService.java:238)
at org.springframework.security.oauth2.server.authorization.authentication.OAuth2TokenRevocationAuthenticationProvider.authenticate(OAuth2TokenRevocationAuthenticationProvider.java:63)
at org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:182)
at org.springframework.security.oauth2.server.authorization.web.OAuth2TokenRevocationEndpointFilter.doFilterInternal(OAuth2TokenRevocationEndpointFilter.java:104)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)

@Ravis22 Ravis22 added the type: bug A general bug label Jan 5, 2022
@Ravis22 Ravis22 changed the title Access token with custom claims having value Long is not getting revoked Access token with custom claims having value Long is throwing error: The class with java.lang.Long and name of java.lang.Long is not in the allowlist. Jan 5, 2022
@jgrandja
Copy link
Collaborator

jgrandja commented Jan 7, 2022

Closing as duplicate of gh-397

@jgrandja jgrandja closed this as completed Jan 7, 2022
@jgrandja jgrandja self-assigned this Jan 7, 2022
@jgrandja jgrandja added status: duplicate A duplicate of another issue and removed type: bug A general bug labels Jan 7, 2022
@kinsersh
Copy link

I'm seeing this same issue when attempting to use Spring Authorization Server with Okta, where the token from Okta contains a claim as follows:

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

It fails with the exception described in this issue after the OAuth 2 with Okta is complete and Spring Authorization Server has issued an authorization code to a relying party, and when the relying party is exchanging the authorization code for an access token.

kinsersh added a commit to kinsersh/spring-authorization-server that referenced this issue May 18, 2022
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"
    ]
  ]
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
status: duplicate A duplicate of another issue
Projects
None yet
Development

No branches or pull requests

3 participants