json-jwt 0.0.2 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of json-jwt might be problematic. Click here for more details.

data/Gemfile.lock CHANGED
@@ -1,21 +1,15 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- json-jwt (0.0.1)
5
- activesupport (>= 2.3)
6
- i18n
4
+ json-jwt (0.0.2)
7
5
  json (>= 1.4.3)
8
6
  url_safe_base64
9
7
 
10
8
  GEM
11
9
  remote: http://rubygems.org/
12
10
  specs:
13
- activesupport (3.1.0)
14
- multi_json (~> 1.0)
15
11
  diff-lcs (1.1.3)
16
- i18n (0.6.0)
17
- json (1.6.0)
18
- multi_json (1.0.3)
12
+ json (1.6.1)
19
13
  rake (0.9.2)
20
14
  rcov (0.9.10)
21
15
  rspec (2.6.0)
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.0.2
1
+ 0.0.3
data/json-jwt.gemspec CHANGED
@@ -12,8 +12,6 @@ Gem::Specification.new do |s|
12
12
  s.require_paths = ["lib"]
13
13
  s.add_runtime_dependency "json", ">= 1.4.3"
14
14
  s.add_runtime_dependency "url_safe_base64"
15
- s.add_runtime_dependency "activesupport", ">= 2.3"
16
- s.add_runtime_dependency "i18n"
17
15
  s.add_development_dependency "rake", ">= 0.8"
18
16
  s.add_development_dependency "rcov", ">= 0.9"
19
17
  s.add_development_dependency "rspec", ">= 2"
data/lib/json/jws.rb CHANGED
@@ -14,14 +14,30 @@ module JSON
14
14
  end
15
15
 
16
16
  def verify(signature_base_string, signature, public_key_or_secret)
17
- sign(signature_base_string, public_key_or_secret) == signature or
17
+ valid?(signature_base_string, signature, public_key_or_secret) or
18
18
  raise VerificationFailed
19
19
  end
20
20
 
21
21
  private
22
22
 
23
23
  def algorithm
24
- @header[:alg]
24
+ header[:alg] || header['alg']
25
+ end
26
+
27
+ def digest
28
+ OpenSSL::Digest::Digest.new "SHA#{algorithm.to_s[2, 3]}"
29
+ end
30
+
31
+ def hmac?
32
+ [:HS256, :HS384, :HS512].collect(&:to_s).include? algorithm.to_s
33
+ end
34
+
35
+ def rsa?
36
+ [:RS256, :RS384, :RS512].collect(&:to_s).include? algorithm.to_s
37
+ end
38
+
39
+ def ecdsa?
40
+ [:ES256, :ES384, :ES512].collect(&:to_s).include? algorithm.to_s
25
41
  end
26
42
 
27
43
  def signature_base_string
@@ -34,15 +50,30 @@ module JSON
34
50
  end
35
51
 
36
52
  def sign(signature_base_string, private_key_or_secret)
37
- digest = OpenSSL::Digest::Digest.new "SHA#{algorithm.to_s[2, 3]}"
38
- case algorithm
39
- when :HS256, :HS384, :HS512
53
+ case
54
+ when hmac?
40
55
  secret = private_key_or_secret
41
56
  OpenSSL::HMAC.digest digest, secret, signature_base_string
42
- when :RS256, :RS384, :RS512
57
+ when rsa?
43
58
  private_key = private_key_or_secret
44
59
  private_key.sign digest, signature_base_string
45
- when :ES256, :ES384, :ES512
60
+ when ecdsa?
61
+ # TODO
62
+ raise NotImplementedError.new
63
+ else
64
+ raise InvalidFormat.new('Unknown Signature Algorithm')
65
+ end
66
+ end
67
+
68
+ def valid?(signature_base_string, signature, public_key_or_secret)
69
+ case
70
+ when hmac?
71
+ secret = public_key_or_secret
72
+ sign(signature_base_string, secret) == signature
73
+ when rsa?
74
+ public_key = public_key_or_secret
75
+ public_key.verify digest, signature, signature_base_string
76
+ when ecdsa?
46
77
  # TODO
47
78
  raise NotImplementedError.new
48
79
  else
data/lib/json/jwt.rb CHANGED
@@ -26,12 +26,12 @@ module JSON
26
26
  JWS.new(self).sign!(private_key_or_secret)
27
27
  end
28
28
 
29
- def verify(signature_base_string, signature = '', prublic_key_or_secret = nil)
29
+ def verify(signature_base_string, signature = '', public_key_or_secret = nil)
30
30
  case header[:alg]
31
31
  when :none
32
32
  signature == '' or raise VerificationFailed
33
33
  else
34
- JWS.new(self).verify(signature_base_string, signature, prublic_key_or_secret)
34
+ JWS.new(self).verify(signature_base_string, signature, public_key_or_secret)
35
35
  end
