jwt 1.5.6 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 8cd1a9ca017dec28c4984e18003e8ae58aee776c
4
- data.tar.gz: c5fef77f9a8e42d8fa92c060c468be6ee2e3c561
3
+ metadata.gz: c63d3d103ec14f12ea2b51b95ae8f5407dd7ace9
4
+ data.tar.gz: f1de3f1e8ddfb79aa690a1f6d44492c70d037942
5
5
  SHA512:
6
- metadata.gz: c0dc92b0ea35004782c8260f8d2d47c9973a1172f5eb6bef33fe42ae3a2e8341c9264e5fafc7cb62442039409194c3aa6fbd3db78667db75af04ffd26586422f
7
- data.tar.gz: af9967d4c04b332ef8916d3b837e31c20b2e5db8c96531b277286324f29730edbc65eb66401f6db405b22dbd2701895d2579796fab368c26bd1fca58aae30840
6
+ metadata.gz: 3b19fcd5018d17e4277a49abc5787cee37ff3991fc8cbcc97dbb00f50c3878fc08062d97e18e07cdaf5f8f2f09cfbf5a8937e11859ae9b44d90a8d5a20caa021
7
+ data.tar.gz: f9df1adefd0f0d4525567372c8283e72639b2ee67320a893ef03d470bbbd6afd09a65725d3eb3153f8c68e7d40f693c7da3a5ed138ab766a23aa6ebbfe5c62f6
data/.ebert.yml ADDED
@@ -0,0 +1,17 @@
1
+ styleguide: plataformatec/linters
2
+ engines:
3
+ reek:
4
+ enabled: true
5
+ fixme:
6
+ enabled: true
7
+ rubocop:
8
+ enabled: true
9
+ duplication:
10
+ config:
11
+ languages:
12
+ - ruby
13
+ enabled: true
14
+ remark-lint:
15
+ enabled: true
16
+ exclude_paths:
17
+ - spec
data/.reek.yml ADDED
@@ -0,0 +1,40 @@
1
+ ---
2
+ TooManyStatements:
3
+ max_statements: 10
4
+ UncommunicativeMethodName:
5
+ reject:
6
+ - !ruby/regexp /^[a-z]$/
7
+ - !ruby/regexp /[0-9]$/
8
+ UncommunicativeParameterName:
9
+ reject:
10
+ - !ruby/regexp /^.$/
11
+ - !ruby/regexp /[0-9]$/
12
+ - !ruby/regexp /^_/
13
+ UncommunicativeVariableName:
14
+ reject:
15
+ - !ruby/regexp /^.$/
16
+ - !ruby/regexp /[0-9]$/
17
+ UtilityFunction:
18
+ enabled: false
19
+ LongParameterList:
20
+ enabled: false
21
+ DuplicateMethodCall:
22
+ max_calls: 2
23
+ IrresponsibleModule:
24
+ enabled: false
25
+ NestedIterators:
26
+ max_allowed_nesting: 2
27
+ PrimaDonnaMethod:
28
+ enabled: false
29
+ UnusedParameters:
30
+ enabled: false
31
+ FeatureEnvy:
32
+ enabled: false
33
+ ControlParameter:
34
+ enabled: false
35
+ UnusedPrivateMethod:
36
+ enabled: false
37
+ InstanceVariableAssumption:
38
+ exclude:
39
+ - !ruby/regexp /Controller$/
40
+ - !ruby/regexp /Mailer$/s
data/.rubocop.yml CHANGED
@@ -1,2 +1,98 @@
1
+ AllCops:
2
+ Exclude:
3
+ - 'bin/**/*'
4
+ - 'db/**/*'
5
+ - 'config/**/*'
6
+ - 'script/**/*'
7
+
8
+ Rails:
9
+ Enabled: true
10
+
11
+ Style/AlignParameters:
12
+ EnforcedStyle: with_fixed_indentation
13
+
14
+ Style/CaseIndentation:
15
+ EnforcedStyle: end
16
+
17
+ Style/AsciiComments:
18
+ Enabled: false
19
+
20
+ Style/IndentHash:
21
+ Enabled: false
22
+
23
+ Style/CollectionMethods:
24
+ Enabled: true
25
+ PreferredMethods:
26
+ inject: 'inject'
27
+
28
+ Style/Documentation:
29
+ Enabled: false
30
+
31
+ Style/BlockDelimiters:
32
+ Exclude:
33
+ - spec/**/*_spec.rb
34
+
35
+ Style/BracesAroundHashParameters:
36
+ Exclude:
37
+ - spec/**/*_spec.rb
38
+
39
+ Style/GuardClause:
40
+ Enabled: false
41
+
42
+ Style/IfUnlessModifier:
43
+ Enabled: false
44
+
45
+ Style/SpaceInsideHashLiteralBraces:
46
+ Enabled: false
47
+
48
+ Style/Lambda:
49
+ Enabled: false
50
+
51
+ Style/RaiseArgs:
52
+ Enabled: false
53
+
54
+ Style/SignalException:
55
+ Enabled: false
56
+
57
+ Metrics/AbcSize:
58
+ Max: 20
59
+
60
+ Metrics/ClassLength:
61
+ Max: 100
62
+
63
+ Metrics/ModuleLength:
64
+ Max: 100
65
+
1
66
  Metrics/LineLength:
2
67
  Enabled: false
68
+
69
+ Metrics/MethodLength:
70
+ Max: 15
71
+
72
+ Style/SingleLineBlockParams:
73
+ Enabled: false
74
+
75
+ Lint/EndAlignment:
76
+ EnforcedStyleAlignWith: variable
77
+
78
+ Style/FormatString:
79
+ Enabled: false
80
+
81
+ Style/MultilineMethodCallIndentation:
82
+ EnforcedStyle: indented
83
+
84
+ Style/MultilineOperationIndentation:
85
+ EnforcedStyle: indented
86
+
87
+ Style/WordArray:
88
+ Enabled: false
89
+
90
+ Style/RedundantSelf:
91
+ Enabled: false
92
+
93
+ Style/AlignHash:
94
+ Enabled: true
95
+ EnforcedLastArgumentHashStyle: always_ignore
96
+
97
+ Style/TrivialAccessors:
98
+ AllowPredicates: true
data/.travis.yml CHANGED
@@ -1,13 +1,14 @@
1
- sudo: false
1
+ sudo: required
2
2
  cache: bundler
3
+ dist: trusty
3
4
  language: ruby
4
5
  rvm:
5
- - 1.9.3
6
- - 2.0.0
7
- - 2.1.0
8
6
  - 2.2.0
9
7
  - 2.3.0
10
- script: "bundle exec rspec"
11
- addons:
12
- code_climate:
13
- repo_token: e87b175db123ab42ca2ca4420abaa13c0dc2085608402b9a25f08a83ca3ba202
8
+ - 2.4.0
9
+ script: "bundle exec rspec && bundle exec codeclimate-test-reporter"
10
+ before_install:
11
+ - sudo add-apt-repository ppa:chris-lea/libsodium -y
12
+ - sudo apt-get update -q
13
+ - sudo apt-get install libsodium-dev -y
14
+ - gem install bundler
data/CHANGELOG.md CHANGED
@@ -1,5 +1,86 @@
1
1
  # Change Log
2
2
 
3
+ ## [v2.0.0](https://github.com/jwt/ruby-jwt/tree/v2.0.0) (2017-09-03)
4
+ [Full Changelog](https://github.com/jwt/ruby-jwt/compare/v2.0.0.beta1...v2.0.0)
5
+
6
+ **Fixed bugs:**
7
+
8
+ - Support versions outside 2.1 [\#209](https://github.com/jwt/ruby-jwt/issues/209)
9
+ - Verifying expiration without leeway throws exception [\#206](https://github.com/jwt/ruby-jwt/issues/206)
10
+ - Ruby interpreter warning [\#200](https://github.com/jwt/ruby-jwt/issues/200)
11
+ - TypeError: no implicit conversion of String into Integer [\#188](https://github.com/jwt/ruby-jwt/issues/188)
12
+ - Fix JWT.encode\(nil\) [\#203](https://github.com/jwt/ruby-jwt/pull/203) ([tmm1](https://github.com/tmm1))
13
+
14
+ **Closed issues:**
15
+
16
+ - Possibility to disable claim verifications [\#222](https://github.com/jwt/ruby-jwt/issues/222)
17
+ - Proper way to verify Firebase id tokens [\#216](https://github.com/jwt/ruby-jwt/issues/216)
18
+
19
+ **Merged pull requests:**
20
+
21
+ - Skip 'exp' claim validation for array payloads [\#224](https://github.com/jwt/ruby-jwt/pull/224) ([excpt](https://github.com/excpt))
22
+ - Use a default leeway of 0 [\#223](https://github.com/jwt/ruby-jwt/pull/223) ([travisofthenorth](https://github.com/travisofthenorth))
23
+ - Fix reported codesmells [\#221](https://github.com/jwt/ruby-jwt/pull/221) ([excpt](https://github.com/excpt))
24
+ - Add fancy gem version badge [\#220](https://github.com/jwt/ruby-jwt/pull/220) ([excpt](https://github.com/excpt))
25
+ - Add missing dist option to .travis.yml [\#219](https://github.com/jwt/ruby-jwt/pull/219) ([excpt](https://github.com/excpt))
26
+ - Fix ruby version requirements in gemspec file [\#218](https://github.com/jwt/ruby-jwt/pull/218) ([excpt](https://github.com/excpt))
27
+ - Fix a little typo in the readme [\#214](https://github.com/jwt/ruby-jwt/pull/214) ([RyanBrushett](https://github.com/RyanBrushett))
28
+ - Update README.md [\#212](https://github.com/jwt/ruby-jwt/pull/212) ([zuzannast](https://github.com/zuzannast))
29
+ - Fix typo in HS512256 algorithm description [\#211](https://github.com/jwt/ruby-jwt/pull/211) ([ojab](https://github.com/ojab))
30
+ - Allow configuration of multiple acceptable issuers [\#210](https://github.com/jwt/ruby-jwt/pull/210) ([ojab](https://github.com/ojab))
31
+ - Enforce `exp` to be an `Integer` [\#205](https://github.com/jwt/ruby-jwt/pull/205) ([lucasmazza](https://github.com/lucasmazza))
32
+ - ruby 1.9.3 support message upd [\#204](https://github.com/jwt/ruby-jwt/pull/204) ([maokomioko](https://github.com/maokomioko))
33
+ - Guard against partially loaded RbNaCl when failing to load libsodium [\#202](https://github.com/jwt/ruby-jwt/pull/202) ([Dorian](https://github.com/Dorian))
34
+
35
+ ## [v2.0.0.beta1](https://github.com/jwt/ruby-jwt/tree/v2.0.0.beta1) (2017-02-27)
36
+ [Full Changelog](https://github.com/jwt/ruby-jwt/compare/v1.5.6...v2.0.0.beta1)
37
+
38
+ **Implemented enhancements:**
39
+
40
+ - Error with method sign for String [\#171](https://github.com/jwt/ruby-jwt/issues/171)
41
+ - Refactor the encondig code [\#121](https://github.com/jwt/ruby-jwt/issues/121)
42
+ - Refactor [\#196](https://github.com/jwt/ruby-jwt/pull/196) ([EmilioCristalli](https://github.com/EmilioCristalli))
43
+ - Move signature logic to its own module [\#195](https://github.com/jwt/ruby-jwt/pull/195) ([EmilioCristalli](https://github.com/EmilioCristalli))
44
+ - Add options for claim-specific leeway [\#187](https://github.com/jwt/ruby-jwt/pull/187) ([EmilioCristalli](https://github.com/EmilioCristalli))
45
+ - Add user friendly encode error if private key is a String, \#171 [\#176](https://github.com/jwt/ruby-jwt/pull/176) ([xamenrax](https://github.com/xamenrax))
46
+ - Return empty string if signature less than byte\_size \#155 [\#175](https://github.com/jwt/ruby-jwt/pull/175) ([xamenrax](https://github.com/xamenrax))
47
+ - Remove 'typ' optional parameter [\#174](https://github.com/jwt/ruby-jwt/pull/174) ([xamenrax](https://github.com/xamenrax))
48
+ - Pass payload to keyfinder [\#172](https://github.com/jwt/ruby-jwt/pull/172) ([CodeMonkeySteve](https://github.com/CodeMonkeySteve))
49
+ - Use RbNaCl for HMAC if available with fallback to OpenSSL [\#149](https://github.com/jwt/ruby-jwt/pull/149) ([mwpastore](https://github.com/mwpastore))
50
+
51
+ **Fixed bugs:**
52
+
53
+ - ruby-jwt::raw\_to\_asn1: Fails for signatures less than byte\_size [\#155](https://github.com/jwt/ruby-jwt/issues/155)
54
+ - The leeway parameter is applies to all time based verifications [\#129](https://github.com/jwt/ruby-jwt/issues/129)
55
+ - Add options for claim-specific leeway [\#187](https://github.com/jwt/ruby-jwt/pull/187) ([EmilioCristalli](https://github.com/EmilioCristalli))
56
+ - Make algorithm option required to verify signature [\#184](https://github.com/jwt/ruby-jwt/pull/184) ([EmilioCristalli](https://github.com/EmilioCristalli))
57
+ - Validate audience when payload is a scalar and options is an array [\#183](https://github.com/jwt/ruby-jwt/pull/183) ([steti](https://github.com/steti))
58
+
59
+ **Closed issues:**
60
+
61
+ - Different encoded value between servers with same password [\#197](https://github.com/jwt/ruby-jwt/issues/197)
62
+ - Signature is different at each run [\#190](https://github.com/jwt/ruby-jwt/issues/190)
63
+ - Include custom headers with password [\#189](https://github.com/jwt/ruby-jwt/issues/189)
64
+ - can't create token - 'NotImplementedError: Unsupported signing method' [\#186](https://github.com/jwt/ruby-jwt/issues/186)
65
+ - Why jwt depends on json \< 2.0 ? [\#179](https://github.com/jwt/ruby-jwt/issues/179)
66
+ - Cannot verify JWT at all?? [\#177](https://github.com/jwt/ruby-jwt/issues/177)
67
+ - verify\_iss: true is raising JWT::DecodeError instead of JWT::InvalidIssuerError [\#170](https://github.com/jwt/ruby-jwt/issues/170)
68
+
69
+ **Merged pull requests:**
70
+
71
+ - Version bump 2.0.0.beta1 [\#199](https://github.com/jwt/ruby-jwt/pull/199) ([excpt](https://github.com/excpt))
72
+ - Update CHANGELOG.md and minor fixes [\#198](https://github.com/jwt/ruby-jwt/pull/198) ([excpt](https://github.com/excpt))
73
+ - Add Codacy coverage reporter [\#194](https://github.com/jwt/ruby-jwt/pull/194) ([excpt](https://github.com/excpt))
74
+ - Add minimum required ruby version to gemspec [\#193](https://github.com/jwt/ruby-jwt/pull/193) ([excpt](https://github.com/excpt))
75
+ - Code smell fixes [\#192](https://github.com/jwt/ruby-jwt/pull/192) ([excpt](https://github.com/excpt))
76
+ - Version bump to 2.0.0.dev [\#191](https://github.com/jwt/ruby-jwt/pull/191) ([excpt](https://github.com/excpt))
77
+ - Basic encode module refactoring \#121 [\#182](https://github.com/jwt/ruby-jwt/pull/182) ([xamenrax](https://github.com/xamenrax))
78
+ - Fix travis ci build configuration [\#181](https://github.com/jwt/ruby-jwt/pull/181) ([excpt](https://github.com/excpt))
79
+ - Fix travis ci build configuration [\#180](https://github.com/jwt/ruby-jwt/pull/180) ([excpt](https://github.com/excpt))
80
+ - Fix typo in README [\#178](https://github.com/jwt/ruby-jwt/pull/178) ([tomeduarte](https://github.com/tomeduarte))
81
+ - Fix code style [\#173](https://github.com/jwt/ruby-jwt/pull/173) ([excpt](https://github.com/excpt))
82
+ - Fixed a typo in a spec name [\#169](https://github.com/jwt/ruby-jwt/pull/169) ([Mingan](https://github.com/Mingan))
83
+
3
84
  ## [v1.5.6](https://github.com/jwt/ruby-jwt/tree/v1.5.6) (2016-09-19)
4
85
  [Full Changelog](https://github.com/jwt/ruby-jwt/compare/v1.5.5...v1.5.6)
5
86
 
@@ -9,6 +90,7 @@
9
90
 
10
91
  **Merged pull requests:**
11
92
 
93
+ - Update changelog [\#168](https://github.com/jwt/ruby-jwt/pull/168) ([excpt](https://github.com/excpt))
12
94
  - Fix rubocop code smells [\#167](https://github.com/jwt/ruby-jwt/pull/167) ([excpt](https://github.com/excpt))
13
95
 
14
96
  ## [v1.5.5](https://github.com/jwt/ruby-jwt/tree/v1.5.5) (2016-09-16)
@@ -253,7 +335,6 @@
253
335
 
254
336
  **Closed issues:**
255
337
 
256
- - yanking of version 0.1.12 causes issues [\#39](https://github.com/jwt/ruby-jwt/issues/39)
257
338
  - Semantic versioning [\#37](https://github.com/jwt/ruby-jwt/issues/37)
258
339
  - Update gem to get latest changes [\#36](https://github.com/jwt/ruby-jwt/issues/36)
259
340
 
data/Gemfile CHANGED
@@ -1,4 +1,3 @@
1
- # encoding: utf-8
2
1
  source 'https://rubygems.org'
3
2
 
4
3
  gemspec
data/README.md CHANGED
@@ -1,5 +1,6 @@
1
1
  # JWT
2
2
 
3
+ [![Gem Version](https://badge.fury.io/rb/jwt.svg)](https://badge.fury.io/rb/jwt)
3
4
  [![Build Status](https://travis-ci.org/jwt/ruby-jwt.svg)](https://travis-ci.org/jwt/ruby-jwt)
4
5
  [![Code Climate](https://codeclimate.com/github/jwt/ruby-jwt/badges/gpa.svg)](https://codeclimate.com/github/jwt/ruby-jwt)
5
6
  [![Test Coverage](https://codeclimate.com/github/jwt/ruby-jwt/badges/coverage.svg)](https://codeclimate.com/github/jwt/ruby-jwt/coverage)
@@ -7,11 +8,11 @@
7
8
 
8
9
  A pure ruby implementation of the [RFC 7519 OAuth JSON Web Token (JWT)](https://tools.ietf.org/html/rfc7519) standard.
9
10
 
10
- If you have further questions releated to development or usage, join us: [ruby-jwt google group](https://groups.google.com/forum/#!forum/ruby-jwt).
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).
11
12
 
12
13
  ## Announcements
13
14
 
14
- * Ruby 1.9.3 support will be dropped by December 31st, 2016.
15
+ * Ruby 1.9.3 support was dropped at December 31st, 2016.
15
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)
16
17
 
17
18
  ## Installing
@@ -55,7 +56,7 @@ decoded_token = JWT.decode token, nil, false
55
56
  # Array
56
57
  # [
57
58
  # {"data"=>"test"}, # payload
58
- # {"typ"=>"JWT", "alg"=>"none"} # header
59
+ # {"alg"=>"none"} # header
59
60
  # ]
60
61
  puts decoded_token
61
62
  ```
@@ -63,6 +64,7 @@ puts decoded_token
63
64
  **HMAC** (default: HS256)
64
65
 
65
66
  * HS256 - HMAC using SHA-256 hash algorithm (default)
67
+ * HS512256 - HMAC using SHA-512-256 hash algorithm (only available with RbNaCl; see note below)
66
68
  * HS384 - HMAC using SHA-384 hash algorithm
67
69
  * HS512 - HMAC using SHA-512 hash algorithm
68
70
 
@@ -79,11 +81,17 @@ decoded_token = JWT.decode token, hmac_secret, true, { :algorithm => 'HS256' }
79
81
  # Array
80
82
  # [
81
83
  # {"data"=>"test"}, # payload
82
- # {"typ"=>"JWT", "alg"=>"HS256"} # header
84
+ # {"alg"=>"HS256"} # header
83
85
  # ]
84
86
  puts decoded_token
85
87
  ```
86
88
 
89
+ 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.
90
+
91
+ [RbNaCl](https://github.com/cryptosphere/rbnacl) requires
92
+ [libsodium](https://github.com/jedisct1/libsodium), it can be installed
93
+ on MacOS with `brew install libsodium`.
94
+
87
95
  **RSA**
88
96
 
89
97
  * RS256 - RSA using SHA-256 hash algorithm
@@ -104,7 +112,7 @@ decoded_token = JWT.decode token, rsa_public, true, { :algorithm => 'RS256' }
104
112
  # Array
105
113
  # [
106
114
  # {"data"=>"test"}, # payload
107
- # {"typ"=>"JWT", "alg"=>"RS256"} # header
115
+ # {"alg"=>"RS256"} # header
108
116
  # ]
109
117
  puts decoded_token
110
118
  ```
@@ -131,7 +139,7 @@ decoded_token = JWT.decode token, ecdsa_public, true, { :algorithm => 'ES256' }
131
139
  # Array
132
140
  # [
133
141
  # {"test"=>"data"}, # payload
134
- # {"typ"=>"JWT", "alg"=>"ES256"} # header
142
+ # {"alg"=>"ES256"} # header
135
143
  # ]
136
144
  puts decoded_token
137
145
  ```
@@ -152,6 +160,38 @@ used. JWT supports these reserved claim names:
152
160
  - 'iat' (Issued At) Claim
153
161
  - 'sub' (Subject) Claim
154
162
 
163
+ ## Add custom header fields
164
+ Ruby-jwt gem supports custom [header fields] (https://tools.ietf.org/html/rfc7519#section-5)
165
+ To add custom header fields you need to pass `header_fields` parameter
166
+
167
+ ```ruby
168
+ token = JWT.encode payload, key, algorithm='HS256', header_fields={}
169
+ ```
170
+
171
+ **Example:**
172
+
173
+ ```ruby
174
+ require 'jwt'
175
+
176
+ payload = {:data => 'test'}
177
+
178
+ # IMPORTANT: set nil as password parameter
179
+ token = JWT.encode payload, nil, 'none', { :typ => "JWT" }
180
+
181
+ # eyJ0eXAiOiJKV1QiLCJhbGciOiJub25lIn0.eyJkYXRhIjoidGVzdCJ9.
182
+ puts token
183
+
184
+ # Set password to nil and validation to false otherwise this won't work
185
+ decoded_token = JWT.decode token, nil, false
186
+
187
+ # Array
188
+ # [
189
+ # {"data"=>"test"}, # payload
190
+ # {"typ"=>"JWT", "alg"=>"none"} # header
191
+ # ]
192
+ puts decoded_token
193
+ ```
194
+
155
195
  ### Expiration Time Claim
156
196
 
157
197
  From [Oauth JSON Web Token 4.1.4. "exp" (Expiration Time) Claim](https://tools.ietf.org/html/rfc7519#section-4.1.4):
@@ -186,7 +226,7 @@ token = JWT.encode exp_payload, hmac_secret, 'HS256'
186
226
 
187
227
  begin
188
228
  # add leeway to ensure the token is still accepted
189
- decoded_token = JWT.decode token, hmac_secret, true, { :leeway => leeway, :algorithm => 'HS256' }
229
+ decoded_token = JWT.decode token, hmac_secret, true, { :exp_leeway => leeway, :algorithm => 'HS256' }
190
230
  rescue JWT::ExpiredSignature
191
231
  # Handle expired token, e.g. logout user or deny access
192
232
  end
@@ -226,7 +266,7 @@ token = JWT.encode nbf_payload, hmac_secret, 'HS256'
226
266
 
227
267
  begin
228
268
  # add leeway to ensure the token is valid
229
- decoded_token = JWT.decode token, hmac_secret, true, { :leeway => leeway, :algorithm => 'HS256' }
269
+ decoded_token = JWT.decode token, hmac_secret, true, { :nbf_leeway => leeway, :algorithm => 'HS256' }
230
270
  rescue JWT::ImmatureSignature
231
271
  # Handle invalid token, e.g. logout user or deny access
232
272
  end
@@ -238,6 +278,8 @@ From [Oauth JSON Web Token 4.1.1. "iss" (Issuer) Claim](https://tools.ietf.org/h
238
278
 
239
279
  > The `iss` (issuer) claim identifies the principal that issued the JWT. The processing of this claim is generally application specific. The `iss` value is a case-sensitive string containing a ***StringOrURI*** value. Use of this claim is OPTIONAL.
240
280
 
281
+ You can pass multiple allowed issuers as an Array, verification will pass if one of them matches the `iss` value in the payload.
282
+
241
283
  ```ruby
242
284
  iss = 'My Awesome Company Inc. or https://my.awesome.website/'
243
285
  iss_payload = { :data => 'data', :iss => iss }
@@ -305,6 +347,8 @@ From [Oauth JSON Web Token 4.1.6. "iat" (Issued At) Claim](https://tools.ietf.or
305
347
 
306
348
  > The `iat` (issued at) claim identifies the time at which the JWT was issued. This claim can be used to determine the age of the JWT. Its value MUST be a number containing a ***NumericDate*** value. Use of this claim is OPTIONAL.
307
349
 
350
+ **Handle Issued At Claim**
351
+
308
352
  ```ruby
309
353
  iat = Time.now.to_i
310
354
  iat_payload = { :data => 'data', :iat => iat }
@@ -319,6 +363,25 @@ rescue JWT::InvalidIatError
319
363
  end
320
364
  ```
321
365
 
366
+ **Adding Leeway**
367
+
368
+ ```ruby
369
+ iat = Time.now.to_i + 10
370
+ leeway = 30 # seconds
371
+
372
+ iat_payload = { :data => 'data', :iat => iat }
373
+
374
+ # build token issued in the future
375
+ token = JWT.encode iat_payload, hmac_secret, 'HS256'
376
+
377
+ begin
378
+ # add leeway to ensure the token is accepted
379
+ decoded_token = JWT.decode token, hmac_secret, true, { :iat_leeway => leeway, :verify_iat => true, :algorithm => 'HS256' }
380
+ rescue JWT::InvalidIatError
381
+ # Handle invalid token, e.g. logout user or deny access
382
+ end
383
+ ```
384
+
322
385
  ### Subject Claim
323
386
 
324
387
  From [Oauth JSON Web Token 4.1.2. "sub" (Subject) Claim](https://tools.ietf.org/html/rfc7519#section-4.1.2):
data/lib/jwt/decode.rb CHANGED
@@ -1,57 +1,49 @@
1
1
  # frozen_string_literal: true
2
- require 'jwt/json'
3
- require 'jwt/verify'
2
+
3
+ require 'json'
4
4
 
5
5
  # JWT::Decode module
6
6
  module JWT
7
- extend JWT::Json
8
-
9
7
  # Decoding logic for JWT
10
8
  class Decode
11
9
  attr_reader :header, :payload, :signature
12
10
 
13
- def initialize(jwt, key, verify, options, &keyfinder)
11
+ def self.base64url_decode(str)
12
+ str += '=' * (4 - str.length.modulo(4))
13
+ Base64.decode64(str.tr('-_', '+/'))
14
+ end
15
+
16
+ def initialize(jwt, verify)
14
17
  @jwt = jwt
15
- @key = key
16
18
  @verify = verify
17
- @options = options
18
- @keyfinder = keyfinder
19
+ @header = ''
20
+ @payload = ''
21
+ @signature = ''
19
22
  end
20
23
 
21
24
  def decode_segments
22
- header_segment, payload_segment, crypto_segment = raw_segments(@jwt, @verify)
25
+ header_segment, payload_segment, crypto_segment = raw_segments
23
26
  @header, @payload = decode_header_and_payload(header_segment, payload_segment)
24
27
  @signature = Decode.base64url_decode(crypto_segment.to_s) if @verify
25
28
  signing_input = [header_segment, payload_segment].join('.')
26
29
  [@header, @payload, @signature, signing_input]
27
30
  end
28
31
 
29
- def raw_segments(jwt, verify)
30
- segments = jwt.split('.')
31
- required_num_segments = verify ? [3] : [2, 3]
32
+ private
33
+
34
+ def raw_segments
35
+ segments = @jwt.split('.')
36
+ required_num_segments = @verify ? [3] : [2, 3]
32
37
  raise(JWT::DecodeError, 'Not enough or too many segments') unless required_num_segments.include? segments.length
33
38
  segments
34
39
  end
35
- private :raw_segments
36
40
 
37
41
  def decode_header_and_payload(header_segment, payload_segment)
38
- header = JWT.decode_json(Decode.base64url_decode(header_segment))
39
- payload = JWT.decode_json(Decode.base64url_decode(payload_segment))
42
+ header = JSON.parse(Decode.base64url_decode(header_segment))
43
+ payload = JSON.parse(Decode.base64url_decode(payload_segment))
40
44
  [header, payload]
41
- end
42
- private :decode_header_and_payload
43
-
44
- def self.base64url_decode(str)
45
- str += '=' * (4 - str.length.modulo(4))
46
- Base64.decode64(str.tr('-_', '+/'))
47
- end
48
-
49
- def verify
50
- @options.each do |key, val|
51
- next unless key.to_s =~ /verify/
52
-
53
- Verify.send(key, payload, @options) if val
54
- end
45
+ rescue JSON::ParserError
46
+ raise JWT::DecodeError, 'Invalid segment encoding'
55
47
  end
56
48
  end
57
49
  end
@@ -0,0 +1,14 @@
1
+ module JWT
2
+ module DefaultOptions
3
+ DEFAULT_OPTIONS = {
4
+ verify_expiration: true,
5
+ verify_not_before: true,
6
+ verify_iss: false,
7
+ verify_iat: false,
8
+ verify_jti: false,
9
+ verify_aud: false,
10
+ verify_sub: false,
11
+ leeway: 0
12
+ }.freeze
13
+ end
14
+ end
data/lib/jwt/encode.rb ADDED
@@ -0,0 +1,51 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'json'
4
+
5
+ # JWT::Encode module
6
+ module JWT
7
+ # Encoding logic for JWT
8
+ class Encode
9
+ attr_reader :payload, :key, :algorithm, :header_fields, :segments
10
+
11
+ def self.base64url_encode(str)
12
+ Base64.encode64(str).tr('+/', '-_').gsub(/[\n=]/, '')
13
+ end
14
+
15
+ def initialize(payload, key, algorithm, header_fields)
16
+ @payload = payload
17
+ @key = key
18
+ @algorithm = algorithm
19
+ @header_fields = header_fields
20
+ @segments = encode_segments
21
+ end
22
+
23
+ private
24
+
25
+ def encoded_header
26
+ header = { 'alg' => @algorithm }.merge(@header_fields)
27
+ Encode.base64url_encode(JSON.generate(header))
28
+ end
29
+
30
+ def encoded_payload
31
+ raise InvalidPayload, 'exp claim must be an integer' if @payload && !@payload.is_a?(Array) && @payload.key?('exp') && !@payload['exp'].is_a?(Integer)
32
+ Encode.base64url_encode(JSON.generate(@payload))
33
+ end
34
+
35
+ def encoded_signature(signing_input)
36
+ if @algorithm == 'none'
37
+ ''
38
+ else
39
+ signature = JWT::Signature.sign(@algorithm, signing_input, @key)
40
+ Encode.base64url_encode(signature)
41
+ end
42
+ end
43
+
44
+ def encode_segments
45
+ header = encoded_header
46
+ payload = encoded_payload
47
+ signature = encoded_signature([header, payload].join('.'))
48
+ [header, payload, signature].join('.')
49
+ end
50
+ end
51
+ end
data/lib/jwt/error.rb CHANGED
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module JWT
4
+ class EncodeError < StandardError; end
3
5
  class DecodeError < StandardError; end
4
6
  class VerificationError < DecodeError; end
5
7
  class ExpiredSignature < DecodeError; end