-
Notifications
You must be signed in to change notification settings - Fork 30
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
Not validating #3
Comments
It seems that QJsonDocument switches the key-value pairs when it decodes the string. QJsonDocument::toJson( QJsonDocument::fromJson( QByteArray::fromBase64( QString("eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzUxMiJ9").toUtf8() ) ) ); results in the key-value pairs being switched. I expect the similar thing is happening with the payload, and so the signature calculated is different from the one in the certificate and validation fails. What version of QT was this written for? I am compiling on OS X with QT v5.5. |
Take a look at the QJsonWebToken::getSignature source code. Specially the first two lines, you can see that internally, The problem might be that when the Then take a look at how Qt parses the same Json: See the order difference in the payload? This might result in a different hash being computed. So validation the signature of both implementations will be different. The implications of this is that for the most part I would have loved to make this class compatible with other implementations, but that would require me to bypass Qt's Json parser and API and create my own and basically: |
Love that video! I understand that your goal was not to rewrite the JSON library for QT. There are lots of people complaining about that fact that the order is not maintained and you are right it is indeed alphabetical. However, the JSON spec does not require that order be maintained so it is not a bug. I have managed to change the order of the keys such that they are ordered alphabetically when the server creates that JWT. The jwt is now: eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJtaWtlLmdyZWVuaXNoQGFkZGhhcHRpY3MuY29tIiwiZGF0YSI6eyJjaWQiOiIxMDgwMTA4MDAwIiwibGljX2lkIjoiNSIsIm1vZHVsZXMiOjF9LCJleHAiOiIyMDE4LTA5LTI5VDE2OjE0OjQ0LTA0OjAwIiwiaWF0IjoiMjAxNy0wOS0yOVQxNjoxNDo0NC0wNDowMCIsImlzcyI6IkFkZCBIYXB0aWNzIn0.wiJ5D6zkk_K0JYizYQ-nAjlrEfZKyhIjOF8NcDLXnwWEGEzAjovcfUsLAcioVYBKhzVlOMydAPluTOfAD81H0Q The jwt.io debugger says it is valid. However, the QJsonWebToken says it is not valid. I have checked the base64 encoded compacted json header matches exactly the original header passed. For the payload, the calculated base64 encoded compacted json payload matches exactly but has an additional '=' on the end. In isValid() All data: "eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJtaWtlLmdyZWVuaXNoQGFkZGhhcHRpY3MuY29tIiwiZGF0YSI6eyJjaWQiOiIxMDgwMTA4MDAwIiwibGljX2lkIjoiNSIsIm1vZHVsZXMiOjF9LCJleHAiOiIyMDE4LTA5LTI5VDE2OjE0OjQ0LTA0OjAwIiwiaWF0IjoiMjAxNy0wOS0yOVQxNjoxNDo0NC0wNDowMCIsImlzcyI6IkFkZCBIYXB0aWNzIn0=" If I truncate the last byte of the array to remove the extra '=' as below, it still fails. All data: "eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJtaWtlLmdyZWVuaXNoQGFkZGhhcHRpY3MuY29tIiwiZGF0YSI6eyJjaWQiOiIxMDgwMTA4MDAwIiwibGljX2lkIjoiNSIsIm1vZHVsZXMiOjF9LCJleHAiOiIyMDE4LTA5LTI5VDE2OjE0OjQ0LTA0OjAwIiwiaWF0IjoiMjAxNy0wOS0yOVQxNjoxNDo0NC0wNDowMCIsImlzcyI6IkFkZCBIYXB0aWNzIn0" I know you are following the standard provided by jwt.io and you are using standard QT functions. And your code obviously worked for you. So may be it is a code base version issue? Can you run my jwt through on your end and see if it works? |
I have looked into the php implementation of the JWT library. Between the base64 encoding and the generation of the hash, there is a filter to make sure the base64-encoded string is url safe, as follows:
That would expain the stripping of the extra '=' on the end. Otherwise, the base64 encoded payloads are the same so that doesn't explain the difference in the hash. I will post the question on the qt forum to see if anyone can provide ideas on what may be the problem. Although the default character set of HTML5 is utf8, I'm not sure that a utf8 string is by default url-safe. Interestingly, stripping the extra '=' seems to have no impact on QT's abililty to convert the string back to the correct json object. |
Hi, If you use the jwtcreator example to create a JWT and then try to validate it with the jwtverifier example it will work for sure. Having this two examples running which actually use the same code (QJsonWebToken class), you can easily debug the JWT validation process. I believe the validation of the payload is failing for you because the I don't know how are your C++ skills, but the QByteArray QJsonWebToken::getSignature()
{
// get header in compact mode and base64 encoded
QByteArray byteHeaderBase64 = QByteArray("PasteYourHeaderHereInBase64");
// get payload in compact mode and base64 encoded
QByteArray bytePayloadBase64 = QByteArray("PasteYourPayloadHereInBase64");
// calculate signature based on chosen algorithm and secret
m_byteAllData = byteHeaderBase64 + "." + bytePayloadBase64;
// etc...
} See if the calculated signature matches what you expect, if it does, then the problem indeed the use of Good luck. |
One problem is that you are parsing the protected header and payload into However there is not a single way to convert your data into JSON because of:
The spec does not mandate that way the JSON should be encoded. What you really should do instead is keep the original string and validate against that. Morover, if you check one example of your implementation: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJldmVyeWJvZHkiLCJleHAiOiIxNTUzMTY0MTk2IiwiaWF0IjoiMTU1MjU1OTM5NiIsImlzcyI6Imp1YW5nYnVyZ29zIiwic3ViIjoiaGV5IHRoZXJlIn0=.jp8RV+4JOqsDqu56R7oIaD/U45KYEeUpqDc+/LeO6wg= Use are using base64 with padding:
Moreover, the JWT/JWS spec mandates base64 URL without padding so this implementation does not generate valid JWTs and cannot validate many JWTs for this reason. |
Do you think any of the available |
@juangburgos, Yes, the base64 encoding part should be fixeable with: |
* add additional header and payload bytearray members to fix signiture verification problem * base64 encoding is now Base64UrlEncoding as per standard * added OmitTrailingEquals when generating signiture * cmake and qt6 support * build examples on condition * fix minor bug and update examples Co-authored-by: Sadeq <sadeq.albana@snono-systems.com>
Thank you for this great bit of code! I am having a problem validating, however.
I created a jwt on the command line using php. I validated it via the jwt.io debugger. I am reading it into my application then passing it into an instanteation of your QJsonWebToken class through ::fromTokenAndSecret(). The header and payload are correct but when I call isValid(), it returns false.
By stepping through, I noticed that the call for getHeaderQStr( JsonDocument::Compact ) made from getSignature() which is made by isValid() returns a header QString this already diffferent than the header that is in the original JWT.
I noticed that when the header is first read, the format is QJsonDocument::Indented and during the validation, the header is encoded with QJsonDocument::Compact. Changing that to ::Indented in both cases did not correct the issue.
Below is my JWT
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzUxMiJ9.eyJpYXQiOiIyMDE3LTA5LTIyVDE5OjAzOjUyLTA0OjAwIiwiaXNzIjoiQWRkIEhhcHRpY3MiLCJleHAiOiIyMDE4LTA5LTIyVDE5OjAzOjUyLTA0OjAwIiwiYXVkIjoibWlrZS5ncmVlbmlzaEBhZGRoYXB0aWNzLmNvbSIsImRhdGEiOnsiY2lkIjoiMTMyMDEwODAwMCIsImxpY19pZCI6IjUiLCJtb2R1bGVzIjoxfX0.E42BptdM4nqmv-LDuMGIzsYnHjQRrvS0OScc4ctzDen8KAsfba9vQ2OVjveSDz0po6Ynm6lLjzkSnXnLNavH7Q
I am using base64 encoding
Any help you could provide with figuring out what I am doing wrong would be greatly appreciated.
The text was updated successfully, but these errors were encountered: