JWT validation
-
I am working to decode a Json Web Token that is received as a certificate. The JWT is base64 encoded.
For the header of the JWT, I start with the following:
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzUxMiJ9
I base64 unecode and convert to a json document.
QJsonDocument jdocHeader = QJsonDocument::fromJson( QByteArray::fromBase64( QString("eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzUxMiJ9").toUtf8() ) );
When I convert to an object:
QJsonObject jobjHeader = jdocHeader.object();
I get what I expect:
{
"typ": "JWT",
"alg": "HS512"
}When I try to go back:
QByteArray qsHeader64 = QString( jdocHeader.toJson(QJsonDocument::JsonFormat::Compact).toBase64() );
I don't get the same original string, I get:
eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9
If I use QJsonDocument::JsonFormat::Indented, I also don't get the original string. What's going on?
-
Hi
Disclaimer. ultra tired so test might be incorrect.
AnywayQByteArray input = QByteArray::fromBase64( QString("eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzUxMiJ9").toUtf8() ); qDebug() << input.size() << "IN:>" << input.toStdString().c_str(); QJsonDocument jdocHeader = QJsonDocument::fromJson( input ) ; QJsonObject jobjHeader = jdocHeader.object(); qDebug() << jobjHeader; QByteArray qsHeader64 = jdocHeader.toJson(QJsonDocument::JsonFormat::Compact);//.toBase64() ; qDebug() << qsHeader64.size() << "OUT:>" << QString(qsHeader64); qDebug() << qsHeader64.toBase64(); qDebug() << "------------does order matter-------"; qDebug() << QByteArray("123456789").toBase64(); qDebug() << QByteArray("987654321").toBase64();
result
27 IN:> {"typ":"JWT","alg":"HS512"}
QJsonObject({"alg":"HS512","typ":"JWT"})
27 OUT:> "{"alg":"HS512","typ":"JWT"}"
"eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9"
------------does order matter-------
"MTIzNDU2Nzg5"
"OTg3NjU0MzIx"So it seems that the keys in the jsonobject are in other order and hence the base64 string becomes different.
-
Wow, nice find!! I've looked at this so long I didn't notice the difference in the order of the key-value pairs between the decoding by the debugger on jwt.io and the decoding performed by QJsonDocument::fromJson( ... ).object(). I confirm that I seem the same difference when stepping through the code.
So it seems either the ::fromJson or the .object is switching the order of the keys. If I do QJsonDocument::toJson( QJsonDocument::fromJson( ... ) ), the keys are already switched so it seems the fromJson() is switching them. This seems like a bug to me, no?
Any ideas for a work around?
-
I got lucky ;)
Well the order of keys is not really guaranteed as it just a map and its based on lookup so im not sure it qualifies as a bug.I would try to create an new jsonobject with the keys and see if inserting order is
fixed/deterministic and if yes, you could take the values and inset in new object and base64 that. -
@mgreenish
Im assume it comes from the internal structure used to keep the keys/value pairs but i didnt check the code to verify that.
I can see that is very annoying with JWT due to the nature of the service.
Im not sure what you need to do with it or if creating a new object can fix it.
In case you decide to use an other json lib, i can highly recommend
https://github.com/bblanchon/ArduinoJson
I didnt test if it would keep order but so far i didnt notice it didnt any re-order and we are using ith with base64 (to avoid clear text transfer) and not seen any issue.
(but no promises ;)
Its header only so really easy to get going.