Skip to content

fpjwt cannot process JWT tokens when audience is an array - EJSON exception "Cannot convert data from array value" raised

Summary

TClaims implement aud as a string.

TClaims = Class(TBaseJWT)
  private
    FAud: String;  //Bug: this could be an array of strings, and usually is
    FExp: Int64;
    FIat: Int64;
    FIss: String;
    FJTI: String;
    FNbf: Int64;
    FSub: String;
  Published
    // Registered Claim Names. Keep the case lowercase, the RTTI must match the registered name.
    Property iss : String Read FIss Write FIss;
    Property sub : String Read FSub Write FSub;
    Property aud : String Read FAud Write FAud; //Bug: this could be an array of strings, and usually is
    Property exp : Int64 Read FExp Write FExp;
    Property nbf : Int64 Read FNbf Write FNbf;
    Property iat : Int64 Read FIat Write FIat;
    Property jti : String Read FJTI Write FJTI;
  end;

But RFC 7519 (https://datatracker.ietf.org/doc/html/rfc7519#section-4.1.3) states: "In the general case, the "aud" value is an array of case-sensitive strings, each containing a StringOrURI value. In the special case when the JWT has one audience, the "aud" value MAY be a single case-sensitive string containing a StringOrURI value."

For example Keycloak 24+ returns a token like:

{
    "exp": 1743759752,
    "iat": 1743759452,
    "auth_time": 1743759451,
    "jti": "fccaf7dc-bebb-46ae-8d94-8fccc11a697f",
    "iss": "https://www.example.com/realms/myrealm",
    "aud": [
        "myaud_1",
        "myaud_2",
        "myaud_3",
        "account"
    ],
    "sub": "172bd0d2-8d4a-4ed7-9d7a-81a5c104dad7",
    "typ": "Bearer",
    "azp": "myapp",
    "nonce": "8624221b-4683-4d05-867b-0077fadc2b56",
    "session_state": "5acb3131-4393-4883-b08a-31ce77184092",

System Information

  • Ubuntu 22 LTS
  • x86-64
  • FPC 3.3.1
  • Computer

Steps to reproduce

This simple code:

var
  AuthHdr: string;  // Keycloak issued token
  JWTData: TJWT;
  PubKey: string;  // Keycloak public key

JWTData := TJWT.ValidateJWT(AuthHdr, TJWTKey.Create(PemToDER(PubKey, '', '')));

Will rise a EJSON exception when trying to validate the token, since it can process the aud field correctly.

Example Project

What is the current bug behavior?

EJSON exception raised "Cannot convert data from array value".

What is the expected (correct) behavior?

No exception is raised and the "aud" field is processed and filled correctly, containing all audiences - that's needed to check if the call can be processed or not.

Relevant logs and/or screenshots

To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information