36
36
  end
37
37
 
@@ -51,9 +51,10 @@ module JSON
51
51
  header, claims, signature = jwt_string.split('.').collect do |segment|
52
52
  UrlSafeBase64.decode64 segment.to_s
53
53
  end
54
- jwt = new JSON.parse(claims).with_indifferent_access
55
- jwt.header = JSON.parse(header).with_indifferent_access
56
- jwt.verify [header, claims].join('.'), signature, public_key_or_secret
54
+ signature_base_string = jwt_string.split('.')[0,2].join('.')
55
+ jwt = new JSON.parse(claims)
56
+ jwt.header = JSON.parse header
57
+ jwt.verify signature_base_string, signature, public_key_or_secret
57
58
  jwt
58
59
  rescue JSON::ParserError
59
60
  raise InvalidFormat.new("Invalid JSON Format")
@@ -8,6 +8,8 @@ describe JSON::JWS do
8
8
  _jwt_
9
9
  end
10
10
  let(:jws) { JSON::JWS.new jwt }
11
+ let(:signed) { jws.sign! private_key_or_secret }
12
+ let(:decoded) { JSON::JWT.decode signed.to_s, public_key_or_secret }
11
13
  let(:claims) do
12
14
  {
13
15
  :iss => 'joe',
@@ -15,6 +17,19 @@ describe JSON::JWS do
15
17
  'http://example.com/is_root' => true
16
18
  }
17
19
  end
20
+ let(:expected_signature) {
21
+ {
22
+ :HS256 => 'DyuTgO2Ggb5nrhkkhI-RjVYIBe3o8oL4ijkAn94YPxQ',
23
+ :HS384 => 'a5-7rr61TG8Snv9xxJ7l064ky-SCq1Mswe9t8HEorvoc_nnfIeUy9WQCLMIli34R',
24
+ :HS512 => 'ce-GlHDaNwaHfmAFRGp3QPPKvrpruTug2hC1bf6yNlbuvkMwJw2jFZgq_4wmIPetRdiBy7XFq7rrtmw1Im7tmQ',
25
+ :RS256 => 'E5VELqAdla2Bx1axc9KFxO0EiCr0Mw6HPYX070qGQ8zA_XmyxGPUZLyyWU_6Cn399W-oYBWO2ynLlr8pqqjP3jXevyCeYeGRVN0HzLYiBebEugNnc3hevr7WV2UzfksWRA-Ux2bDv2sz9p_LGbL33wWNxGDvIlpDyZUul_a48nCipS0riBjkTLTSE8dfBxQTXEF5GEUUu99ot6aBLzUhc25nHXSXogXF6MHK-hAcE7f4v-vJ0lbPbHLVGUopIoxoqe4XjoBpzE5UvhrVl5LYbdjbyJhu5ZIA8GLsgwtUFh3dfdIechORoR3k5NSFSv8157bAEa8t4iwgWD2MSNSQnw',
26
+ :RS384 => 'lT5JbytGKgG9QrwkJuxgw7UjmN9tjkEQW9pVGR2XnKEdC0_wLNIzAmT-jTwyMDGBLUkWO7opDOP6Xy6_DOTg58k9PwVkyQzrLnmxJMEng2Q-aMqcitRSIvUk3DPy8kemp8yUPls9NzWmByM2GoUVHbDsR0r-tZN-g_9QYev32mvMhjMr30JI5S2xiRjc9m2GAaXMOQmNTovJgV4bgCp4UjruCrA0BD1JJwDqKYoR_YYr_ALcVjD_LUgy80udJvbi8MAYJVUf0QYtQDrX2wnT_-eiiWjD5XafLuXEQVDRh-v2MKAwdvtXMq5cZ08Zjl2SyHxJ3OqhEeWPvYGltxZh_A',
27
+ :RS512 => 'EHeGM2Mo3ghhUfSB99AlREehrbC6OPE-nYL_rwf88ysTnJ8L1QQ0UuCrXq4SpRutGLK_bYTK3ZALvFRPoOgK_g0QWmqv6qjQRU_QTxoq8y8APP-IgKKDuIiGH6daBV2rAPLDReqYNKsKjmTvZJo2c0a0e_WZkkj_ZwpgjTG3v0gW9lbDAzLJDz18eqtR4ZO7JTu_fyNrUrNk-w2_wpxSsn9sygIMp0lKE0_pt0b01fz3gjTDjlltU0cKSalUp4geaBDH7QRcexrolIctdQFbNKTXQxoigxD3NLNkKGH7f6A8KZdcOm8AnEjullcZs8_OWGnW43p1qrxoBRSivb9pqQ',
28
+ :ES256 => :TODO,
29
+ :ES384 => :TODO,
30
+ :ES512 => :TODO
31
+ }
32
+ }
18
33
 
19
34
  shared_examples_for :jwt_with_alg do
20
35
  it { should == jwt }
@@ -28,44 +43,79 @@ describe JSON::JWS do
28
43
  end
29
44
 
30
45
  describe '#sign!' do
31
- shared_examples_for :jwt_with_expected_signature do
32
- it 'should generate expected signature' do
46
+ shared_examples_for :generate_expected_signature do
47
+ it do
33
48
  UrlSafeBase64.encode64(signed.signature).should == expected_signature[alg]
34
49
  end
35
50
  end
36
- let(:expected_signature) {
37
- {
38
- :HS256 => 'DyuTgO2Ggb5nrhkkhI-RjVYIBe3o8oL4ijkAn94YPxQ',
39
- :HS384 => 'a5-7rr61TG8Snv9xxJ7l064ky-SCq1Mswe9t8HEorvoc_nnfIeUy9WQCLMIli34R',
40
- :HS512 => 'ce-GlHDaNwaHfmAFRGp3QPPKvrpruTug2hC1bf6yNlbuvkMwJw2jFZgq_4wmIPetRdiBy7XFq7rrtmw1Im7tmQ',
41
- :RS256 => 'E5VELqAdla2Bx1axc9KFxO0EiCr0Mw6HPYX070qGQ8zA_XmyxGPUZLyyWU_6Cn399W-oYBWO2ynLlr8pqqjP3jXevyCeYeGRVN0HzLYiBebEugNnc3hevr7WV2UzfksWRA-Ux2bDv2sz9p_LGbL33wWNxGDvIlpDyZUul_a48nCipS0riBjkTLTSE8dfBxQTXEF5GEUUu99ot6aBLzUhc25nHXSXogXF6MHK-hAcE7f4v-vJ0lbPbHLVGUopIoxoqe4XjoBpzE5UvhrVl5LYbdjbyJhu5ZIA8GLsgwtUFh3dfdIechORoR3k5NSFSv8157bAEa8t4iwgWD2MSNSQnw',
42
- :RS384 => 'lT5JbytGKgG9QrwkJuxgw7UjmN9tjkEQW9pVGR2XnKEdC0_wLNIzAmT-jTwyMDGBLUkWO7opDOP6Xy6_DOTg58k9PwVkyQzrLnmxJMEng2Q-aMqcitRSIvUk3DPy8kemp8yUPls9NzWmByM2GoUVHbDsR0r-tZN-g_9QYev32mvMhjMr30JI5S2xiRjc9m2GAaXMOQmNTovJgV4bgCp4UjruCrA0BD1JJwDqKYoR_YYr_ALcVjD_LUgy80udJvbi8MAYJVUf0QYtQDrX2wnT_-eiiWjD5XafLuXEQVDRh-v2MKAwdvtXMq5cZ08Zjl2SyHxJ3OqhEeWPvYGltxZh_A',
43
- :RS512 => 'EHeGM2Mo3ghhUfSB99AlREehrbC6OPE-nYL_rwf88ysTnJ8L1QQ0UuCrXq4SpRutGLK_bYTK3ZALvFRPoOgK_g0QWmqv6qjQRU_QTxoq8y8APP-IgKKDuIiGH6daBV2rAPLDReqYNKsKjmTvZJo2c0a0e_WZkkj_ZwpgjTG3v0gW9lbDAzLJDz18eqtR4ZO7JTu_fyNrUrNk-w2_wpxSsn9sygIMp0lKE0_pt0b01fz3gjTDjlltU0cKSalUp4geaBDH7QRcexrolIctdQFbNKTXQxoigxD3NLNkKGH7f6A8KZdcOm8AnEjullcZs8_OWGnW43p1qrxoBRSivb9pqQ',
44
- :ES256 => :TODO,
45
- :ES384 => :TODO,
46
- :ES512 => :TODO
47
- }
48
- }
49
- let(:signed) do
50
- jws.sign! key
51
- end
52
51
  subject { signed }
53
52
 
54
53
  [:HS256, :HS384, :HS512].each do |algorithm|
55
54
  describe algorithm do
56
- let(:key) { shared_secret }
55
+ let(:private_key_or_secret) { shared_secret }
57
56
  let(:alg) { algorithm }
58
57
  it_behaves_like :jwt_with_alg
59
- it_behaves_like :jwt_with_expected_signature
58
+ it_behaves_like :generate_expected_signature
60
59
  end
61
60
  end
62
61
 
63
62
  [:RS256, :RS384, :RS512].each do |algorithm|
64
63
  describe algorithm do
65
- let(:key) { private_key }
64
+ let(:private_key_or_secret) { private_key }
66
65
  let(:alg) { algorithm }
67
66
  it_behaves_like :jwt_with_alg
