json_web_token 0.1.1 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +5 -0
- data/Gemfile +1 -0
- data/README.md +5 -3
- data/json_web_token.gemspec +1 -1
- data/lib/json_web_token.rb +2 -2
- data/lib/json_web_token/algorithm/ecdsa.rb +28 -13
- data/lib/json_web_token/algorithm/hmac.rb +26 -10
- data/lib/json_web_token/algorithm/rsa.rb +21 -9
- data/lib/json_web_token/format/base64_url.rb +19 -20
- data/lib/json_web_token/jwa.rb +30 -13
- data/lib/json_web_token/jws.rb +50 -23
- data/lib/json_web_token/jwt.rb +31 -12
- data/lib/json_web_token/util.rb +1 -1
- data/lib/json_web_token/version.rb +1 -1
- data/spec/json_web_token/algorithm/ecdsa_spec.rb +17 -17
- data/spec/json_web_token/algorithm/hmac_spec.rb +44 -45
- data/spec/json_web_token/algorithm/rsa_spec.rb +21 -23
- data/spec/json_web_token/jwa_spec.rb +16 -17
- data/spec/json_web_token/jws_spec.rb +40 -32
- data/spec/json_web_token/jwt_spec.rb +55 -45
- data/spec/json_web_token/util_spec.rb +6 -6
- data/spec/json_web_token_spec.rb +1 -1
- data/spec/support/plausible_jwt.rb +1 -1
- metadata +4 -3
@@ -4,12 +4,12 @@ require 'support/ecdsa_key'
|
|
4
4
|
module JsonWebToken
|
5
5
|
describe Jws do
|
6
6
|
context 'w payload' do
|
7
|
-
let(:payload) { '
|
8
|
-
context '#
|
9
|
-
shared_examples_for '
|
10
|
-
it '
|
11
|
-
jws = Jws.
|
12
|
-
expect(Jws.
|
7
|
+
let(:payload) { '{"iss":"joe","exp":1300819380,"http://example.com/is_root":true}' }
|
8
|
+
context '#sign' do
|
9
|
+
shared_examples_for 'does #verify' do
|
10
|
+
it 'w a jws' do
|
11
|
+
jws = Jws.sign(header, payload, signing_key)
|
12
|
+
expect(Jws.verify jws, algorithm, verifying_key).to eql jws
|
13
13
|
end
|
14
14
|
end
|
15
15
|
|
@@ -18,23 +18,31 @@ module JsonWebToken
|
|
18
18
|
let(:verifying_key) { signing_key }
|
19
19
|
context "w HS256 'alg' header parameter" do
|
20
20
|
let(:header) { {alg: 'HS256'} }
|
21
|
-
|
21
|
+
context 'w passing a matching algorithm to #verify' do
|
22
22
|
let(:algorithm) { 'HS256' }
|
23
|
-
it_behaves_like '
|
23
|
+
it_behaves_like 'does #verify'
|
24
24
|
|
25
|
-
describe 'w/o passing key to #
|
25
|
+
describe 'w/o passing key to #verify' do
|
26
26
|
it "returns 'Invalid'" do
|
27
|
-
jws = Jws.
|
28
|
-
expect(Jws.
|
27
|
+
jws = Jws.sign(header, payload, signing_key)
|
28
|
+
expect(Jws.verify jws, algorithm, nil).to be false
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
describe 'w passing a changed key to #verify' do
|
33
|
+
let(:changed_key) { 'gZH75aKtMN3Yj0iPS4hcgUuTwjAzZr9Z' }
|
34
|
+
it "returns 'Invalid'" do
|
35
|
+
jws = Jws.sign(header, payload, signing_key)
|
36
|
+
expect(Jws.verify jws, algorithm, changed_key).to be false
|
29
37
|
end
|
30
38
|
end
|
31
39
|
end
|
32
40
|
|
33
|
-
describe 'w/o passing a matching algorithm to #
|
41
|
+
describe 'w/o passing a matching algorithm to #verify' do
|
34
42
|
let(:algorithm) { 'RS256' }
|
35
43
|
it 'raises' do
|
36
|
-
jws = Jws.
|
37
|
-
expect { Jws.
|
44
|
+
jws = Jws.sign(header, payload, signing_key)
|
45
|
+
expect { Jws.verify(jws, algorithm, verifying_key) }
|
38
46
|
.to raise_error(RuntimeError, "Algorithm not matching 'alg' header parameter")
|
39
47
|
end
|
40
48
|
end
|
@@ -46,35 +54,35 @@ module JsonWebToken
|
|
46
54
|
let(:verifying_key) { signing_key.public_key }
|
47
55
|
context "w RS256 'alg' header parameter" do
|
48
56
|
let(:header) { {alg: 'RS256'} }
|
49
|
-
describe 'w passing a matching algorithm to #
|
57
|
+
describe 'w passing a matching algorithm to #verify' do
|
50
58
|
let(:algorithm) { 'RS256' }
|
51
|
-
it_behaves_like '
|
59
|
+
it_behaves_like 'does #verify'
|
52
60
|
end
|
53
61
|
end
|
54
62
|
end
|
55
63
|
|
56
64
|
context "w ES256 'alg' header parameter" do
|
57
65
|
let(:header) { {alg: 'ES256'} }
|
58
|
-
describe 'w passing a matching algorithm to #
|
66
|
+
describe 'w passing a matching algorithm to #verify' do
|
59
67
|
let(:algorithm) { 'ES256' }
|
60
|
-
it '
|
68
|
+
it 'w a jws' do
|
61
69
|
private_key = EcdsaKey.curve_new('256')
|
62
70
|
public_key_str = EcdsaKey.public_key_str(private_key)
|
63
71
|
public_key = EcdsaKey.public_key_new('256', public_key_str)
|
64
72
|
|
65
|
-
jws = Jws.
|
66
|
-
expect(Jws.
|
73
|
+
jws = Jws.sign(header, payload, private_key)
|
74
|
+
expect(Jws.verify jws, algorithm, public_key).to eql jws
|
67
75
|
end
|
68
76
|
end
|
69
77
|
end
|
70
78
|
end
|
71
79
|
|
72
80
|
context 'header validation' do
|
73
|
-
let(:signing_key) { '
|
81
|
+
let(:signing_key) { 'gZH75aKtMN3Yj0iPS4hcgUuTwjAzZr9C' }
|
74
82
|
describe "w/o a recognized 'alg' header parameter" do
|
75
83
|
let(:header) { {alg: 'HS257'} }
|
76
84
|
it 'raises' do
|
77
|
-
expect { Jws.
|
85
|
+
expect { Jws.sign(header, payload, signing_key) }
|
78
86
|
.to raise_error(RuntimeError, 'Unrecognized algorithm')
|
79
87
|
end
|
80
88
|
end
|
@@ -82,29 +90,29 @@ module JsonWebToken
|
|
82
90
|
describe "w/o a required 'alg' header parameter" do
|
83
91
|
let(:header) { {typ: 'JWT'} }
|
84
92
|
it 'raises' do
|
85
|
-
expect { Jws.
|
93
|
+
expect { Jws.sign(header, payload, signing_key) }
|
86
94
|
.to raise_error(RuntimeError, "Missing required 'alg' header parameter")
|
87
95
|
end
|
88
96
|
end
|
89
97
|
end
|
90
98
|
|
91
|
-
context '#
|
99
|
+
context '#unsecured_message' do
|
92
100
|
context 'w valid header' do
|
93
101
|
let(:header) { {alg: 'none'} }
|
94
|
-
describe 'w passing a matching algorithm to #
|
102
|
+
describe 'w passing a matching algorithm to #verify' do
|
95
103
|
let(:algorithm) { 'none' }
|
96
|
-
it '
|
97
|
-
jws = Jws.
|
98
|
-
expect(Jws.
|
104
|
+
it 'w a jws' do
|
105
|
+
jws = Jws.unsecured_message(header, payload)
|
106
|
+
expect(Jws.verify jws, algorithm).to eql jws
|
99
107
|
end
|
100
108
|
end
|
101
109
|
|
102
|
-
describe 'w/o passing a matching algorithm to #
|
110
|
+
describe 'w/o passing a matching algorithm to #verify' do
|
103
111
|
let(:algorithm) { 'HS256' }
|
104
112
|
let(:verifying_key) { 'gZH75aKtMN3Yj0iPS4hcgUuTwjAzZr9C' }
|
105
113
|
it 'raises' do
|
106
|
-
jws = Jws.
|
107
|
-
expect { Jws.
|
114
|
+
jws = Jws.unsecured_message(header, payload)
|
115
|
+
expect { Jws.verify(jws, algorithm, verifying_key) }
|
108
116
|
.to raise_error(RuntimeError, "Algorithm not matching 'alg' header parameter")
|
109
117
|
end
|
110
118
|
end
|
@@ -113,7 +121,7 @@ module JsonWebToken
|
|
113
121
|
describe 'w invalid header' do
|
114
122
|
let(:header) { {alg: 'HS256'} }
|
115
123
|
it 'raises' do
|
116
|
-
expect { Jws.
|
124
|
+
expect { Jws.unsecured_message(header, payload) }
|
117
125
|
.to raise_error(RuntimeError, "Invalid 'alg' header parameter")
|
118
126
|
end
|
119
127
|
end
|
@@ -4,71 +4,81 @@ require 'support/plausible_jwt'
|
|
4
4
|
|
5
5
|
module JsonWebToken
|
6
6
|
describe Jwt do
|
7
|
-
context '#
|
8
|
-
shared_examples_for '
|
9
|
-
it '
|
10
|
-
jwt = Jwt.
|
11
|
-
expect(Jwt.
|
7
|
+
context '#sign' do
|
8
|
+
shared_examples_for 'does #verify' do
|
9
|
+
it 'w a claims set' do
|
10
|
+
jwt = Jwt.sign(claims, sign_options)
|
11
|
+
expect(Jwt.verify jwt, verify_options).to include(claims)
|
12
12
|
end
|
13
13
|
end
|
14
14
|
|
15
|
-
shared_examples_for 'return
|
16
|
-
it 'plausible' do
|
17
|
-
jwt = Jwt.
|
15
|
+
shared_examples_for 'return a jwt' do
|
16
|
+
it 'that is plausible' do
|
17
|
+
jwt = Jwt.sign(claims, sign_options)
|
18
18
|
expect(plausible_message_signature? jwt).to be true
|
19
19
|
end
|
20
20
|
end
|
21
21
|
|
22
22
|
context 'w claims' do
|
23
|
-
let(:claims) { {exp: '
|
23
|
+
let(:claims) { { iss: 'joe', exp: 1300819380, 'http://example.com/is_root': true} }
|
24
24
|
context 'w HS256 keys' do
|
25
25
|
let(:signing_key) { 'gZH75aKtMN3Yj0iPS4hcgUuTwjAzZr9C' }
|
26
26
|
let(:verifying_key) { signing_key }
|
27
|
-
let(:
|
27
|
+
let(:verify_options) { {key: verifying_key} }
|
28
28
|
describe 'default header' do
|
29
|
-
let(:
|
30
|
-
it_behaves_like '
|
31
|
-
it_behaves_like 'return
|
29
|
+
let(:sign_options) { {key: signing_key} }
|
30
|
+
it_behaves_like 'does #verify'
|
31
|
+
it_behaves_like 'return a jwt'
|
32
32
|
end
|
33
33
|
|
34
34
|
describe 'w alg option' do
|
35
|
-
let(:
|
36
|
-
it_behaves_like '
|
37
|
-
it_behaves_like 'return
|
35
|
+
let(:sign_options) { {alg: 'HS256', key: signing_key} }
|
36
|
+
it_behaves_like 'does #verify'
|
37
|
+
it_behaves_like 'return a jwt'
|
38
38
|
end
|
39
39
|
|
40
40
|
describe 'w alg: nil option' do
|
41
|
-
let(:
|
42
|
-
it_behaves_like '
|
43
|
-
it_behaves_like 'return
|
41
|
+
let(:sign_options) { {alg: nil, key: signing_key} }
|
42
|
+
it_behaves_like 'does #verify'
|
43
|
+
it_behaves_like 'return a jwt'
|
44
44
|
end
|
45
45
|
|
46
46
|
describe "w alg empty string option" do
|
47
|
-
let(:
|
48
|
-
it_behaves_like '
|
49
|
-
it_behaves_like 'return
|
47
|
+
let(:sign_options) { {alg: '', key: signing_key} }
|
48
|
+
it_behaves_like 'does #verify'
|
49
|
+
it_behaves_like 'return a jwt'
|
50
50
|
end
|
51
51
|
|
52
52
|
describe "w alg: 'none' option" do
|
53
|
-
let(:
|
53
|
+
let(:sign_options) { {alg: 'none', key: signing_key} }
|
54
54
|
it 'raises' do
|
55
|
-
jwt = Jwt.
|
56
|
-
expect { Jwt.
|
55
|
+
jwt = Jwt.sign(claims, sign_options)
|
56
|
+
expect { Jwt.verify(jwt, verify_options) }
|
57
57
|
.to raise_error(RuntimeError, "Algorithm not matching 'alg' header parameter")
|
58
58
|
end
|
59
59
|
end
|
60
60
|
end
|
61
61
|
|
62
|
+
describe 'w HS256 key changed' do
|
63
|
+
let(:sign_options) { {alg: 'HS256', key: 'gZH75aKtMN3Yj0iPS4hcgUuTwjAzZr9C'} }
|
64
|
+
let(:changed_key) { 'gZH75aKtMN3Yj0iPS4hcgUuTwjAzZr9Z' }
|
65
|
+
let(:verify_options) { {key: verifying_key} }
|
66
|
+
it 'raises' do
|
67
|
+
jwt = Jwt.sign(claims, sign_options)
|
68
|
+
expect(Jwt.verify jwt, {key: changed_key}).to include(error: 'invalid')
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
62
72
|
context 'w RS256 keys' do
|
63
73
|
let(:signing_key) { OpenSSL::PKey::RSA.generate(2048) }
|
64
74
|
let(:verifying_key) { signing_key.public_key }
|
65
|
-
let(:
|
75
|
+
let(:verify_options) { {alg: 'RS256', key: verifying_key} }
|
66
76
|
describe 'passing matching options' do
|
67
|
-
let(:
|
68
|
-
it_behaves_like '
|
77
|
+
let(:sign_options) { {alg: 'RS256', key: signing_key} }
|
78
|
+
it_behaves_like 'does #verify'
|
69
79
|
|
70
80
|
it 'plausible' do
|
71
|
-
jwt = Jwt.
|
81
|
+
jwt = Jwt.sign(claims, sign_options)
|
72
82
|
expect(plausible_message_signature? jwt, 256).to be true
|
73
83
|
end
|
74
84
|
end
|
@@ -76,17 +86,17 @@ module JsonWebToken
|
|
76
86
|
|
77
87
|
context "w ES256 'alg' header parameter" do
|
78
88
|
let(:algorithm) { 'ES256' }
|
79
|
-
describe 'w passing a matching algorithm to #
|
89
|
+
describe 'w passing a matching algorithm to #verify' do
|
80
90
|
it 'is verified and plausible' do
|
81
91
|
private_key = EcdsaKey.curve_new('256')
|
82
92
|
public_key_str = EcdsaKey.public_key_str(private_key)
|
83
93
|
public_key = EcdsaKey.public_key_new('256', public_key_str)
|
84
94
|
|
85
|
-
|
86
|
-
jwt = Jwt.
|
95
|
+
sign_options = {alg: algorithm, key: private_key}
|
96
|
+
jwt = Jwt.sign(claims, sign_options)
|
87
97
|
|
88
|
-
|
89
|
-
expect(Jwt.
|
98
|
+
verify_options = {alg: algorithm, key: public_key}
|
99
|
+
expect(Jwt.verify jwt, verify_options).to include(claims)
|
90
100
|
|
91
101
|
expect(plausible_message_signature? jwt, 64).to be true
|
92
102
|
end
|
@@ -95,20 +105,20 @@ module JsonWebToken
|
|
95
105
|
|
96
106
|
context 'w/o key' do
|
97
107
|
context "w alg: 'none' header parameter" do
|
98
|
-
let(:
|
99
|
-
describe "w
|
100
|
-
let(:
|
101
|
-
it '
|
102
|
-
jwt = Jwt.
|
103
|
-
expect(Jwt.
|
104
|
-
expect(
|
108
|
+
let(:sign_options) { {alg: 'none'} }
|
109
|
+
describe "w verify alg: 'none'" do
|
110
|
+
let(:verify_options) { {alg: 'none'} }
|
111
|
+
it 'verifies a plausible unsecured jws' do
|
112
|
+
jwt = Jwt.sign(claims, sign_options)
|
113
|
+
expect(Jwt.verify jwt, verify_options).to include(claims)
|
114
|
+
expect(plausible_unsecured_message? jwt).to be true
|
105
115
|
end
|
106
116
|
end
|
107
117
|
|
108
|
-
describe 'w default
|
118
|
+
describe 'w default verify alg' do
|
109
119
|
it 'raises' do
|
110
|
-
jwt = Jwt.
|
111
|
-
expect { Jwt.
|
120
|
+
jwt = Jwt.sign(claims, sign_options)
|
121
|
+
expect { Jwt.verify(jwt) }
|
112
122
|
.to raise_error(RuntimeError, "Algorithm not matching 'alg' header parameter")
|
113
123
|
end
|
114
124
|
end
|
@@ -120,7 +130,7 @@ module JsonWebToken
|
|
120
130
|
let(:options) { {key: 'gZH75aKtMN3Yj0iPS4hcgUuTwjAzZr9C'} }
|
121
131
|
shared_examples_for 'w/o claims' do
|
122
132
|
it 'raises' do
|
123
|
-
expect { Jwt.
|
133
|
+
expect { Jwt.sign(claims, options) }
|
124
134
|
.to raise_error(RuntimeError, 'Claims blank')
|
125
135
|
end
|
126
136
|
end
|
@@ -2,14 +2,14 @@ require 'json_web_token/util'
|
|
2
2
|
|
3
3
|
module JsonWebToken
|
4
4
|
describe Util do
|
5
|
-
describe '#constant_time_compare' do
|
5
|
+
describe '#constant_time_compare?' do
|
6
6
|
it 'guards against empty or nil strings' do
|
7
|
-
expect(Util.constant_time_compare 'a', 'a').to be true
|
7
|
+
expect(Util.constant_time_compare? 'a', 'a').to be true
|
8
8
|
|
9
|
-
expect(Util.constant_time_compare 'a', 'b').to be false
|
10
|
-
expect(Util.constant_time_compare 'a', 'A').to be false
|
11
|
-
expect(Util.constant_time_compare '', '').to be false
|
12
|
-
expect(Util.constant_time_compare nil, nil).to be false
|
9
|
+
expect(Util.constant_time_compare? 'a', 'b').to be false
|
10
|
+
expect(Util.constant_time_compare? 'a', 'A').to be false
|
11
|
+
expect(Util.constant_time_compare? '', '').to be false
|
12
|
+
expect(Util.constant_time_compare? nil, nil).to be false
|
13
13
|
end
|
14
14
|
end
|
15
15
|
|
data/spec/json_web_token_spec.rb
CHANGED
@@ -37,7 +37,7 @@ describe JsonWebToken do
|
|
37
37
|
|
38
38
|
describe 'w/o key w default header alg' do
|
39
39
|
it 'raises' do
|
40
|
-
expect { JsonWebToken.create(claims) }.to raise_error(RuntimeError, 'Invalid key')
|
40
|
+
expect { JsonWebToken.create(claims) }.to raise_error(RuntimeError, 'Invalid shared key')
|
41
41
|
end
|
42
42
|
end
|
43
43
|
end
|
@@ -9,7 +9,7 @@ def plausible_message_signature?(str, bytesize = 32)
|
|
9
9
|
mac.bytesize == bytesize && mac.class == String
|
10
10
|
end
|
11
11
|
|
12
|
-
def
|
12
|
+
def plausible_unsecured_message?(str)
|
13
13
|
return false unless str.end_with?('.')
|
14
14
|
str.split('.').length == 2
|
15
15
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: json_web_token
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Gary Fleshman
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-
|
11
|
+
date: 2015-08-02 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: json
|
@@ -44,7 +44,7 @@ dependencies:
|
|
44
44
|
- - "~>"
|
45
45
|
- !ruby/object:Gem::Version
|
46
46
|
version: '3.3'
|
47
|
-
description: Ruby implementation of the JSON Web Token
|
47
|
+
description: Ruby implementation of the JSON Web Token standard, RFC 7519
|
48
48
|
email: gfleshman@newforge-tech.com
|
49
49
|
executables: []
|
50
50
|
extensions: []
|
@@ -108,3 +108,4 @@ signing_key:
|
|
108
108
|
specification_version: 4
|
109
109
|
summary: JSON Web Token for Ruby
|
110
110
|
test_files: []
|
111
|
+
has_rdoc:
|