SkyLothar / lua-resty-jwt

JWT For The Great Openresty
Apache License 2.0
513 stars 179 forks source link

Validation of HS* tokens depends on the payload order #101

Closed gelin closed 1 year ago

gelin commented 1 year ago

For example:

The token: eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiI1Nzc2ZWI2NS04MzUwLTQ2YmEtOTQwMy05Y2RiNWQyYjZiMGQiLCJub25jZSI6MTY3NTQxMjAyOTA0MywiaWF0IjoxNjc1NDEyMDI5fQ.nxW_dLQREtXEQDm4yjLjtQTa7qDQBCT6rQVVmtZP5ogCKl-2OG7UhQIGH4GGYKTOchbFYZJwlA4IT1jXB6Emhg with payload: {"sub":"5776eb65-8350-46ba-9403-9cdb5d2b6b0d","nonce":1675412029043,"iat":1675412029} always fails validation. The failure reason is: signature mismatch: nxW_dLQREtXEQDm4yjLjtQTa7qDQBCT6rQVVmtZP5ogCKl-2OG7UhQIGH4GGYKTOchbFYZJwlA4IT1jXB6Emhg (see, it matches with the original signature!)

But the token: eyJhbGciOiJIUzUxMiJ9.eyJpYXQiOjE2NzU0MTIwMjksInN1YiI6IjU3NzZlYjY1LTgzNTAtNDZiYS05NDAzLTljZGI1ZDJiNmIwZCIsIm5vbmNlIjoxNjc1NDEyMDI5MDQzfQ.Ds_iyozfEtEreiqwPL9wmdX7Lrwj0QtLjQPmJMo0t-cCQZxcOAaaXPxBJjEjNBY2YJUY8_fTSXYToVp6SGKhrw with payload: {"iat":1675412029,"sub":"5776eb65-8350-46ba-9403-9cdb5d2b6b0d","nonce":1675412029043} passed the validation.

The difference is only in the order of payload keys. You can use any secret for signature.

Probably, the problem is in these lines of code in jwt.lua:

local jwt_str = string_format(str_const.regex_jwt_join_str, jwt_obj.raw_header , jwt_obj.raw_payload , jwt_obj.signature)
-- ...
  if alg == str_const.HS256 or alg == str_const.HS512 then
    local success, ret = pcall(_M.sign, self, secret, jwt_obj)
    --- ...
    elseif jwt_str ~= ret then
      -- signature check
      jwt_obj[str_const.reason] = "signature mismatch: " .. jwt_obj[str_const.signature]

Not only the signature, but the whole token strings are compared. But it looks like somewhere the payload keys are reordered producing another base64 content for it.

gelin commented 1 year ago

Looks like somebody in the mirror is an idiot. Probably, the issue is not in this lib, but in how the tokens are generated in my system....