68
- it_behaves_like :jwt_with_expected_signature
67
+ it_behaves_like :generate_expected_signature
68
+ end
69
+ end
70
+
71
+ [:ES256, :ES384, :ES512].each do |algorithm|
72
+ describe algorithm do
73
+ let(:alg) { algorithm }
74
+ it :TODO
75
+ end
76
+ end
77
+ end
78
+
79
+ describe '#verify' do
80
+ shared_examples_for :succes_signature_verification do
81
+ it do
82
+ expect { decoded }.should_not raise_error
83
+ decoded.should be_a JSON::JWT
84
+ end
85
+
86
+ describe 'header' do
87
+ let(:header) { decoded.header }
88
+ it 'should be parsed successfully' do
89
+ header['typ'].should == 'JWT'
90
+ header['alg'].should == alg.to_s
91
+ end
92
+ end
93
+
94
+ describe 'claims' do
95
+ it 'should be parsed successfully' do
96
+ decoded['iss'].should == 'joe'
97
+ decoded['exp'].should == 1300819380
98
+ decoded['http://example.com/is_root'] == true
99
+ end
100
+ end
101
+ end
102
+ subject { decoded }
103
+
104
+ [:HS256, :HS384, :HS512].each do |algorithm|
105
+ describe algorithm do
106
+ let(:private_key_or_secret) { shared_secret }
107
+ let(:public_key_or_secret) { shared_secret }
108
+ let(:alg) { algorithm }
109
+ it_behaves_like :succes_signature_verification
110
+ end
111
+ end
112
+
113
+ [:RS256, :RS384, :RS512].each do |algorithm|
114
+ describe algorithm do
115
+ let(:private_key_or_secret) { private_key }
116
+ let(:public_key_or_secret) { public_key }
117
+ let(:alg) { algorithm }
118
+ it_behaves_like :succes_signature_verification
69
119
  end
70
120
  end
71
121
 
metadata CHANGED
@@ -2,7 +2,7 @@
2
2
  name: json-jwt
3
3
  version: !ruby/object:Gem::Version
4
4
  prerelease:
5
- version: 0.0.2
5
+ version: 0.0.3
6
6
  platform: ruby
7
7
  authors:
8
8
  - nov matake
@@ -34,61 +34,39 @@ dependencies:
34
34
  version: "0"
35
35
  type: :runtime
36
36
  version_requirements: *id002
37
- - !ruby/object:Gem::Dependency
38
- name: activesupport
39
- prerelease: false
40
- requirement: &id003 !ruby/object:Gem::Requirement
41
- none: false
42
- requirements:
43
- - - ">="
44
- - !ruby/object:Gem::Version
45
- version: "2.3"
46
- type: :runtime
47
- version_requirements: *id003
48
- - !ruby/object:Gem::Dependency
49
- name: i18n
50
- prerelease: false
51
- requirement: &id004 !ruby/object:Gem::Requirement
52
- none: false
53
- requirements:
54
- - - ">="
55
- - !ruby/object:Gem::Version
56
- version: "0"
57
- type: :runtime
58
- version_requirements: *id004
59
37
  - !ruby/object:Gem::Dependency
60
38
  name: rake
61
39
  prerelease: false
62
- requirement: &id005 !ruby/object:Gem::Requirement
40
+ requirement: &id003 !ruby/object:Gem::Requirement
63
41
  none: false
64
42
  requirements:
65
43
  - - ">="
66
44
  - !ruby/object:Gem::Version
67
45
  version: "0.8"
68
46
  type: :development
69
- version_requirements: *id005
47
+ version_requirements: *id003
70
48
  - !ruby/object:Gem::Dependency
71
49
  name: rcov
72
50
  prerelease: false
73
- requirement: &id006 !ruby/object:Gem::Requirement
51
+ requirement: &id004 !ruby/object:Gem::Requirement
74
52
  none: false
75
53
  requirements:
76
54
  - - ">="
77
55
  - !ruby/object:Gem::Version
78
56
  version: "0.9"
79
57
  type: :development
80
- version_requirements: *id006
58
+ version_requirements: *id004
81
59
  - !ruby/object:Gem::Dependency
82
60
  name: rspec
83
61
  prerelease: false
84
- requirement: &id007 !ruby/object:Gem::Requirement
62
+ requirement: &id005 !ruby/object:Gem::Requirement
85
63
  none: false
86
64
  requirements:
87
65
  - - ">="
88
66
  - !ruby/object:Gem::Version
89
67
  version: "2"
90
68
  type: :development
91
- version_requirements: *id007
69
+ version_requirements: *id005
92
70
  description: JSON Web Token and its family (JSON Web Signature, JSON Web Encryption and JSON Web Key) in Ruby
93
71
  email:
94
72
  - nov@matake.jp