#1 2022-03-26 23:23:09

dougb
Member
Registered: 2022-03-26
Posts: 2

JWT Decode Bug

If I decode a JWT that has a NULL field, then the verification fails and the decoding of the JSON payload stops at the field prior to the null value.

I'm sure I'm missing some expected behavior when it comes to null values, but couldn't find a solution after reading the documentation.

I first encountered this problem when trying to decode a JWT from a third party, where one of the fields was set to null.

Here's a console application that reproduces this error.

Program TestJwt;

{$APPTYPE CONSOLE}

{$R *.res}

uses
  System.SysUtils, SynCrypto, SynCommons;

var
  claims: TDocVariantData;
  j: TJWTHS256;
  claimArray: TTVarRecDynArray;
  token: RawUTF8;
  jwtContent: TJWTContent;
begin
  try
    claims.Init([], dvArray);
    claims.AddItem('Field1'); claims.AddItem('value-1');
    claims.AddItem('Field2'); claims.AddItem('value-2');
    claims.AddItem('Field3'); claims.AddItem(Null);
    claims.AddItem('Field4'); claims.AddItem('value-4');
    claims.AddItem('Field5'); claims.AddItem('value-5');

    j := TJWTHS256.Create('secret', 0, [], []);
    try
      Writeln('TOKEN');
      Writeln('-----');
      claims.ToArrayOfConst(claimArray);
      token := j.Compute(claimArray);
      Writeln(token);

      Writeln;
      Writeln('DECODED TOKEN');
      Writeln('-------------');
      j.Verify(token, jwtContent);
      Writeln(jwtContent.data.ToJSON);

      if (jwtContent.result <> jwtValid) then
        Writeln('**INVALID** TOKEN')
      else
        Writeln('TOKEN IS VALID');

    finally
      j.Free;
    end;
    Readln;
  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
end.

Offline

#2 2022-03-27 17:35:57

dougb
Member
Registered: 2022-03-26
Posts: 2

Re: JWT Decode Bug

It looks like commenting out the following line in SynCrypto.pas fixes this problem, although I don't know what other side-effects this might cause.

@ab Is this a valid solution? It seems to work when passing the resulting JSON to TDocVariantData.InitJSON() and then iterating through the fields.

procedure TJWTAbstract.Parse()
[...]
  if cap>0 then
  repeat
    N := GetJSONPropName(P);
    if N=nil then
      exit;
    V := GetJSONFieldOrObjectOrArray(P,@wasstring,@EndOfObject,true);
//    if V=nil then <<===============
//      exit;       <<===============
    len := StrLen(N);
    if len=3 then begin
      c := PInteger(N)^;
      for claim := low(claim) to high(claim) do
        if PInteger(JWT_CLAIMS_TEXT[claim])^=c then begin
          if V^=#0 then

Offline

#3 2022-03-28 07:00:00

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,324
Website

Re: JWT Decode Bug

This is likely to raise random GPF when V^ is accessed just after (e.g. for a 3 chars name).

Please try https://synopse.info/fossil/info/477b83cf44

Offline

Board footer

Powered by FluxBB