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
Fix usage of non JSON numeric values for time fractions (without having precision issues) #706
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Only int and float are accepted as returns from a converted date.
After reading all other discussions (and code for this PR) I have an impression there is no understanding on what's happening: php's float64 (and literally every other's programming language implementation of IEEE754) fails to represent precisely more than 53 bits of significand precision. This leads to "rounding" problem (which in fact is just lack of precision in the float64 ieee754 type, nothing really "rounds"). You cannot solve it in userland using built-in numeric types only. What MUST be done though: date fields MUST be encoded as numbers, it should not even be an option, it's REQUIRED by the spec. Ideally, all changes that led to making the generated jwt non-complaint should be reverted, because there is no way or need to "fix" it, since it only broke everything even "worse". What can be done if one wants precision over 53 bits of significand precision they need:
And once again: just shuffling
The problem with that "problem" is that it never was formalised: some arbitrary values were chosen as a "proof" of having the "issue" and then the "solution" was optimised to fit only that limited problem. If the library wants to solve the problem with "rounding" floats - then it should be first defined to what point. At this point it's not obvious why losing 18th significant digit is worse than losing 15th one. |
If you read my old PR #702, the goal was to keep the 6 decimal digits same from a timestamp after encoding/decoding Json. If you think my solution has a problem or won't work, can you show me a case or example and explain why?
Im talking only about the 6 digits of timestamp and not talking about floats
Can you please explain what you mean by this? Also what do you belive that can be changed to fix this "the bug is there and the referred PR is closed" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We're missing the test that guarantees that precision of time fractions is kept after the parsing - using that json_encode()
logic.
Without that we're just asserting that the claims are now using floats - which doesn't address the concern we had before.
I'll add the test and rebase your branch. Either we prove that your approach works or that @zerkms is correct.
Looking forward to hearing from you 👌. |
baed0bf
to
ba4aa2d
Compare
@Ocramius would you also have a look at this, please? |
$claims[$claim] = $this->convertDate((string) $claims[$claim]); | ||
$date = $claims[$claim]; | ||
|
||
$claims[$claim] = $this->convertDate(is_string($date) ? $date : json_encode($date, JSON_THROW_ON_ERROR)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To make this explicit as well, the check is only needed for compatibility with previously issued tokens...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Awesome solution, but I think we should keep integer type for integer timestamps
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Awesome solution, but I think we should keep integer type for integer timestamps
Yes, i remember now , That's why I left the integers and floats as returns. , because if you count, many use this library will got some problems about existing tokens that contains only integers. 👏🏻
I'll handle that int stuff. Thanks for the review @Slamdunk |
Your implementation would work, I just thought this: #618 (comment) was a problem.
Timestamp is encoded as a float. |
@lcobucci I was kinda glancing over this earlier today, and I don't see
massive problems with the patch itself.
It seems fine code-wise, but I don't understand the rationale behind it:
mostly lacking reference to issues connected to this.
Marco Pivetta
http://twitter.com/Ocramius
http://ocramius.github.com/
…On Fri, Mar 19, 2021 at 7:14 PM Luís Cobucci ***@***.***> wrote:
@Ocramius <https://github.com/Ocramius> would you also have a look at
this, please?
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#706 (comment)>, or
unsubscribe
<https://github.com/notifications/unsubscribe-auth/AABFVEHHKPAFNCDBP5OWXF3TEOIBZANCNFSM4ZNZFXFQ>
.
|
The RFC-7519 states that the `NumericDate` type is: > JSON numeric value representing the number of seconds from > 1970-01-01T00:00:00Z UTC until the specified UTC date/time, ignoring > leap seconds. Then also mentions that time fractions (as covered by RFC-3339) are supported: > Seconds Since the Epoch", in which each day is accounted for by > exactly 86400 seconds, other than that non-integer values can be > represented. While adding support for time fractions we've interpreted the "non-integer" really as any "non-integer" value, and used strings to guard against precision issues. That causes issues, since a string isn't a "JSON numeric value" according to the JSON specs. We observed that the 6-digit precision is not lost when doing JSON encode/decode operations, this applies that technique to make sure we comply to the specs and have "rounding issues" when dealing with floats.
@Ocramius I've tried to explain the issue on the commit message: 9a961f4 does it give you more info?
It is only a problem when casting to strings, that was @yassinrais' finding. |
I've applied the changes and extracted the test to a separate place, would you all give a final check? Even though this is a minor BC-break, it's solving a compatibility issue that has been introduced since v4.0 and we should ship it as a patch. |
@yassinrais once again, thank you very much for your help in finding the fix 👍 |
@lcobucci you're welcome ! |
🖋 The problem of precession of timestamp floats is solved by using a json_encode instead of (string).
This solves the float round problem when we encode/parse floats .