jwt 1.5.6 → 2.2.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (58) hide show
  1. checksums.yaml +5 -5
  2. data/.ebert.yml +18 -0
  3. data/.gitignore +1 -1
  4. data/.rubocop.yml +96 -0
  5. data/.travis.yml +26 -10
  6. data/AUTHORS +84 -0
  7. data/Appraisals +18 -0
  8. data/CHANGELOG.md +296 -10
  9. data/Gemfile +0 -1
  10. data/README.md +182 -64
  11. data/lib/jwt.rb +14 -176
  12. data/lib/jwt/algos/ecdsa.rb +35 -0
  13. data/lib/jwt/algos/eddsa.rb +23 -0
  14. data/lib/jwt/algos/hmac.rb +34 -0
  15. data/lib/jwt/algos/ps.rb +43 -0
  16. data/lib/jwt/algos/rsa.rb +19 -0
  17. data/lib/jwt/algos/unsupported.rb +16 -0
  18. data/lib/jwt/base64.rb +19 -0
  19. data/lib/jwt/claims_validator.rb +33 -0
  20. data/lib/jwt/decode.rb +81 -31
  21. data/lib/jwt/default_options.rb +15 -0
  22. data/lib/jwt/encode.rb +68 -0
  23. data/lib/jwt/error.rb +6 -0
  24. data/lib/jwt/json.rb +10 -9
  25. data/lib/jwt/jwk.rb +31 -0
  26. data/lib/jwt/jwk/key_finder.rb +57 -0
  27. data/lib/jwt/jwk/rsa.rb +54 -0
  28. data/lib/jwt/security_utils.rb +57 -0
  29. data/lib/jwt/signature.rb +54 -0
  30. data/lib/jwt/verify.rb +45 -53
  31. data/lib/jwt/version.rb +3 -3
  32. data/ruby-jwt.gemspec +11 -7
  33. metadata +76 -67
  34. data/Manifest +0 -8
  35. data/spec/fixtures/certs/ec256-private.pem +0 -8
  36. data/spec/fixtures/certs/ec256-public.pem +0 -4
  37. data/spec/fixtures/certs/ec256-wrong-private.pem +0 -8
  38. data/spec/fixtures/certs/ec256-wrong-public.pem +0 -4
  39. data/spec/fixtures/certs/ec384-private.pem +0 -9
  40. data/spec/fixtures/certs/ec384-public.pem +0 -5
  41. data/spec/fixtures/certs/ec384-wrong-private.pem +0 -9
  42. data/spec/fixtures/certs/ec384-wrong-public.pem +0 -5
  43. data/spec/fixtures/certs/ec512-private.pem +0 -10
  44. data/spec/fixtures/certs/ec512-public.pem +0 -6
  45. data/spec/fixtures/certs/ec512-wrong-private.pem +0 -10
  46. data/spec/fixtures/certs/ec512-wrong-public.pem +0 -6
  47. data/spec/fixtures/certs/rsa-1024-private.pem +0 -15
  48. data/spec/fixtures/certs/rsa-1024-public.pem +0 -6
  49. data/spec/fixtures/certs/rsa-2048-private.pem +0 -27
  50. data/spec/fixtures/certs/rsa-2048-public.pem +0 -9
  51. data/spec/fixtures/certs/rsa-2048-wrong-private.pem +0 -27
  52. data/spec/fixtures/certs/rsa-2048-wrong-public.pem +0 -9
  53. data/spec/fixtures/certs/rsa-4096-private.pem +0 -51
  54. data/spec/fixtures/certs/rsa-4096-public.pem +0 -14
  55. data/spec/integration/readme_examples_spec.rb +0 -190
  56. data/spec/jwt/verify_spec.rb +0 -197
  57. data/spec/jwt_spec.rb +0 -240
  58. data/spec/spec_helper.rb +0 -31
@@ -1,240 +0,0 @@
1
- require 'spec_helper'
2
- require 'jwt'
3
- require 'jwt/decode'
4
-
5
- describe JWT do
6
- let(:payload) { { 'user_id' => 'some@user.tld' } }
7
-
8
- let :data do
9
- {
10
- :secret => 'My$ecretK3y',
11
- :rsa_private => OpenSSL::PKey.read(File.read(File.join(CERT_PATH, 'rsa-2048-private.pem'))),
12
- :rsa_public => OpenSSL::PKey.read(File.read(File.join(CERT_PATH, 'rsa-2048-public.pem'))),
13
- :wrong_rsa_private => OpenSSL::PKey.read(File.read(File.join(CERT_PATH, 'rsa-2048-wrong-public.pem'))),
14
- :wrong_rsa_public => OpenSSL::PKey.read(File.read(File.join(CERT_PATH, 'rsa-2048-wrong-public.pem'))),
15
- 'ES256_private' => OpenSSL::PKey.read(File.read(File.join(CERT_PATH, 'ec256-private.pem'))),
16
- 'ES256_public' => OpenSSL::PKey.read(File.read(File.join(CERT_PATH, 'ec256-public.pem'))),
17
- 'ES384_private' => OpenSSL::PKey.read(File.read(File.join(CERT_PATH, 'ec384-private.pem'))),
18
- 'ES384_public' => OpenSSL::PKey.read(File.read(File.join(CERT_PATH, 'ec384-public.pem'))),
19
- 'ES512_private' => OpenSSL::PKey.read(File.read(File.join(CERT_PATH, 'ec512-private.pem'))),
20
- 'ES512_public' => OpenSSL::PKey.read(File.read(File.join(CERT_PATH, 'ec512-public.pem'))),
21
- 'NONE' => 'eyJ0eXAiOiJKV1QiLCJhbGciOiJub25lIn0.eyJ1c2VyX2lkIjoic29tZUB1c2VyLnRsZCJ9.',
22
- 'HS256' => 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoic29tZUB1c2VyLnRsZCJ9.tCGvlClld0lbQ3NZaH8y53n5RSBr3zlS4Oy5bXqvzZQ',
23
- 'HS384' => 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzM4NCJ9.eyJ1c2VyX2lkIjoic29tZUB1c2VyLnRsZCJ9.sj1gc01SawlJSrPZgmveifJ8CzZRYAWjejWm4FRaGaAISESJ9Ncf12fCz2vHrITm',
24
- 'HS512' => 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzUxMiJ9.eyJ1c2VyX2lkIjoic29tZUB1c2VyLnRsZCJ9.isjhsWMZpRQOWw6LKtlY4L6tMDNkLr0qZ3bQe_xRFXWhzVvJlkclTbLVa1J6Dlj2WyZ_I1jEobTaFMDoXPzwWg',
25
- 'RS256' => 'eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJ1c2VyX2lkIjoic29tZUB1c2VyLnRsZCJ9.u82QrhjZTtwve5akvfWS_4LPywbkb1Yp0nUwZJWtTW0ID7dY9rRiQF5KGj2UDLZotqRlUjyNQgE_hB5BBzICDQdCjQHQoYWE5n_D2wV4PMu7Qg3FVKoBFbf8ee6irodu10fgYxpUIZtvbWw52_6k6A9IoSLSzx_lCcxoVGdW90dUuKhBcZkDtY5WNuQg7MiDthupSL1-V4Y1jmT_7o8tLNGFiocyZfGNw4yGpEOGNvD5WePNit0xsnbj6dEquovUvSFKsMaQXp2PVDEkLOiLMcyk0RrHqrHw2eNSCquWTH8PhX5Up-CVmjQM5zF9ibkaiq8NyPtsy-7rgtbyVMqXBQ',
26
- 'RS384' => 'eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzM4NCJ9.eyJ1c2VyX2lkIjoic29tZUB1c2VyLnRsZCJ9.2_jPwOsUWJ-3r6lXMdJGPdhLNJQSSEmY2mrDXCwNJk-2YhMIqKAzJJCbyso_A1hS7BVkXmHt54RCcNJXroZBOgmGavCcYTPMaT6sCvVVvJJ_wn7jzKHNAJfL5nWeynTQIBWmL-m_v9QpZAgPALdeqjPRv4JHePZm23kvrUgQOxef2ldXv1l6IB3zfF72uEbk9T5pKBvgeeeQ46xm_HtkpXqMdqcTHawUXeXhuiWxuWfy9pAvhm8ivxwJhiQ15-sQNBlS9lG1_gQz1xaZ_Ou_n1nhNfGwpK5HeS0AgmqsqyCOvaGHeAuAOPZ_dSC3cFKu2AP7kc6_AKBgwJzh4agkXg',
27
- 'RS512' => 'eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzUxMiJ9.eyJ1c2VyX2lkIjoic29tZUB1c2VyLnRsZCJ9.abwof7BqTvuLkN69OhEuFTP7vjGzfvAvooQdwIRne_a88MsjCq31n4UPvyIlY9_8u69rpU79RbMsrq_UZ6L85zP83EcyYI-HOfFZgYDAL3DJ7biBD99JTzyOsH_2i_E6yCkevjEX6uL_Am_C7jpWyePJQkYzTFni6mW4W1T9UobiVGA1tIZ-XOJDPHHxZkGu6W8lKW0UCsr9Ge2SCSlTs_LDSOa34gqMC5GP89unhLqSMqEMJ_Nm6Rj0rnmk87wBZM-b04LLteWuEU59QDNa4nMTjfXW74U4hX9n5EECDPQdQMecgxlUbFunAfZaoNzP4m7H4vux2FzYkjkXhdqnnw',
28
- 'ES256' => '',
29
- 'ES384' => '',
30
- 'ES512' => ''
31
- }
32
- end
33
-
34
- after(:each) do
35
- expect(OpenSSL.errors).to be_empty
36
- end
37
-
38
- context 'alg: NONE' do
39
- let(:alg) { 'none' }
40
-
41
- it 'should generate a valid token' do
42
- token = JWT.encode payload, nil, alg
43
-
44
- expect(token).to eq data['NONE']
45
- end
46
-
47
- it 'should decode a valid token' do
48
- jwt_payload, header = JWT.decode data['NONE'], nil, false
49
-
50
- expect(header['alg']).to eq alg
51
- expect(jwt_payload).to eq payload
52
- end
53
-
54
- it 'should display a better error message if payload exp is_a?(Time)' do
55
- payload['exp'] = Time.now
56
-
57
- expect do
58
- JWT.encode payload, nil, alg
59
- end.to raise_error JWT::InvalidPayload
60
- end
61
- end
62
-
63
- %w(HS256 HS384 HS512).each do |alg|
64
- context "alg: #{alg}" do
65
- it 'should generate a valid token' do
66
- token = JWT.encode payload, data[:secret], alg
67
-
68
- expect(token).to eq data[alg]
69
- end
70
-
71
- it 'should decode a valid token' do
72
- jwt_payload, header = JWT.decode data[alg], data[:secret]
73
-
74
- expect(header['alg']).to eq alg
75
- expect(jwt_payload).to eq payload
76
- end
77
-
78
- it 'wrong secret should raise JWT::DecodeError' do
79
- expect do
80
- JWT.decode data[alg], 'wrong_secret'
81
- end.to raise_error JWT::DecodeError
82
- end
83
-
84
- it 'wrong secret and verify = false should not raise JWT::DecodeError' do
85
- expect do
86
- JWT.decode data[alg], 'wrong_secret', false
87
- end.not_to raise_error
88
- end
89
- end
90
- end
91
-
92
- %w(RS256 RS384 RS512).each do |alg|
93
- context "alg: #{alg}" do
94
- it 'should generate a valid token' do
95
- token = JWT.encode payload, data[:rsa_private], alg
96
-
97
- expect(token).to eq data[alg]
98
- end
99
-
100
- it 'should decode a valid token' do
101
- jwt_payload, header = JWT.decode data[alg], data[:rsa_public]
102
-
103
- expect(header['alg']).to eq alg
104
- expect(jwt_payload).to eq payload
105
- end
106
-
107
- it 'wrong key should raise JWT::DecodeError' do
108
- key = OpenSSL::PKey.read File.read(File.join(CERT_PATH, 'rsa-2048-wrong-public.pem'))
109
-
110
- expect do
111
- JWT.decode data[alg], key
112
- end.to raise_error JWT::DecodeError
113
- end
114
-
115
- it 'wrong key and verify = false should not raise JWT::DecodeError' do
116
- key = OpenSSL::PKey.read File.read(File.join(CERT_PATH, 'rsa-2048-wrong-public.pem'))
117
-
118
- expect do
119
- JWT.decode data[alg], key, false
120
- end.not_to raise_error
121
- end
122
- end
123
- end
124
-
125
- %w(ES256 ES384 ES512).each do |alg|
126
- context "alg: #{alg}" do
127
- before(:each) do
128
- data[alg] = JWT.encode payload, data["#{alg}_private"], alg
129
- end
130
-
131
- let(:wrong_key) { OpenSSL::PKey.read(File.read(File.join(CERT_PATH, 'ec256-wrong-public.pem'))) }
132
-
133
- it 'should generate a valid token' do
134
- jwt_payload, header = JWT.decode data[alg], data["#{alg}_public"]
135
-
136
- expect(header['alg']).to eq alg
137
- expect(jwt_payload).to eq payload
138
- end
139
-
140
- it 'should decode a valid token' do
141
- jwt_payload, header = JWT.decode data[alg], data["#{alg}_public"]
142
-
143
- expect(header['alg']).to eq alg
144
- expect(jwt_payload).to eq payload
145
- end
146
-
147
- it 'wrong key should raise JWT::DecodeError' do
148
- expect do
149
- JWT.decode data[alg], wrong_key
150
- end.to raise_error JWT::DecodeError
151
- end
152
-
153
- it 'wrong key and verify = false should not raise JWT::DecodeError' do
154
- expect do
155
- JWT.decode data[alg], wrong_key, false
156
- end.not_to raise_error
157
- end
158
- end
159
- end
160
-
161
- context 'Invalid' do
162
- it 'algorithm should raise NotImplementedError' do
163
- expect do
164
- JWT.encode payload, 'secret', 'HS255'
165
- end.to raise_error NotImplementedError
166
- end
167
-
168
- it 'ECDSA curve_name should raise JWT::IncorrectAlgorithm' do
169
- key = OpenSSL::PKey::EC.new 'secp256k1'
170
- key.generate_key
171
-
172
- expect do
173
- JWT.encode payload, key, 'ES256'
174
- end.to raise_error JWT::IncorrectAlgorithm
175
-
176
- token = JWT.encode payload, data['ES256_private'], 'ES256'
177
- key.private_key = nil
178
-
179
- expect do
180
- JWT.decode token, key
181
- end.to raise_error JWT::IncorrectAlgorithm
182
- end
183
- end
184
-
185
- context 'Verify' do
186
- context 'algorithm' do
187
- it 'should raise JWT::IncorrectAlgorithm on missmatch' do
188
- token = JWT.encode payload, data[:secret], 'HS512'
189
-
190
- expect do
191
- JWT.decode token, data[:secret], true, algorithm: 'HS384'
192
- end.to raise_error JWT::IncorrectAlgorithm
193
-
194
- expect do
195
- JWT.decode token, data[:secret], true, algorithm: 'HS512'
196
- end.not_to raise_error
197
- end
198
- end
199
-
200
- context 'issuer claim' do
201
- let(:iss) { 'ruby-jwt-gem' }
202
- let(:invalid_token) { JWT.encode payload, data[:secret] }
203
-
204
- let :token do
205
- iss_payload = payload.merge(iss: iss)
206
- JWT.encode iss_payload, data[:secret]
207
- end
208
-
209
- it 'if verify_iss is set to false (default option) should not raise JWT::InvalidIssuerError' do
210
- expect do
211
- JWT.decode token, data[:secret], true, iss: iss
212
- end.not_to raise_error
213
- end
214
- end
215
- end
216
-
217
- context 'Base64' do
218
- it 'urlsafe replace + / with - _' do
219
- allow(Base64).to receive(:encode64) { 'string+with/non+url-safe/characters_' }
220
- expect(JWT.base64url_encode('foo')).to eq('string-with_non-url-safe_characters_')
221
- end
222
- end
223
-
224
- describe 'secure comparison' do
225
- it 'returns true if strings are equal' do
226
- expect(JWT.secure_compare('Foo', 'Foo')).to eq true
227
- end
228
-
229
- it 'returns false if either input is nil or empty' do
230
- [nil, ''].each do |bad|
231
- expect(JWT.secure_compare(bad, 'Foo')).to eq false
232
- expect(JWT.secure_compare('Foo', bad)).to eq false
233
- end
234
- end
235
-
236
- it 'retuns false if the strings are different' do
237
- expect(JWT.secure_compare('Foo', 'Bar')).to eq false
238
- end
239
- end
240
- end
@@ -1,31 +0,0 @@
1
- require 'rspec'
2
- require 'simplecov'
3
- require 'simplecov-json'
4
- require 'codeclimate-test-reporter'
5
-
6
- SimpleCov.configure do
7
- root File.join(File.dirname(__FILE__), '..')
8
- project_name 'Ruby JWT - Ruby JSON Web Token implementation'
9
- SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter.new([
10
- SimpleCov::Formatter::HTMLFormatter,
11
- SimpleCov::Formatter::JSONFormatter
12
- ])
13
-
14
- add_filter 'spec'
15
- end
16
-
17
- SimpleCov.start if ENV['COVERAGE']
18
- CodeClimate::TestReporter.start if ENV['CODECLIMATE_REPO_TOKEN']
19
-
20
- CERT_PATH = File.join(File.dirname(__FILE__), 'fixtures', 'certs')
21
-
22
- RSpec.configure do |config|
23
- config.expect_with :rspec do |c|
24
- c.syntax = [:should, :expect]
25
- end
26
-
27
- config.run_all_when_everything_filtered = true
28
- config.filter_run :focus
29
-
30
- config.order = 'random'
31
- end