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

Handling updated_at claim as a String in JsonWebToken throws error when expected as a number #43924

Open
waldimiro opened this issue Oct 17, 2024 · 4 comments
Labels
area/security kind/bug Something isn't working

Comments

@waldimiro
Copy link

waldimiro commented Oct 17, 2024

Description:

I encountered an issue when working with JWTs (JSON Web Tokens) in Quarkus. Specifically, when I try to read the updated_at claim from the JsonWebToken, I receive an error if the value is a string instead of a number. This issue commonly arises when using Auth0 as the identity provider because Auth0 provides the updated_at field as an ISO 8601 string (e.g., "2024-10-16T08:30:00.000Z") rather than as a Unix timestamp (number).

Steps to Reproduce:

  1. Configure Auth0 as the authentication provider for the Quarkus application.
  2. Use Quarkus' JsonWebToken API to extract claims.
  3. Try to read the updated_at claim, which in Auth0 is a string (ISO 8601 format).
  4. Observe the error thrown.

Example Code:

<dependency>
	<groupId>io.quarkus</groupId>
	<artifactId>quarkus-oidc</artifactId>
</dependency>
<dependency>
	<groupId>io.quarkus</groupId>
	<artifactId>quarkus-smallrye-jwt</artifactId>
</dependency>
<dependency>
	<groupId>io.quarkus</groupId>
	<artifactId>quarkus-security</artifactId>
</dependency>
@Inject
JsonWebToken jwt;

public String getUpdatedAt() {
    Long updatedAt = jwt.getClaim("updated_at");  // This throws an error if "updated_at" is a string THE SAME IF YOU CLAIM OTHER FIELDS (ex. email, ...)
    return updatedAt != null ? updatedAt.toString() : "N/A";
}

Error:

The value of the 'updated_at' claim is not the expected type (2024-10-17T05:34:02.796Z - Cannot cast java.lang.String to java.lang.Number)

Can you help me? Thanks!!!

Environment:

Quarkus version: 3.14.4
Java version: jdk-21.0.3.9-hotspot

@quarkus-bot
Copy link

quarkus-bot bot commented Oct 17, 2024

/cc @pedroigor (bearer-token), @sberyozkin (bearer-token,jwt,security)

@geoand geoand added the kind/question Further information is requested label Oct 17, 2024
@sberyozkin
Copy link
Member

sberyozkin commented Oct 17, 2024

Hi @waldimiro

Unfortunately the current JsonWebToken API is untyped for those claims which have not been formally treated at the MP JWT level. There are plans to do something like jwt.getClaim("updated_at", Long.class), but without a hint like Long.class, the implementation does not know Long is expected.

So when you type Long updatedAt = jwt.getClaim("updated_at"); the error is inevitable if the claim value is String.
In this case you need to read it as String and use Java API to convert to date/etc.

Does it answer the question ?

@waldimiro
Copy link
Author

Hi @sberyozkin

thank you for your time! unfortunately, the problem is a little more insidious... as you can see, in the code snippet, I don't call jsonWebToken.getClaim(“updated_at”) but jsonWebToken.getRawToken() and jsonWebToken.getClaim(“email”) and yet the Quarkus console shows me the exception. The exception though doesn't block the application and is not fired since in the try/catch it is ignored. Is mostly annoying and I can only remove it with ENV variable -Dquarkus.log.category.\"org.jose4j\".level=OFF. The exception I see it every time I call getClaim(...) it almost seems like JWT validation happens in the background every time...

Code snippet

		if(jsonWebToken == null || StringUtils.isBlank(jsonWebToken.getRawToken())) {

			if(accountRequired) {
				throw new SystemException(SystemException.Status.UNAUTHENTICATED, "Account required");
			}

			return Optional.empty();
		}

		String email = jsonWebToken.getClaim("email");

Exception

: org.jose4j.jwt.MalformedClaimException: The value of the 'updated_at' claim is not the expected type (2024-10-18T05:56:53.674Z - Cannot cast java.lang.String to java.lang.Number)
	at org.jose4j.jwt.JwtClaims.getClaimValue(JwtClaims.java:256)
	at io.smallrye.jwt.auth.principal.DefaultJWTCallerPrincipal.getClaimValue(DefaultJWTCallerPrincipal.java:110)
	at io.smallrye.jwt.auth.principal.JWTCallerPrincipal.getClaim(JWTCallerPrincipal.java:93)
	at io.smallrye.jwt.auth.principal.JWTCallerPrincipal.toString(JWTCallerPrincipal.java:136)
	at io.smallrye.jwt.auth.principal.JWTCallerPrincipal.toString(JWTCallerPrincipal.java:105)
	at org.eclipse.microprofile.jwt.OidcJsonWebTokenProducer_ProducerMethod_currentAccessToken_bMms-Hu5y1Ct01k9iAujJbSp9Yc_ClientProxy.toString(Unknown Source)
...

@sberyozkin sberyozkin added kind/bug Something isn't working and removed kind/question Further information is requested labels Oct 18, 2024
@sberyozkin
Copy link
Member

sberyozkin commented Oct 18, 2024

@waldimiro Hi, I see it now at the smallrye-jwt level, it does expect this value be in the long format, I'm not sure now why this claim was even listed there, but I'll look at avoiding this log message

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

No branches or pull requests

3 participants