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 +4 -4
- data/.ebert.yml +17 -0
- data/.reek.yml +40 -0
- data/.rubocop.yml +96 -0
- data/.travis.yml +9 -8
- data/CHANGELOG.md +82 -1
- data/Gemfile +0 -1
- data/README.md +71 -8
- data/lib/jwt/decode.rb +21 -29
- data/lib/jwt/default_options.rb +14 -0
- data/lib/jwt/encode.rb +51 -0
- data/lib/jwt/error.rb +2 -0
- data/lib/jwt/security_utils.rb +52 -0
- data/lib/jwt/signature.rb +106 -0
- data/lib/jwt/verify.rb +48 -53
- data/lib/jwt/version.rb +3 -3
- data/lib/jwt.rb +28 -159
- data/ruby-jwt.gemspec +4 -3
- data/spec/integration/readme_examples_spec.rb +20 -8
- data/spec/jwt/verify_spec.rb +64 -42
- data/spec/jwt_spec.rb +49 -32
- data/spec/spec_helper.rb +4 -7
- metadata +33 -15
- data/lib/jwt/json.rb +0 -17
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c63d3d103ec14f12ea2b51b95ae8f5407dd7ace9
|
4
|
+
data.tar.gz: f1de3f1e8ddfb79aa690a1f6d44492c70d037942
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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:
|
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
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
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
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
|
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
|
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
|
-
# {"
|
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
|
-
# {"
|
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
|
-
# {"
|
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
|
-
# {"
|
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, { :
|
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, { :
|
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
|
-
|
3
|
-
require '
|
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
|
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
|
-
@
|
18
|
-
@
|
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
|
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
|
-
|
30
|
-
|
31
|
-
|
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 =
|
39
|
-
payload =
|
42
|
+
header = JSON.parse(Decode.base64url_decode(header_segment))
|
43
|
+
payload = JSON.parse(Decode.base64url_decode(payload_segment))
|
40
44
|
[header, payload]
|
41
|
-
|
42
|
-
|
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
|