Skip to content
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

Only issue invalid base64 warning on successful decode #601

Closed
wants to merge 1 commit into from

Conversation

jeremyevans
Copy link

Description

To make the patch minimally invasive, this attempts to decode the given jwt in strict base64 mode only after a successful full decode and validation.

Most jwts are small, so this should have minimal performance impact, though it does require decoding twice. It is possible to fix the issue and only decode once, but it would be more invasive.

A big advantage of this approach is the use of :uplevel when calling Kernel#warn, so that the calling location that triggers the warning is included in the warning message, greatly simplifying debugging.

Checklist

Before the PR can be merged be sure the following are checked:

  • There are tests for the fix or feature added/changed
  • A description of the changes and a reference to the PR has been added to CHANGELOG.md. More details in the CONTRIBUTING.md

To make the patch minimally invasive, this attempts to decode the
given jwt in strict base64 mode only after a successful full
decode and validation.

Most jwts are small, so this should have minimal performance
impact, though it does require decoding twice.  It is possible to
fix the issue and only decode once, but it would be more invasive.

A big advantage of this approach is the use of :uplevel when
calling Kernel#warn, so that the calling location that triggers
the warning is included in the warning message, greatly simplifying
debugging.

Co-authored-by: Joakim Antman <antmanj@gmail.com>
@anakinj
Copy link
Member

anakinj commented Jun 16, 2024

Thanks for taking the time thinking about this. In this approach the concern is that now it's doing this for every successful decode "just in case".

@jeremyevans
Copy link
Author

Thanks for taking the time thinking about this. In this approach the concern is that now it's doing this for every successful decode "just in case".

Correct. It's a simpler approach. I'm not sure what the performance difference is, but I expect it to be small unless the JWTs are quite large. Would you like me to benchmark both approaches?

@anakinj
Copy link
Member

anakinj commented Jun 16, 2024

My only argument against this is that it will affect all the requests that have no issue with base64 encoding, the assumption that JWTs are small is a bit dangerous :)

Benchmarking would be interesting. On the other hand one could focus on trying to get a new major version out there that would just remove all this complexity of being nice to the user.

@jeremyevans
Copy link
Author

Here's a benchmark:

require 'benchmark/ips'
require 'jwt'

h = {}
ARGV[0].to_i.times{|i| h[i.to_s] = i}
key = '1'*32
jwt = JWT.encode(h, key)

Benchmark.ips do |x|
  x.report('decode'){JWT.decode(jwt, key)}
end

Performance of #601 is about 5-10% worse than #600 depending on the size of the JWT:

#601:

0 entries:
              decode     18.119k (_ 2.8%) i/s -     91.884k in   5.075099s
10000 entries:
              decode    199.303 (_ 3.0%) i/s -      1.008k in   5.061691s

#600:

0 entries:
              decode     18.959k (_ 1.6%) i/s -     94.770k in   5.000008s
10000 entries:
              decode    220.187 (_ 3.6%) i/s -      1.113k in   5.060928

Parsing JSON is much slower than decoding base64, which is why even for large JWTs, this will never result in a major slowdown. Up to you whether the simpler implementation and easier debugging (via uplevel) in this approach is worth the slight decrease in performance.

@jeremyevans
Copy link
Author

Closing as fixed by #600.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants