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

Resource server token introspection - ClassCastException #153

Closed
cezaryluksza opened this issue Nov 6, 2023 · 3 comments
Closed

Resource server token introspection - ClassCastException #153

cezaryluksza opened this issue Nov 6, 2023 · 3 comments
Assignees
Labels
bug Something isn't working

Comments

@cezaryluksza
Copy link

cezaryluksza commented Nov 6, 2023

Hi

I decided to add token introspection to my resource server.
I followed this tutorial: https://github.com/ch4mpy/spring-addons/blob/spring-addons-7.1.8/samples/tutorials/resource-server_with_introspection/README.md

And I'm getting this exception in introspectionAuthenticationConverter():

java.lang.ClassCastException: class java.time.Instant cannot be cast to class java.lang.Integer (java.time.Instant and java.lang.Integer are in module java.base of loader 'bootstrap')
at com.c4_soft.springaddons.security.oidc.starter.synchronised.SpringAddonsOidcBeans.lambda$introspectionAuthenticationConverter$2(SpringAddonsOidcBeans.java:115)
at org.springframework.security.oauth2.server.resource.authentication.OpaqueTokenAuthenticationProvider.authenticate(OpaqueTokenAuthenticationProvider.java:109)

Attributes from my token:
iat -> {Instant@22266} "2023-11-06T10:48:02Z"
exp -> {Instant@22264} "2023-11-06T20:48:00Z"

I use keycloak token introspection endpoint.

Expected behavior
I think converter shouldn't assume that these attributes are castable to integers, but please correct me if I'm wrong.

Sample token JSON payload after anonymization (generated random UUID):

{
  "exp": 1699312319,
  "iat": 1699277575,
  "auth_time": 1699276319,
  "jti": "f260b55c-bb20-4976-be99-76d565944261",
  "iss": "XXX",
  "aud": [
    "account"
  ],
  "sub": "af298c5e-201d-40a9-a570-8bf06c4ec700",
  "typ": "Bearer",
  "azp": "XXX",
  "nonce": "69f9cff0-4178-41a3-a500-0721744e7002",
  "session_state": "60f12d89-721e-4598-bbf5-eaa7368a699c",
  "acr": "0",
  "allowed-origins": [
    "*"
  ],
  "realm_access": {
    "roles": [
      "offline_access",
      "default-roles-XXX",
      "uma_authorization"
    ]
  },
  "resource_access": {
    "XXX": {
      "roles": [
        "XXX"
      ]
    }
  },
  "scope": "openid profile email",
  "sid": "7e202aad-3447-4bc4-bf86-7a4b870a4466",
  "email_verified": true,
  "name": "XXX",
  "preferred_username": "XXX",
  "given_name": "XXX",
  "family_name": "XXX",
  "email": "XXX"
}
@cezaryluksza cezaryluksza added the bug Something isn't working label Nov 6, 2023
@ch4mpy
Copy link
Owner

ch4mpy commented Nov 6, 2023

This is a tricky question: the JWT spec states that the JSON value in the token payload should be a NumericDate (the number of seconds since January the 1st 1970 UTC), but there is nothing about the Java representation of the parsed JSON...

I am almost sure that Spring didn't map the value at the time the default OpaqueTokenAuthenticationConverter was written (accessing the iat claim was returning the number of seconds since EPOCH).

It would certainly be safer if this authentication converter was adapting to the type of value returned by the Java representation of the token claims.

Edit

The spec I link about JWTs is completely irrelevant: the introspected token can be in any format. What we are interested in is the format of the payload for the token introspection endpoint. But, according to this spec, the iat should be an integer in the introspection response too.

Got it: the claims are altered in SpringOpaqueTokenIntrospector::convertClaimsSet, which is private (among other things, Long values with seconds since EPOCH are replaced with Instant instances).

As each introspector implementation could have its own claim alteration rules, I'll have the default authentication converter accept Long, Instant and Date values for exp, iat.

ch4mpy added a commit that referenced this issue Nov 6, 2023
ch4mpy added a commit that referenced this issue Nov 6, 2023
@ch4mpy
Copy link
Owner

ch4mpy commented Nov 6, 2023

@cezaryluksza I just released a fix in 7.1.13. Please confirm it solves your problem and close.

@cezaryluksza
Copy link
Author

It works, thank you!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants