jwt 2.4.1 → 2.9.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (77) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +177 -14
  3. data/CONTRIBUTING.md +7 -7
  4. data/README.md +180 -37
  5. data/lib/jwt/base64.rb +33 -0
  6. data/lib/jwt/claims/audience.rb +20 -0
  7. data/lib/jwt/claims/decode_verifier.rb +40 -0
  8. data/lib/jwt/claims/expiration.rb +22 -0
  9. data/lib/jwt/claims/issued_at.rb +15 -0
  10. data/lib/jwt/claims/issuer.rb +24 -0
  11. data/lib/jwt/claims/jwt_id.rb +25 -0
  12. data/lib/jwt/claims/not_before.rb +22 -0
  13. data/lib/jwt/claims/numeric.rb +55 -0
  14. data/lib/jwt/claims/required.rb +23 -0
  15. data/lib/jwt/claims/subject.rb +20 -0
  16. data/lib/jwt/claims/verifier.rb +62 -0
  17. data/lib/jwt/claims.rb +82 -0
  18. data/lib/jwt/claims_validator.rb +3 -24
  19. data/lib/jwt/configuration/container.rb +32 -0
  20. data/lib/jwt/configuration/decode_configuration.rb +46 -0
  21. data/lib/jwt/configuration/jwk_configuration.rb +27 -0
  22. data/lib/jwt/configuration.rb +15 -0
  23. data/lib/jwt/decode.rb +54 -41
  24. data/lib/jwt/deprecations.rb +48 -0
  25. data/lib/jwt/encode.rb +21 -21
  26. data/lib/jwt/error.rb +1 -0
  27. data/lib/jwt/jwa/compat.rb +29 -0
  28. data/lib/jwt/jwa/ecdsa.rb +93 -0
  29. data/lib/jwt/jwa/eddsa.rb +34 -0
  30. data/lib/jwt/jwa/hmac.rb +83 -0
  31. data/lib/jwt/jwa/hmac_rbnacl.rb +49 -0
  32. data/lib/jwt/jwa/hmac_rbnacl_fixed.rb +46 -0
  33. data/lib/jwt/jwa/none.rb +23 -0
  34. data/lib/jwt/jwa/ps.rb +36 -0
  35. data/lib/jwt/jwa/rsa.rb +36 -0
  36. data/lib/jwt/jwa/signing_algorithm.rb +60 -0
  37. data/lib/jwt/jwa/unsupported.rb +19 -0
  38. data/lib/jwt/jwa/wrapper.rb +43 -0
  39. data/lib/jwt/jwa.rb +50 -0
  40. data/lib/jwt/jwk/ec.rb +162 -65
  41. data/lib/jwt/jwk/hmac.rb +69 -24
  42. data/lib/jwt/jwk/key_base.rb +45 -7
  43. data/lib/jwt/jwk/key_finder.rb +19 -35
  44. data/lib/jwt/jwk/kid_as_key_digest.rb +15 -0
  45. data/lib/jwt/jwk/okp_rbnacl.rb +110 -0
  46. data/lib/jwt/jwk/rsa.rb +141 -54
  47. data/lib/jwt/jwk/set.rb +80 -0
  48. data/lib/jwt/jwk/thumbprint.rb +26 -0
  49. data/lib/jwt/jwk.rb +14 -11
  50. data/lib/jwt/verify.rb +10 -89
  51. data/lib/jwt/version.rb +24 -2
  52. data/lib/jwt/x5c_key_finder.rb +3 -6
  53. data/lib/jwt.rb +12 -4
  54. data/ruby-jwt.gemspec +11 -4
  55. metadata +59 -31
  56. data/.codeclimate.yml +0 -8
  57. data/.github/workflows/coverage.yml +0 -27
  58. data/.github/workflows/test.yml +0 -66
  59. data/.gitignore +0 -13
  60. data/.reek.yml +0 -22
  61. data/.rspec +0 -2
  62. data/.rubocop.yml +0 -67
  63. data/.sourcelevel.yml +0 -17
  64. data/Appraisals +0 -13
  65. data/Gemfile +0 -7
  66. data/Rakefile +0 -16
  67. data/lib/jwt/algos/ecdsa.rb +0 -64
  68. data/lib/jwt/algos/eddsa.rb +0 -33
  69. data/lib/jwt/algos/hmac.rb +0 -36
  70. data/lib/jwt/algos/none.rb +0 -17
  71. data/lib/jwt/algos/ps.rb +0 -43
  72. data/lib/jwt/algos/rsa.rb +0 -22
  73. data/lib/jwt/algos/unsupported.rb +0 -19
  74. data/lib/jwt/algos.rb +0 -44
  75. data/lib/jwt/default_options.rb +0 -18
  76. data/lib/jwt/security_utils.rb +0 -59
  77. data/lib/jwt/signature.rb +0 -35
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 6e7f3474ee58d51ca5646f48ca28bf669b40a4b7676cbe7211597ca6ae69f672
4
- data.tar.gz: 570e6930c9094afea40ea8e8a6a7c9b3293890b121893f5148914b0a8e7d11f8
3
+ metadata.gz: ce035519b0df530866af63d7dd6cb267490700e9458fc9c32fb0bb15be446f6e
4
+ data.tar.gz: 94fd6a38f0e3c91407b04aa254d568e113877e7dcdcb4b923c28b6a320587119
5
5
  SHA512:
6
- metadata.gz: 3249529ec6bacc8e655e2830949af61c10e235a569f9dc67d3880335d5939b8afc56c180145d3e02dd09744288d50c31547338e105cf55ae4e0fbe237eb2a0e8
7
- data.tar.gz: dd415314a7bd048d8b2b5b630d5b7011128932bf207dc785ac6154748aff68836a1c39e766dc176e225c643fc406fe9fdc5c510b36dc939e36722e327d8fe92f
6
+ metadata.gz: aaf541769af85436646e45a61e0f3a57d75a88e640f4a811eff35d8be61285dc77b1741e79147cf435fed5b51519863fc027722d43805c3457a159d8e235f568
7
+ data.tar.gz: f548c7bcfac5c31520ba0a1cc1b5dd546cf600277667109e7c33fde167138a3a29a930cf127cc51a7546e5b4c14e5e093a8279949107cd0d0062d016067a1723
data/CHANGELOG.md CHANGED
@@ -1,31 +1,194 @@
1
1
  # Changelog
2
- ## [v2.4.1](https://github.com/jwt/ruby-jwt/tree/v2.4.1) (2022-06-07)
2
+
3
+ ## Upcoming breaking changes
4
+
5
+ Notable changes in the upcoming **version 3.0**:
6
+
7
+ - The indirect dependency to [rbnacl](https://github.com/RubyCrypto/rbnacl) will be removed:
8
+ - Support for the nonstandard SHA512256 algorithm will be removed.
9
+ - Support for Ed25519 will be moved to a [separate gem](https://github.com/anakinj/jwt-eddsa) for better dependency handling.
10
+
11
+ - Base64 decoding will no longer fallback on the looser RFC 2045.
12
+
13
+ - Claim verification has been [split into separate classes](https://github.com/jwt/ruby-jwt/pull/605) and has [a new api](https://github.com/jwt/ruby-jwt/pull/626) and lead to the following deprecations:
14
+ - The `::JWT::ClaimsValidator` class will be removed in favor of the functionality provided by `::JWT::Claims`.
15
+ - The `::JWT::Claims::verify!` method will be removed in favor of `::JWT::Claims::verify_payload!`.
16
+ - The `::JWT::JWA.create` method will be removed. No recommended alternatives.
17
+ - The `::JWT::Verify` class will be removed in favor of the functionality provided by `::JWT::Claims`.
18
+ - Calling `::JWT::Claims::Numeric.new` with a payload will be removed in favor of `::JWT::Claims::verify_payload!(payload, :numeric)`.
19
+ - Calling `::JWT::Claims::Numeric.verify!` with a payload will be removed in favor of `::JWT::Claims::verify_payload!(payload, :numeric)`.
20
+
21
+ - The internal algorithms were [restructured](https://github.com/jwt/ruby-jwt/pull/607) to support extensions from separate libraries. The changes lead to a few deprecations and new requirements:
22
+ - The `sign` and `verify` static methods on all the algorithms (`::JWT::JWA`) will be removed.
23
+ - Custom algorithms are expected to include the `JWT::JWA::SigningAlgorithm` module.
24
+
25
+ ## [v2.9.3](https://github.com/jwt/ruby-jwt/tree/v2.9.3) (2024-10-03)
26
+
27
+ [Full Changelog](https://github.com/jwt/ruby-jwt/compare/v2.9.2...v2.9.3)
28
+
29
+ **Fixes and enhancements:**
30
+
31
+ - Return truthy value for `::JWT::ClaimsValidator#validate!` and `::JWT::Verify.verify_claims` [#628](https://github.com/jwt/ruby-jwt/pull/628) ([@anakinj](https://github.com/anakinj))
32
+
33
+ ## [v2.9.2](https://github.com/jwt/ruby-jwt/tree/v2.9.2) (2024-10-03)
34
+
35
+ [Full Changelog](https://github.com/jwt/ruby-jwt/compare/v2.9.1...v2.9.2)
36
+
37
+ **Features:**
38
+
39
+ - Standalone claim verification interface [#626](https://github.com/jwt/ruby-jwt/pull/626) ([@anakinj](https://github.com/anakinj))
40
+
41
+ **Fixes and enhancements:**
42
+
43
+ - Updated README to correctly document `OpenSSL::HMAC` documentation [#617](https://github.com/jwt/ruby-jwt/pull/617) ([@aedryan](https://github.com/aedryan))
44
+ - Verify JWT header format [#622](https://github.com/jwt/ruby-jwt/pull/622) ([@304](https://github.com/304))
45
+ - Bring back `::JWT::ClaimsValidator`, `::JWT::Verify` and a few other removed interfaces for preserved backwards compatibility [#624](https://github.com/jwt/ruby-jwt/pull/624) ([@anakinj](https://github.com/anakinj))
46
+
47
+ ## [v2.9.1](https://github.com/jwt/ruby-jwt/tree/v2.9.1) (2024-09-23)
48
+
49
+ [Full Changelog](https://github.com/jwt/ruby-jwt/compare/v2.9.0...v2.9.1)
50
+
51
+ **Fixes and enhancements:**
52
+
53
+ - Fix regression in `iss` and `aud` claim validation [#619](https://github.com/jwt/ruby-jwt/pull/619) ([@anakinj](https://github.com/anakinj))
54
+
55
+ ## [v2.9.0](https://github.com/jwt/ruby-jwt/tree/v2.9.0) (2024-09-15)
56
+
57
+ [Full Changelog](https://github.com/jwt/ruby-jwt/compare/v2.8.2...v2.9.0)
58
+
59
+ **Features:**
60
+
61
+ - Build and push gem using a GH action [#612](https://github.com/jwt/ruby-jwt/pull/612) ([@anakinj](https://github.com/anakinj))
62
+
63
+ **Fixes and enhancements:**
64
+
65
+ - Refactor claim validators into their own classes [#605](https://github.com/jwt/ruby-jwt/pull/605) ([@anakinj](https://github.com/anakinj), [@MatteoPierro](https://github.com/MatteoPierro))
66
+ - Allow extending available algorithms [#607](https://github.com/jwt/ruby-jwt/pull/607) ([@anakinj](https://github.com/anakinj))
67
+ - Do not include the EdDSA algorithm if rbnacl not available [#613](https://github.com/jwt/ruby-jwt/pull/613) ([@anakinj](https://github.com/anakinj))
68
+
69
+ ## [v2.8.2](https://github.com/jwt/ruby-jwt/tree/v2.8.2) (2024-06-18)
70
+
71
+ [Full Changelog](https://github.com/jwt/ruby-jwt/compare/v2.8.1...v2.8.2)
72
+
73
+ **Fixes and enhancements:**
74
+
75
+ - Print deprecation warnings only on when token decoding succeeds [#600](https://github.com/jwt/ruby-jwt/pull/600) ([@anakinj](https://github.com/anakinj))
76
+ - Unify code style [#602](https://github.com/jwt/ruby-jwt/pull/602) ([@anakinj](https://github.com/anakinj))
77
+
78
+ ## [v2.8.1](https://github.com/jwt/ruby-jwt/tree/v2.8.1) (2024-02-29)
79
+
80
+ [Full Changelog](https://github.com/jwt/ruby-jwt/compare/v2.8.0...v2.8.1)
81
+
82
+ **Features:**
83
+
84
+ - Configurable base64 decode behaviour [#589](https://github.com/jwt/ruby-jwt/pull/589) ([@anakinj](https://github.com/anakinj))
85
+
86
+ **Fixes and enhancements:**
87
+
88
+ - Output deprecation warnings once [#589](https://github.com/jwt/ruby-jwt/pull/589) ([@anakinj](https://github.com/anakinj))
89
+
90
+ ## [v2.8.0](https://github.com/jwt/ruby-jwt/tree/v2.8.0) (2024-02-17)
91
+
92
+ [Full Changelog](https://github.com/jwt/ruby-jwt/compare/v2.7.1...v2.8.0)
93
+
94
+ **Features:**
95
+
96
+ - Updated rubocop to 1.56 [#573](https://github.com/jwt/ruby-jwt/pull/573) ([@anakinj](https://github.com/anakinj))
97
+ - Run CI on Ruby 3.3 [#577](https://github.com/jwt/ruby-jwt/pull/577) ([@anakinj](https://github.com/anakinj))
98
+ - Deprecation warning added for the HMAC algorithm HS512256 (HMAC-SHA-512 truncated to 256-bits) [#575](https://github.com/jwt/ruby-jwt/pull/575) ([@anakinj](https://github.com/anakinj))
99
+ - Stop using RbNaCl for standard HMAC algorithms [#575](https://github.com/jwt/ruby-jwt/pull/575) ([@anakinj](https://github.com/anakinj))
100
+
101
+ **Fixes and enhancements:**
102
+
103
+ - Fix signature has expired error if payload is a string [#555](https://github.com/jwt/ruby-jwt/pull/555) ([@GobinathAL](https://github.com/GobinathAL))
104
+ - Fix key base equality and spaceship operators [#569](https://github.com/jwt/ruby-jwt/pull/569) ([@magneland](https://github.com/magneland))
105
+ - Remove explicit base64 require from x5c_key_finder [#580](https://github.com/jwt/ruby-jwt/pull/580) ([@anakinj](https://github.com/anakinj))
106
+ - Performance improvements and cleanup of tests [#581](https://github.com/jwt/ruby-jwt/pull/581) ([@anakinj](https://github.com/anakinj))
107
+ - Repair EC x/y coordinates when importing JWK [#585](https://github.com/jwt/ruby-jwt/pull/585) ([@julik](https://github.com/julik))
108
+ - Explicit dependency to the base64 gem [#582](https://github.com/jwt/ruby-jwt/pull/582) ([@anakinj](https://github.com/anakinj))
109
+ - Deprecation warning for decoding content not compliant with RFC 4648 [#582](https://github.com/jwt/ruby-jwt/pull/582) ([@anakinj](https://github.com/anakinj))
110
+ - Algorithms moved under the `::JWT::JWA` module ([@anakinj](https://github.com/anakinj))
111
+
112
+ ## [v2.7.1](https://github.com/jwt/ruby-jwt/tree/v2.8.0) (2023-06-09)
113
+
114
+ [Full Changelog](https://github.com/jwt/ruby-jwt/compare/v2.7.0...v2.7.1)
115
+
116
+ **Fixes and enhancements:**
117
+
118
+ - Handle invalid algorithm when decoding JWT [#559](https://github.com/jwt/ruby-jwt/pull/559) ([@nataliastanko](https://github.com/nataliastanko))
119
+ - Do not raise error when verifying bad HMAC signature [#563](https://github.com/jwt/ruby-jwt/pull/563) ([@hieuk09](https://github.com/hieuk09))
120
+
121
+ ## [v2.7.0](https://github.com/jwt/ruby-jwt/tree/v2.7.0) (2023-02-01)
122
+
123
+ [Full Changelog](https://github.com/jwt/ruby-jwt/compare/v2.6.0...v2.7.0)
124
+
125
+ **Features:**
126
+
127
+ - Support OKP (Ed25519) keys for JWKs [#540](https://github.com/jwt/ruby-jwt/pull/540) ([@anakinj](https://github.com/anakinj))
128
+ - JWK Sets can now be used for tokens with nil kid [#543](https://github.com/jwt/ruby-jwt/pull/543) ([@bellebaum](https://github.com/bellebaum))
3
129
 
4
130
  **Fixes and enhancements:**
5
- - Raise JWT::DecodeError on invalid signature [\#484](https://github.com/jwt/ruby-jwt/pull/484) ([@freakyfelt!](https://github.com/freakyfelt!)).
131
+
132
+ - Fix issue with multiple keys returned by keyfinder and multiple allowed algorithms [#545](https://github.com/jwt/ruby-jwt/pull/545) ([@mpospelov](https://github.com/mpospelov))
133
+ - Non-string `kid` header values are now rejected [#543](https://github.com/jwt/ruby-jwt/pull/543) ([@bellebaum](https://github.com/bellebaum))
134
+
135
+ ## [v2.6.0](https://github.com/jwt/ruby-jwt/tree/v2.6.0) (2022-12-22)
136
+
137
+ [Full Changelog](https://github.com/jwt/ruby-jwt/compare/v2.5.0...v2.6.0)
138
+
139
+ **Features:**
140
+
141
+ - Support custom algorithms by passing algorithm objects [#512](https://github.com/jwt/ruby-jwt/pull/512) ([@anakinj](https://github.com/anakinj))
142
+ - Support descriptive (not key related) JWK parameters [#520](https://github.com/jwt/ruby-jwt/pull/520) ([@bellebaum](https://github.com/bellebaum))
143
+ - Support for JSON Web Key Sets [#525](https://github.com/jwt/ruby-jwt/pull/525) ([@bellebaum](https://github.com/bellebaum))
144
+ - Support HMAC keys over 32 chars when using RbNaCl [#521](https://github.com/jwt/ruby-jwt/pull/521) ([@anakinj](https://github.com/anakinj))
145
+
146
+ **Fixes and enhancements:**
147
+
148
+ - Raise descriptive error on empty hmac_secret and OpenSSL 3.0/openssl gem <3.0.1 [#530](https://github.com/jwt/ruby-jwt/pull/530) ([@jonmchan](https://github.com/jonmchan))
149
+
150
+ ## [v2.5.0](https://github.com/jwt/ruby-jwt/tree/v2.5.0) (2022-08-25)
151
+
152
+ [Full Changelog](https://github.com/jwt/ruby-jwt/compare/v2.4.1...v2.5.0)
153
+
154
+ **Features:**
155
+
156
+ - Support JWK thumbprints as key ids [#481](https://github.com/jwt/ruby-jwt/pull/481) ([@anakinj](https://github.com/anakinj))
157
+ - Support OpenSSL >= 3.0 [#496](https://github.com/jwt/ruby-jwt/pull/496) ([@anakinj](https://github.com/anakinj))
158
+
159
+ **Fixes and enhancements:**
160
+ - Bring back the old Base64 (RFC2045) deocode mechanisms [#488](https://github.com/jwt/ruby-jwt/pull/488) ([@anakinj](https://github.com/anakinj))
161
+ - Rescue RbNaCl exception for EdDSA wrong key [#491](https://github.com/jwt/ruby-jwt/pull/491) ([@n-studio](https://github.com/n-studio))
162
+ - New parameter name for cases when kid is not found using JWK key loader proc [#501](https://github.com/jwt/ruby-jwt/pull/501) ([@anakinj](https://github.com/anakinj))
163
+ - Fix NoMethodError when a 2 segment token is missing 'alg' header [#502](https://github.com/jwt/ruby-jwt/pull/502) ([@cmrd-senya](https://github.com/cmrd-senya))
164
+
165
+ ## [v2.4.1](https://github.com/jwt/ruby-jwt/tree/v2.4.1) (2022-06-07)
6
166
 
7
167
  [Full Changelog](https://github.com/jwt/ruby-jwt/compare/v2.4.0...v2.4.1)
8
168
 
169
+ **Fixes and enhancements:**
170
+ - Raise JWT::DecodeError on invalid signature [\#484](https://github.com/jwt/ruby-jwt/pull/484) ([@freakyfelt!](https://github.com/freakyfelt!))
171
+
9
172
  ## [v2.4.0](https://github.com/jwt/ruby-jwt/tree/v2.4.0) (2022-06-06)
10
173
 
11
174
  [Full Changelog](https://github.com/jwt/ruby-jwt/compare/v2.3.0...v2.4.0)
12
175
 
13
176
  **Features:**
14
177
 
15
- - Dropped support for Ruby 2.5 and older [#453](https://github.com/jwt/ruby-jwt/pull/453) - [@anakinj](https://github.com/anakinj).
16
- - Use Ruby built-in url-safe base64 methods [#454](https://github.com/jwt/ruby-jwt/pull/454) - [@bdewater](https://github.com/bdewater).
17
- - Updated rubocop to 1.23.0 [#457](https://github.com/jwt/ruby-jwt/pull/457) - [@anakinj](https://github.com/anakinj).
18
- - Add x5c header key finder [#338](https://github.com/jwt/ruby-jwt/pull/338) - [@bdewater](https://github.com/bdewater).
19
- - Author driven changelog process [#463](https://github.com/jwt/ruby-jwt/pull/463) - [@anakinj](https://github.com/anakinj).
20
- - Allow regular expressions and procs to verify issuer [\#437](https://github.com/jwt/ruby-jwt/pull/437) ([rewritten](https://github.com/rewritten)).
21
- - Add Support to be able to verify from multiple keys [\#425](https://github.com/jwt/ruby-jwt/pull/425) ([ritikesh](https://github.com/ritikesh)).
178
+ - Dropped support for Ruby 2.5 and older [#453](https://github.com/jwt/ruby-jwt/pull/453) - ([@anakinj](https://github.com/anakinj))
179
+ - Use Ruby built-in url-safe base64 methods [#454](https://github.com/jwt/ruby-jwt/pull/454) - ([@bdewater](https://github.com/bdewater))
180
+ - Updated rubocop to 1.23.0 [#457](https://github.com/jwt/ruby-jwt/pull/457) - ([@anakinj](https://github.com/anakinj))
181
+ - Add x5c header key finder [#338](https://github.com/jwt/ruby-jwt/pull/338) - ([@bdewater](https://github.com/bdewater))
182
+ - Author driven changelog process [#463](https://github.com/jwt/ruby-jwt/pull/463) - ([@anakinj](https://github.com/anakinj))
183
+ - Allow regular expressions and procs to verify issuer [\#437](https://github.com/jwt/ruby-jwt/pull/437) ([rewritten](https://github.com/rewritten))
184
+ - Add Support to be able to verify from multiple keys [\#425](https://github.com/jwt/ruby-jwt/pull/425) ([ritikesh](https://github.com/ritikesh))
22
185
 
23
186
  **Fixes and enhancements:**
24
- - Readme: Typo fix re MissingRequiredClaim [\#451](https://github.com/jwt/ruby-jwt/pull/451) ([antonmorant](https://github.com/antonmorant)).
25
- - Fix RuboCop TODOs [\#476](https://github.com/jwt/ruby-jwt/pull/476) ([typhoon2099](https://github.com/typhoon2099)).
26
- - Make specific algorithms in README linkable [\#472](https://github.com/jwt/ruby-jwt/pull/472) ([milieu](https://github.com/milieu)).
27
- - Update note about supported JWK types [\#475](https://github.com/jwt/ruby-jwt/pull/475) ([dpashkevich](https://github.com/dpashkevich)).
28
- - Create CODE\_OF\_CONDUCT.md [\#449](https://github.com/jwt/ruby-jwt/pull/449) ([loic5](https://github.com/loic5)).
187
+ - Readme: Typo fix re MissingRequiredClaim [\#451](https://github.com/jwt/ruby-jwt/pull/451) ([antonmorant](https://github.com/antonmorant))
188
+ - Fix RuboCop TODOs [\#476](https://github.com/jwt/ruby-jwt/pull/476) ([typhoon2099](https://github.com/typhoon2099))
189
+ - Make specific algorithms in README linkable [\#472](https://github.com/jwt/ruby-jwt/pull/472) ([milieu](https://github.com/milieu))
190
+ - Update note about supported JWK types [\#475](https://github.com/jwt/ruby-jwt/pull/475) ([dpashkevich](https://github.com/dpashkevich))
191
+ - Create CODE\_OF\_CONDUCT.md [\#449](https://github.com/jwt/ruby-jwt/pull/449) ([loic5](https://github.com/loic5))
29
192
 
30
193
  ## [v2.3.0](https://github.com/jwt/ruby-jwt/tree/v2.3.0) (2021-10-03)
31
194
 
data/CONTRIBUTING.md CHANGED
@@ -12,19 +12,19 @@ git remote add upstream https://github.com/jwt/ruby-jwt
12
12
 
13
13
  ## Create a branch for your implementation
14
14
 
15
- Make sure you have the latest upstream master branch of the project.
15
+ Make sure you have the latest upstream main branch of the project.
16
16
 
17
17
  ```
18
18
  git fetch --all
19
- git checkout master
20
- git rebase upstream/master
21
- git push origin master
19
+ git checkout main
20
+ git rebase upstream/main
21
+ git push origin main
22
22
  git checkout -b fix-a-little-problem
23
23
  ```
24
24
 
25
25
  ## Running the tests and linter
26
26
 
27
- Before you start with your implementation make sure you are able to get a succesful test run with the current revision.
27
+ Before you start with your implementation make sure you are able to get a successful test run with the current revision.
28
28
 
29
29
  The tests are written with rspec and [Appraisal](https://github.com/thoughtbot/appraisal) is used to ensure compatibility with 3rd party dependencies providing cryptographic features.
30
30
 
@@ -78,12 +78,12 @@ A maintainer will review and probably merge you changes when time allows, be pat
78
78
 
79
79
  ## Keeping your branch up-to-date
80
80
 
81
- It's recommended that you keep your branch up-to-date by rebasing to the upstream master.
81
+ It's recommended that you keep your branch up-to-date by rebasing to the upstream main.
82
82
 
83
83
  ```
84
84
  git fetch upstream
85
85
  git checkout fix-a-little-problem
86
- git rebase upstream/master
86
+ git rebase upstream/main
87
87
  git push origin fix-a-little-problem -f
88
88
  ```
89
89
 
data/README.md CHANGED
@@ -1,18 +1,17 @@
1
1
  # JWT
2
2
 
3
3
  [![Gem Version](https://badge.fury.io/rb/jwt.svg)](https://badge.fury.io/rb/jwt)
4
- [![Build Status](https://github.com/jwt/ruby-jwt/workflows/test/badge.svg?branch=master)](https://github.com/jwt/ruby-jwt/actions)
4
+ [![Build Status](https://github.com/jwt/ruby-jwt/workflows/test/badge.svg?branch=main)](https://github.com/jwt/ruby-jwt/actions)
5
5
  [![Code Climate](https://codeclimate.com/github/jwt/ruby-jwt/badges/gpa.svg)](https://codeclimate.com/github/jwt/ruby-jwt)
6
6
  [![Test Coverage](https://codeclimate.com/github/jwt/ruby-jwt/badges/coverage.svg)](https://codeclimate.com/github/jwt/ruby-jwt/coverage)
7
7
  [![Issue Count](https://codeclimate.com/github/jwt/ruby-jwt/badges/issue_count.svg)](https://codeclimate.com/github/jwt/ruby-jwt)
8
- [![SourceLevel](https://app.sourcelevel.io/github/jwt/-/ruby-jwt.svg)](https://app.sourcelevel.io/github/jwt/-/ruby-jwt)
9
8
 
10
9
  A ruby implementation of the [RFC 7519 OAuth JSON Web Token (JWT)](https://tools.ietf.org/html/rfc7519) standard.
11
10
 
12
11
  If you have further questions related to development or usage, join us: [ruby-jwt google group](https://groups.google.com/forum/#!forum/ruby-jwt).
13
12
 
14
13
  ## Announcements
15
- * Ruby 2.4 support is going to be dropped in version 2.4.0
14
+ * Ruby 2.4 support was dropped in version 2.4.0
16
15
  * Ruby 1.9.3 support was dropped at December 31st, 2016.
17
16
  * Version 1.5.3 yanked. See: [#132](https://github.com/jwt/ruby-jwt/issues/132) and [#133](https://github.com/jwt/ruby-jwt/issues/133)
18
17
 
@@ -44,6 +43,23 @@ The JWT spec supports NONE, HMAC, RSASSA, ECDSA and RSASSA-PSS algorithms for cr
44
43
 
45
44
  See: [ JSON Web Algorithms (JWA) 3.1. "alg" (Algorithm) Header Parameter Values for JWS](https://tools.ietf.org/html/rfc7518#section-3.1)
46
45
 
46
+ ### Deprecation warnings
47
+
48
+ Deprecation warnings are logged once (`:once` option) by default to avoid spam in logs. Other options are `:silent` to completely silence warnings and `:warn` to log every time a deprecated path is executed.
49
+
50
+ ```ruby
51
+ JWT.configuration.deprecation_warnings = :warn # default is :once
52
+ ```
53
+
54
+ ### Base64 decoding
55
+
56
+ In the past the gem has been supporting the Base64 decoding specified in [RFC2045](https://www.rfc-editor.org/rfc/rfc2045) allowing newlines and blanks in the base64 encoded payload. In future versions base64 decoding will be stricter and only comply to [RFC4648](https://www.rfc-editor.org/rfc/rfc4648).
57
+
58
+ The stricter base64 decoding when processing tokens can be done via the `strict_base64_decoding` configuration accessor.
59
+ ```ruby
60
+ JWT.configuration.strict_base64_decoding = true # default is false
61
+ ```
62
+
47
63
  ### **NONE**
48
64
 
49
65
  * none - unsigned token
@@ -73,12 +89,11 @@ puts decoded_token
73
89
  ### **HMAC**
74
90
 
75
91
  * HS256 - HMAC using SHA-256 hash algorithm
76
- * HS512256 - HMAC using SHA-512-256 hash algorithm (only available with RbNaCl; see note below)
77
92
  * HS384 - HMAC using SHA-384 hash algorithm
78
93
  * HS512 - HMAC using SHA-512 hash algorithm
79
94
 
80
95
  ```ruby
81
- # The secret must be a string. A JWT::DecodeError will be raised if it isn't provided.
96
+ # The secret must be a string. With OpenSSL 3.0/openssl gem `<3.0.1`, JWT::DecodeError will be raised if it isn't provided.
82
97
  hmac_secret = 'my$ecretK3y'
83
98
 
84
99
  token = JWT.encode payload, hmac_secret, 'HS256'
@@ -96,12 +111,6 @@ decoded_token = JWT.decode token, hmac_secret, true, { algorithm: 'HS256' }
96
111
  puts decoded_token
97
112
  ```
98
113
 
99
- Note: If [RbNaCl](https://github.com/cryptosphere/rbnacl) is loadable, ruby-jwt will use it for HMAC-SHA256, HMAC-SHA512-256, and HMAC-SHA512. RbNaCl enforces a maximum key size of 32 bytes for these algorithms.
100
-
101
- [RbNaCl](https://github.com/cryptosphere/rbnacl) requires
102
- [libsodium](https://github.com/jedisct1/libsodium), it can be installed
103
- on MacOS with `brew install libsodium`.
104
-
105
114
  ### **RSA**
106
115
 
107
116
  * RS256 - RSA using SHA-256 hash algorithm
@@ -135,17 +144,14 @@ puts decoded_token
135
144
  * ES256K - ECDSA using P-256K and SHA-256
136
145
 
137
146
  ```ruby
138
- ecdsa_key = OpenSSL::PKey::EC.new 'prime256v1'
139
- ecdsa_key.generate_key
140
- ecdsa_public = OpenSSL::PKey::EC.new ecdsa_key
141
- ecdsa_public.private_key = nil
147
+ ecdsa_key = OpenSSL::PKey::EC.generate('prime256v1')
142
148
 
143
149
  token = JWT.encode payload, ecdsa_key, 'ES256'
144
150
 
145
151
  # eyJhbGciOiJFUzI1NiJ9.eyJkYXRhIjoidGVzdCJ9.AlLW--kaF7EX1NMX9WJRuIW8NeRJbn2BLXHns7Q5TZr7Hy3lF6MOpMlp7GoxBFRLISQ6KrD0CJOrR8aogEsPeg
146
152
  puts token
147
153
 
148
- decoded_token = JWT.decode token, ecdsa_public, true, { algorithm: 'ES256' }
154
+ decoded_token = JWT.decode token, ecdsa_key, true, { algorithm: 'ES256' }
149
155
 
150
156
  # Array
151
157
  # [
@@ -163,7 +169,7 @@ In order to use this algorithm you need to add the `RbNaCl` gem to you `Gemfile`
163
169
  gem 'rbnacl'
164
170
  ```
165
171
 
166
- For more detailed installation instruction check the official [repository](https://github.com/cryptosphere/rbnacl) on GitHub.
172
+ For more detailed installation instruction check the official [repository](https://github.com/RubyCrypto/rbnacl) on GitHub.
167
173
 
168
174
  * ED25519
169
175
 
@@ -186,7 +192,7 @@ decoded_token = JWT.decode token, public_key, true, { algorithm: 'ED25519' }
186
192
 
187
193
  ### **RSASSA-PSS**
188
194
 
189
- In order to use this algorithm you need to add the `openssl` gem to you `Gemfile` with a version greater or equal to `2.1`.
195
+ In order to use this algorithm you need to add the `openssl` gem to your `Gemfile` with a version greater or equal to `2.1`.
190
196
 
191
197
  ```ruby
192
198
  gem 'openssl', '~> 2.1'
@@ -215,6 +221,37 @@ decoded_token = JWT.decode token, rsa_public, true, { algorithm: 'PS256' }
215
221
  puts decoded_token
216
222
  ```
217
223
 
224
+ ### **Custom algorithms**
225
+
226
+ When encoding or decoding a token, you can pass in a custom object through the `algorithm` option to handle signing or verification. This custom object must include or extend the `JWT::JWA::SigningAlgorithm` module and implement certain methods:
227
+
228
+ - For decoding/verifying: The object must implement the methods `alg` and `verify`.
229
+ - For encoding/signing: The object must implement the methods `alg` and `sign`.
230
+
231
+ For customization options check the details from `JWT::JWA::SigningAlgorithm`.
232
+
233
+
234
+ ```ruby
235
+ module CustomHS512Algorithm
236
+ extend JWT::JWA::SigningAlgorithm
237
+
238
+ def self.alg
239
+ 'HS512'
240
+ end
241
+
242
+ def self.sign(data:, signing_key:)
243
+ OpenSSL::HMAC.digest(OpenSSL::Digest.new('sha512'), signing_key, data)
244
+ end
245
+
246
+ def self.verify(data:, signature:, verification_key:)
247
+ ::OpenSSL.secure_compare(sign(data: data, signing_key: verification_key), signature)
248
+ end
249
+ end
250
+
251
+ token = ::JWT.encode({'pay' => 'load'}, 'secret', CustomHS512Algorithm)
252
+ payload, header = ::JWT.decode(token, 'secret', true, algorithm: CustomHS512Algorithm)
253
+ ```
254
+
218
255
  ## Support for reserved claim names
219
256
  JSON Web Token defines some reserved claim names and defines how they should be
220
257
  used. JWT supports these reserved claim names:
@@ -493,6 +530,24 @@ rescue JWT::InvalidSubError
493
530
  end
494
531
  ```
495
532
 
533
+ ### Standalone claim verification
534
+
535
+ The JWT claim verifications can be used to verify any Hash to include expected keys and values.
536
+
537
+ A few example on verifying the claims for a payload:
538
+ ```ruby
539
+ JWT::Claims.verify_payload!({"exp" => Time.now.to_i + 10}, :numeric, :exp)
540
+ JWT::Claims.valid_payload?({"exp" => Time.now.to_i + 10}, :exp)
541
+ # => true
542
+ JWT::Claims.payload_errors({"exp" => Time.now.to_i - 10}, :exp)
543
+ # => [#<struct JWT::Claims::Error message="Signature has expired">]
544
+ JWT::Claims.verify_payload!({"exp" => Time.now.to_i - 10}, exp: { leeway: 11})
545
+
546
+ JWT::Claims.verify_payload!({"exp" => Time.now.to_i + 10, "sub" => "subject"}, :exp, sub: "subject")
547
+ ```
548
+
549
+
550
+
496
551
  ### Finding a Key
497
552
 
498
553
  To dynamically find the key for verifying the JWT signature, pass a block to the decode block. The block receives headers and the original payload as parameters. It should return with the key to verify the signature that was used to sign the JWT.
@@ -538,7 +593,7 @@ crls = crl_uris.map do |uri|
538
593
  end
539
594
 
540
595
  begin
541
- JWT.decode(token, nil, true, { x5c: { root_certificates: root_certificates, crls: crls })
596
+ JWT.decode(token, nil, true, { x5c: { root_certificates: root_certificates, crls: crls } })
542
597
  rescue JWT::DecodeError
543
598
  # Handle error, e.g. x5c header certificate revoked or expired
544
599
  end
@@ -546,22 +601,62 @@ end
546
601
 
547
602
  ### JSON Web Key (JWK)
548
603
 
549
- JWK is a JSON structure representing a cryptographic key. Currently only supports RSA, EC and HMAC keys.
604
+ JWK is a JSON structure representing a cryptographic key. This gem currently supports RSA, EC, OKP and HMAC keys. OKP support requires [RbNaCl](https://github.com/RubyCrypto/rbnacl) and currently only supports the Ed25519 curve.
605
+
606
+ To encode a JWT using your JWK:
607
+
608
+ ```ruby
609
+ optional_parameters = { kid: 'my-kid', use: 'sig', alg: 'RS512' }
610
+ jwk = JWT::JWK.new(OpenSSL::PKey::RSA.new(2048), optional_parameters)
611
+
612
+ # Encoding
613
+ payload = { data: 'data' }
614
+ token = JWT.encode(payload, jwk.signing_key, jwk[:alg], kid: jwk[:kid])
615
+
616
+ # JSON Web Key Set for advertising your signing keys
617
+ jwks_hash = JWT::JWK::Set.new(jwk).export
618
+ ```
619
+
620
+ To decode a JWT using a trusted entity's JSON Web Key Set (JWKS):
550
621
 
551
622
  ```ruby
552
- jwk = JWT::JWK.new(OpenSSL::PKey::RSA.new(2048), "optional-kid")
553
- payload, headers = { data: 'data' }, { kid: jwk.kid }
623
+ jwks = JWT::JWK::Set.new(jwks_hash)
624
+ jwks.filter! {|key| key[:use] == 'sig' } # Signing keys only!
625
+ algorithms = jwks.map { |key| key[:alg] }.compact.uniq
626
+ JWT.decode(token, nil, true, algorithms: algorithms, jwks: jwks)
627
+ ```
628
+
629
+
630
+ The `jwks` option can also be given as a lambda that evaluates every time a kid is resolved.
631
+ This can be used to implement caching of remotely fetched JWK Sets.
554
632
 
555
- token = JWT.encode(payload, jwk.keypair, 'RS512', headers)
633
+ If the requested `kid` is not found from the given set the loader will be called a second time with the `kid_not_found` option set to `true`.
634
+ The application can choose to implement some kind of JWK cache invalidation or other mechanism to handle such cases.
556
635
 
557
- # The jwk loader would fetch the set of JWKs from a trusted source
558
- jwk_loader = ->(options) do
559
- @cached_keys = nil if options[:invalidate] # need to reload the keys
560
- @cached_keys ||= { keys: [jwk.export] }
636
+ Tokens without a specified `kid` are rejected by default.
637
+ This behaviour may be overwritten by setting the `allow_nil_kid` option for `decode` to `true`.
638
+
639
+ ```ruby
640
+ jwks_loader = ->(options) do
641
+ # The jwk loader would fetch the set of JWKs from a trusted source.
642
+ # To avoid malicious requests triggering cache invalidations there needs to be
643
+ # some kind of grace time or other logic for determining the validity of the invalidation.
644
+ # This example only allows cache invalidations every 5 minutes.
645
+ if options[:kid_not_found] && @cache_last_update < Time.now.to_i - 300
646
+ logger.info("Invalidating JWK cache. #{options[:kid]} not found from previous cache")
647
+ @cached_keys = nil
648
+ end
649
+ @cached_keys ||= begin
650
+ @cache_last_update = Time.now.to_i
651
+ # Replace with your own JWKS fetching routine
652
+ jwks = JWT::JWK::Set.new(jwks_hash)
653
+ jwks.select! { |key| key[:use] == 'sig' } # Signing Keys only
654
+ jwks
655
+ end
561
656
  end
562
657
 
563
658
  begin
564
- JWT.decode(token, nil, true, { algorithms: ['RS512'], jwks: jwk_loader})
659
+ JWT.decode(token, nil, true, { algorithms: ['RS512'], jwks: jwks_loader })
565
660
  rescue JWT::JWKError
566
661
  # Handle problems with the provided JWKs
567
662
  rescue JWT::DecodeError
@@ -569,26 +664,74 @@ rescue JWT::DecodeError
569
664
  end
570
665
  ```
571
666
 
572
- or by passing JWK as a simple Hash
667
+ ### Importing and exporting JSON Web Keys
573
668
 
574
- ```
575
- jwks = { keys: [{ ... }] } # keys accepts both of string and symbol
576
- JWT.decode(token, nil, true, { algorithms: ['RS512'], jwks: jwks})
669
+ The ::JWT::JWK class can be used to import both JSON Web Keys and OpenSSL keys
670
+ and export to either format with and without the private key included.
671
+
672
+ To include the private key in the export pass the `include_private` parameter to the export method.
673
+
674
+ ```ruby
675
+ # Import a JWK Hash (showing an HMAC example)
676
+ jwk = JWT::JWK.new({ kty: 'oct', k: 'my-secret', kid: 'my-kid' })
677
+
678
+ # Import an OpenSSL key
679
+ # You can optionally add descriptive parameters to the JWK
680
+ desc_params = { kid: 'my-kid', use: 'sig' }
681
+ jwk = JWT::JWK.new(OpenSSL::PKey::RSA.new(2048), desc_params)
682
+
683
+ # Export as JWK Hash (public key only by default)
684
+ jwk_hash = jwk.export
685
+ jwk_hash_with_private_key = jwk.export(include_private: true)
686
+
687
+ # Export as OpenSSL key
688
+ public_key = jwk.verify_key
689
+ private_key = jwk.signing_key if jwk.private?
690
+
691
+ # You can also import and export entire JSON Web Key Sets
692
+ jwks_hash = { keys: [{ kty: 'oct', k: 'my-secret', kid: 'my-kid' }] }
693
+ jwks = JWT::JWK::Set.new(jwks_hash)
694
+ jwks_hash = jwks.export
577
695
  ```
578
696
 
579
- ### Importing and exporting JSON Web Keys
697
+ ### Key ID (kid) and JWKs
580
698
 
581
- The ::JWT::JWK class can be used to import and export both the public key (default behaviour) and the private key. To include the private key in the export pass the `include_private` parameter to the export method.
699
+ The key id (kid) generation in the gem is a custom algorithm and not based on any standards.
700
+ To use a standardized JWK thumbprint (RFC 7638) as the kid for JWKs a generator type can be specified in the global configuration
701
+ or can be given to the JWK instance on initialization.
582
702
 
583
703
  ```ruby
584
- jwk = JWT::JWK.new(OpenSSL::PKey::RSA.new(2048))
704
+ JWT.configuration.jwk.kid_generator_type = :rfc7638_thumbprint
705
+ # OR
706
+ JWT.configuration.jwk.kid_generator = ::JWT::JWK::Thumbprint
707
+ # OR
708
+ jwk = JWT::JWK.new(OpenSSL::PKey::RSA.new(2048), nil, kid_generator: ::JWT::JWK::Thumbprint)
585
709
 
586
710
  jwk_hash = jwk.export
587
- jwk_hash_with_private_key = jwk.export(include_private: true)
711
+
712
+ thumbprint_as_the_kid = jwk_hash[:kid]
588
713
  ```
589
714
 
590
- ## How to contribute
715
+ # Development and testing
591
716
 
717
+ The tests are written with rspec. [Appraisal](https://github.com/thoughtbot/appraisal) is used to ensure compatibility with 3rd party dependencies providing cryptographic features.
718
+
719
+ ```bash
720
+ bundle install
721
+ bundle exec appraisal rake test
722
+ ```
723
+
724
+ # Releasing
725
+
726
+ To cut a new release adjust the [version.rb](lib/jwt/version.rb) and [CHANGELOG](CHANGELOG.md) with desired version numbers and dates and commit the changes. Tag the release with the version number using the following command:
727
+
728
+ ```bash
729
+ rake release:source_control_push
730
+ ```
731
+
732
+ This will tag a new version an trigger a [GitHub action](.github/workflows/push_gem.yml) that eventually will push the gem to rubygems.org.
733
+
734
+ ## How to contribute
592
735
  See [CONTRIBUTING](CONTRIBUTING.md).
593
736
 
594
737
  ## Contributors
data/lib/jwt/base64.rb ADDED
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'base64'
4
+
5
+ module JWT
6
+ # Base64 encoding and decoding
7
+ class Base64
8
+ class << self
9
+ # Encode a string with URL-safe Base64 complying with RFC 4648 (not padded).
10
+ def url_encode(str)
11
+ ::Base64.urlsafe_encode64(str, padding: false)
12
+ end
13
+
14
+ # Decode a string with URL-safe Base64 complying with RFC 4648.
15
+ # Deprecated support for RFC 2045 remains for now. ("All line breaks or other characters not found in Table 1 must be ignored by decoding software")
16
+ def url_decode(str)
17
+ ::Base64.urlsafe_decode64(str)
18
+ rescue ArgumentError => e
19
+ raise unless e.message == 'invalid base64'
20
+ raise Base64DecodeError, 'Invalid base64 encoding' if JWT.configuration.strict_base64_decoding
21
+
22
+ loose_urlsafe_decode64(str).tap do
23
+ Deprecations.warning('Invalid base64 input detected, could be because of invalid padding, trailing whitespaces or newline chars. Graceful handling of invalid input will be dropped in the next major version of ruby-jwt', only_if_valid: true)
24
+ end
25
+ end
26
+
27
+ def loose_urlsafe_decode64(str)
28
+ str += '=' * (4 - str.length.modulo(4))
29
+ ::Base64.decode64(str.tr('-_', '+/'))
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ module JWT
4
+ module Claims
5
+ class Audience
6
+ def initialize(expected_audience:)
7
+ @expected_audience = expected_audience
8
+ end
9
+
10
+ def verify!(context:, **_args)
11
+ aud = context.payload['aud']
12
+ raise JWT::InvalidAudError, "Invalid audience. Expected #{expected_audience}, received #{aud || '<none>'}" if ([*aud] & [*expected_audience]).empty?
13
+ end
14
+
15
+ private
16
+
17
+ attr_reader :expected_audience
18
+ end
19
+ end
20
+ end