Can't read a string "aud" claim value from parsed JWT claims using JWTClaimsSet.getStringClaim(String name).

Issue #462 closed
hideki ikeda created an issue

Hi. Can you check the following code?

I thought the claims.getStringClaim("aud") part would return a String value (= "https://server.example.org") without throwing an exception. Is this a wrong assumption? (I know claims.getAudience() is available to get aud value but I would like to know if the following behavior of claims.getStringClaim("aud") is unexpected or on purpose.)

// A signed JWT. The payload value is:
//
//   {
//    "iss": "my-client",
//    "sub": "my-client",
//    "aud": "https://server.example.org",
//    "jti": "my-jwt-001",
//    "exp": 1744228361,
//    "iat": 1644228361
//   }
//
String jwt = "eyJhbGciOiJFUzI1NiJ9.ewogICAgImlzcyI6ICJteS1jbGllbnQiLAogICAgInN1YiI6ICJteS1jbGllbnQiLAogICAgImF1ZCI6ICJodHRwczovL3NlcnZlci5leGFtcGxlLm9yZyIsCiAgICAianRpIjogIm15LWp3dC0wMDEiLAogICAgImV4cCI6IDE3NDQyMjgzNjEsCiAgICAiaWF0IjogMTY0NDIyODM2MQp9.pleTdOmdI_nSIwmoC6U7f7xxrHrI2WAYskEsVSmoXoG5BOgGRH47fpd9JcS0qiDOM2kpSrCwzvSJbGkClfIAYg";

// Parse the JWT.
SignedJWT parsed = SignedJWT.parse(jwt);

// Get the claims.
JWTClaimsSet claims = parsed.getJWTClaimsSet();

// The following code throws a PraseException that says "The aud 
// claim is not a String". However, I expect getStringClaim("aud") 
// to return a String value (= "https://server.example.org").
// Is this a wrong assumption ?
String aud = claims.getStringClaim("aud");  

Comments (10)

  1. Vladimir Dzhuvinov

    Use the typed getAudience getter. The getStringClaims is unsafe because “aud” can also be a JSON array of strings.

  2. hideki ikeda reporter

    Thanks for your reply.

    Yeah, I know aud can be a JSON array of strings.

    Well, actually, my intention here is to distinguish the case where aud in the JWT is a string (e.g. https://server.example.org) from the case aud in the JWT is a JSON array of strings having single element (e.g. [https://server.example.org]).

    Can you distinguish those cases with this library? I guess you can’t do that using getAudience(). So I ended up using getStringClaims.

  3. Vladimir Dzhuvinov

    The parse method normalises the “aud” to a JSON array, that’s why you’re getting the exception: fa91260a

    If you peek inside the parse method you will see that. The intent is to catch illegal std claims early.

    To get the original claims set you can do parsed.getPayload().toJSONObject() and then do get(String) or use the typed JSONObjectUtils.getString.

  4. hideki ikeda reporter

    Cool! That’s exactly what I need. Thank for your swift responses!

    I’ll close this ticket.

  5. Log in to comment