jwt 1.4.0 → 1.4.1

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: 22e5c1eafdf6a7e80397bbca142c3bff69524b21
4
- data.tar.gz: e7acda6c7609412c393a5ebb29e575cb82618f9f
3
+ metadata.gz: cdfac4049ccdded9be1f09b66e5af478ef37fc4d
4
+ data.tar.gz: af9de309fd5e3a80c94c28003b203c7776782591
5
5
  SHA512:
6
- metadata.gz: f897824dd5f6ccc196f16c9944914c14ca0d476d9bc030bc8872ad7e2c5234a3db907ee35b780715689549fe397a4e76521b0e3d06d37f2b06d890cbcf855633
7
- data.tar.gz: aec0e48a68cee3b5694d97f47aa0b3721ac2eee8a82b038c172c884d3ccfc1ade1728a4d4bf92d7cedd2d8bca9273cb180a14fb4ee306b01e981b2e752341515
6
+ metadata.gz: 175bb4f9a775da249f7d3825469d8970f6c2d0d2e78316f2f152be4c2446062d9480d9f0ca6033f2f7c109da9f4d5d6ec56c14386dba0024cc62c4d68d565c54
7
+ data.tar.gz: ca034a2e46c9cbac727a8822fc0c170d2adf04799cc6e698cfe2dc6e014507726d32a939bb4e87739518aca7d60660afc13cfa09a7bc9a6cce30248d7e76be61
data/Rakefile CHANGED
@@ -2,16 +2,16 @@ require 'rubygems'
2
2
  require 'rake'
3
3
  require 'echoe'
4
4
 
5
- Echoe.new('jwt', '1.4.0') do |p|
6
- p.description = "JSON Web Token implementation in Ruby"
7
- p.url = "http://github.com/progrium/ruby-jwt"
8
- p.author = "Jeff Lindsay"
9
- p.email = "progrium@gmail.com"
10
- p.ignore_pattern = ["tmp/*"]
11
- p.development_dependencies = ["echoe >=4.6.3"]
12
- p.licenses = "MIT"
5
+ Echoe.new('jwt', '1.4.1') do |p|
6
+ p.description = 'JSON Web Token implementation in Ruby'
7
+ p.url = 'http://github.com/progrium/ruby-jwt'
8
+ p.author = 'Jeff Lindsay'
9
+ p.email = 'progrium@gmail.com'
10
+ p.ignore_pattern = ['tmp/*']
11
+ p.development_dependencies = ['echoe >=4.6.3']
12
+ p.licenses = 'MIT'
13
13
  end
14
14
 
15
15
  task :test do
16
- sh "rspec spec/jwt_spec.rb"
16
+ sh 'rspec spec/jwt_spec.rb'
17
17
  end
@@ -1,14 +1,14 @@
1
1
  # -*- encoding: utf-8 -*-
2
- # stub: jwt 1.4.0 ruby lib
2
+ # stub: jwt 1.4.1 ruby lib
3
3
 
4
4
  Gem::Specification.new do |s|
5
5
  s.name = "jwt"
6
- s.version = "1.4.0"
6
+ s.version = "1.4.1"
7
7
 
8
8
  s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
9
9
  s.require_paths = ["lib"]
10
10
  s.authors = ["Jeff Lindsay"]
11
- s.date = "2015-03-10"
11
+ s.date = "2015-03-12"
12
12
  s.description = "JSON Web Token implementation in Ruby"
13
13
  s.email = "progrium@gmail.com"
14
14
  s.extra_rdoc_files = ["lib/jwt.rb", "lib/jwt/json.rb"]
data/lib/jwt.rb CHANGED
@@ -4,9 +4,9 @@
4
4
  # Should be up to date with the latest spec:
5
5
  # http://self-issued.info/docs/draft-jones-json-web-token-06.html
6
6
 
7
- require "base64"
8
- require "openssl"
9
- require "jwt/json"
7
+ require 'base64'
8
+ require 'openssl'
9
+ require 'jwt/json'
10
10
 
11
11
  module JWT
12
12
  class DecodeError < StandardError; end
@@ -23,38 +23,38 @@ module JWT
23
23
  module_function
24
24
 
25
25
  def sign(algorithm, msg, key)
26
- if ["HS256", "HS384", "HS512"].include?(algorithm)
26
+ if ['HS256', 'HS384', 'HS512'].include?(algorithm)
27
27
  sign_hmac(algorithm, msg, key)
28
- elsif ["RS256", "RS384", "RS512"].include?(algorithm)
28
+ elsif ['RS256', 'RS384', 'RS512'].include?(algorithm)
29
29
  sign_rsa(algorithm, msg, key)
30
30
  else
31
- raise NotImplementedError.new("Unsupported signing method")
31
+ raise NotImplementedError.new('Unsupported signing method')
32
32
  end
33
33
  end
34
34
 
35
35
  def sign_rsa(algorithm, msg, private_key)
36
- private_key.sign(OpenSSL::Digest.new(algorithm.sub("RS", "sha")), msg)
36
+ private_key.sign(OpenSSL::Digest.new(algorithm.sub('RS', 'sha')), msg)
37
37
  end
38
38
 
39
39
  def verify_rsa(algorithm, public_key, signing_input, signature)
40
- public_key.verify(OpenSSL::Digest.new(algorithm.sub("RS", "sha")), signature, signing_input)
40
+ public_key.verify(OpenSSL::Digest.new(algorithm.sub('RS', 'sha')), signature, signing_input)
41
41
  end
42
42
 
43
43
  def sign_hmac(algorithm, msg, key)
44
- OpenSSL::HMAC.digest(OpenSSL::Digest.new(algorithm.sub("HS", "sha")), key, msg)
44
+ OpenSSL::HMAC.digest(OpenSSL::Digest.new(algorithm.sub('HS', 'sha')), key, msg)
45
45
  end
46
46
 
47
47
  def base64url_decode(str)
48
- str += "=" * (4 - str.length.modulo(4))
49
- Base64.decode64(str.tr("-_", "+/"))
48
+ str += '=' * (4 - str.length.modulo(4))
49
+ Base64.decode64(str.tr('-_', '+/'))
50
50
  end
51
51
 
52
52
  def base64url_encode(str)
53
- Base64.encode64(str).tr("+/", "-_").gsub(/[\n=]/, "")
53
+ Base64.encode64(str).tr('+/', '-_').gsub(/[\n=]/, '')
54
54
  end
55
55
 
56
- def encoded_header(algorithm="HS256", header_fields={})
57
- header = {"typ" => "JWT", "alg" => algorithm}.merge(header_fields)
56
+ def encoded_header(algorithm='HS256', header_fields={})
57
+ header = {'typ' => 'JWT', 'alg' => algorithm}.merge(header_fields)
58
58
  base64url_encode(encode_json(header))
59
59
  end
60
60
 
@@ -63,27 +63,27 @@ module JWT
63
63
  end
64
64
 
65
65
  def encoded_signature(signing_input, key, algorithm)
66
- if algorithm == "none"
67
- ""
66
+ if algorithm == 'none'
67
+ ''
68
68
  else
69
69
  signature = sign(algorithm, signing_input, key)
70
70
  base64url_encode(signature)
71
71
  end
72
72
  end
73
73
 
74
- def encode(payload, key, algorithm="HS256", header_fields={})
75
- algorithm ||= "none"
74
+ def encode(payload, key, algorithm='HS256', header_fields={})
75
+ algorithm ||= 'none'
76
76
  segments = []
77
77
  segments << encoded_header(algorithm, header_fields)
78
78
  segments << encoded_payload(payload)
79
- segments << encoded_signature(segments.join("."), key, algorithm)
80
- segments.join(".")
79
+ segments << encoded_signature(segments.join('.'), key, algorithm)
80
+ segments.join('.')
81
81
  end
82
82
 
83
83
  def raw_segments(jwt, verify=true)
84
- segments = jwt.split(".")
84
+ segments = jwt.split('.')
85
85
  required_num_segments = verify ? [3] : [2,3]
86
- raise JWT::DecodeError.new("Not enough or too many segments") unless required_num_segments.include? segments.length
86
+ raise JWT::DecodeError.new('Not enough or too many segments') unless required_num_segments.include? segments.length
87
87
  segments
88
88
  end
89
89
 
@@ -97,24 +97,24 @@ module JWT
97
97
  header_segment, payload_segment, crypto_segment = raw_segments(jwt, verify)
98
98
  header, payload = decode_header_and_payload(header_segment, payload_segment)
99
99
  signature = base64url_decode(crypto_segment.to_s) if verify
100
- signing_input = [header_segment, payload_segment].join(".")
100
+ signing_input = [header_segment, payload_segment].join('.')
101
101
  [header, payload, signature, signing_input]
102
102
  end
103
103
 
104
104
  def decode(jwt, key=nil, verify=true, options={}, &keyfinder)
105
- raise JWT::DecodeError.new("Nil JSON web token") unless jwt
105
+ raise JWT::DecodeError.new('Nil JSON web token') unless jwt
106
106
 
107
107
  header, payload, signature, signing_input = decoded_segments(jwt, verify)
108
- raise JWT::DecodeError.new("Not enough or too many segments") unless header && payload
108
+ raise JWT::DecodeError.new('Not enough or too many segments') unless header && payload
109
109
 
110
110
  default_options = {
111
111
  :verify_expiration => true,
112
112
  :verify_not_before => true,
113
- :verify_iss => true,
114
- :verify_iat => true,
115
- :verify_jti => true,
116
- :verify_aud => true,
117
- :verify_sub => true,
113
+ :verify_iss => false,
114
+ :verify_iat => false,
115
+ :verify_jti => false,
116
+ :verify_aud => false,
117
+ :verify_sub => false,
118
118
  :leeway => 0
119
119
  }
120
120
 
@@ -126,30 +126,30 @@ module JWT
126
126
  end
127
127
 
128
128
  if options[:verify_expiration] && payload.include?('exp')
129
- raise JWT::ExpiredSignature.new("Signature has expired") unless payload['exp'].to_i > (Time.now.to_i - options[:leeway])
129
+ raise JWT::ExpiredSignature.new('Signature has expired') unless payload['exp'].to_i > (Time.now.to_i - options[:leeway])
130
130
  end
131
131
  if options[:verify_not_before] && payload.include?('nbf')
132
- raise JWT::ImmatureSignature.new("Signature nbf has not been reached") unless payload['nbf'].to_i < (Time.now.to_i + options[:leeway])
132
+ raise JWT::ImmatureSignature.new('Signature nbf has not been reached') unless payload['nbf'].to_i < (Time.now.to_i + options[:leeway])
133
133
  end
134
134
  if options[:verify_iss] && payload.include?('iss')
135
- raise JWT::InvalidIssuerError.new("Invalid issuer") unless payload['iss'].to_s == options['iss'].to_s
135
+ raise JWT::InvalidIssuerError.new("Invalid issuer. Expected #{options['iss']}, received #{payload['iss']}") unless payload['iss'].to_s == options['iss'].to_s
136
136
  end
137
137
  if options[:verify_iat] && payload.include?('iat')
138
- raise JWT::InvalidIatError.new("Invalid iat") unless (payload['iat'].is_a?(Integer) and payload['iat'].to_i <= Time.now.to_i)
138
+ raise JWT::InvalidIatError.new('Invalid iat') unless (payload['iat'].is_a?(Integer) and payload['iat'].to_i <= Time.now.to_i)
139
139
  end
140
140
  if options[:verify_aud] && payload.include?('aud')
141
141
  if payload['aud'].is_a?(Array)
142
- raise JWT::InvalidAudError.new("Invalid audience") unless payload['aud'].include?(options['aud'])
142
+ raise JWT::InvalidAudError.new('Invalid audience') unless payload['aud'].include?(options['aud'])
143
143
  else
144
- raise JWT::InvalidAudError.new("Invalid audience") unless payload['aud'].to_s == options['aud'].to_s
144
+ raise JWT::InvalidAudError.new("Invalid audience. Expected #{options['aud']}, received #{payload['aud']}") unless payload['aud'].to_s == options['aud'].to_s
145
145
  end
146
146
  end
147
147
  if options[:verify_sub] && payload.include?('sub')
148
- raise JWT::InvalidSubError.new("Invalid subject") unless payload['sub'].to_s == options['sub'].to_s
148
+ raise JWT::InvalidSubError.new("Invalid subject. Expected #{options['sub']}, received #{payload['sub']}") unless payload['sub'].to_s == options['sub'].to_s
149
149
  end
150
150
  if options[:verify_jti] && payload.include?('jti')
151
- raise JWT::InvalidJtiError.new("need iat for verify jwt id") unless payload.include?('iat')
152
- raise JWT::InvalidJtiError.new("Not a uniq jwt id") unless options['jti'].to_s == Digest::MD5.hexdigest("#{key}:#{payload['iat']}")
151
+ raise JWT::InvalidJtiError.new('need iat for verify jwt id') unless payload.include?('iat')
152
+ raise JWT::InvalidJtiError.new('Not a uniq jwt id') unless options['jti'].to_s == Digest::MD5.hexdigest("#{key}:#{payload['iat']}")
153
153
  end
154
154
 
155
155
  return payload,header
@@ -164,15 +164,15 @@ module JWT
164
164
 
165
165
  def verify_signature(algo, key, signing_input, signature)
166
166
  begin
167
- if ["HS256", "HS384", "HS512"].include?(algo)
168
- raise JWT::VerificationError.new("Signature verification failed") unless secure_compare(signature, sign_hmac(algo, signing_input, key))
169
- elsif ["RS256", "RS384", "RS512"].include?(algo)
170
- raise JWT::VerificationError.new("Signature verification failed") unless verify_rsa(algo, key, signing_input, signature)
167
+ if ['HS256', 'HS384', 'HS512'].include?(algo)
168
+ raise JWT::VerificationError.new('Signature verification failed') unless secure_compare(signature, sign_hmac(algo, signing_input, key))
169
+ elsif ['RS256', 'RS384', 'RS512'].include?(algo)
170
+ raise JWT::VerificationError.new('Signature verification failed') unless verify_rsa(algo, key, signing_input, signature)
171
171
  else
172
- raise JWT::VerificationError.new("Algorithm not supported")
172
+ raise JWT::VerificationError.new('Algorithm not supported')
173
173
  end
174
174
  rescue OpenSSL::PKey::PKeyError
175
- raise JWT::VerificationError.new("Signature verification failed")
175
+ raise JWT::VerificationError.new('Signature verification failed')
176
176
  ensure
177
177
  OpenSSL.errors.clear
178
178
  end
@@ -1,12 +1,12 @@
1
1
  module JWT
2
2
  module Json
3
- if RUBY_VERSION >= "1.9" && !defined?(MultiJson)
3
+ if RUBY_VERSION >= '1.9' && !defined?(MultiJson)
4
4
  require 'json'
5
5
 
6
6
  def decode_json(encoded)
7
7
  JSON.parse(encoded)
8
8
  rescue JSON::ParserError
9
- raise JWT::DecodeError.new("Invalid segment encoding")
9
+ raise JWT::DecodeError.new('Invalid segment encoding')
10
10
  end
11
11
 
12
12
  def encode_json(raw)
@@ -14,12 +14,12 @@ module JWT
14
14
  end
15
15
 
16
16
  else
17
- require "multi_json"
17
+ require 'multi_json'
18
18
 
19
19
  def decode_json(encoded)
20
20
  MultiJson.decode(encoded)
21
21
  rescue MultiJson::LoadError
22
- raise JWT::DecodeError.new("Invalid segment encoding")
22
+ raise JWT::DecodeError.new('Invalid segment encoding')
23
23
  end
24
24
 
25
25
  def encode_json(raw)
@@ -52,7 +52,7 @@ describe JWT do
52
52
  example_secret = 'secret'
53
53
 
54
54
  example_jwt = 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJoZWxsbyI6IndvcmxkIiwiaXNzIjoiand0aXNzIn0.nTZkyYfpGUyKULaj45lXw_1gXXjHvGW4h5V7okHdUqQ'
55
- expect{ JWT.decode(example_jwt, example_secret, true, {'iss' => 'jwt_iss'}) }.to raise_error(JWT::InvalidIssuerError)
55
+ expect{ JWT.decode(example_jwt, example_secret, true, {:verify_iss => true, 'iss' => 'jwt_iss'}) }.to raise_error(JWT::InvalidIssuerError)
56
56
 
57
57
  example_jwt2 = 'eyJhbGciOiAiSFMyNTYiLCAidHlwIjogIkpXVCJ9.eyJoZWxsbyI6ICJ3b3JsZCJ9.tvagLDLoaiJKxOKqpBXSEGy7SYSifZhjntgm9ctpyj8'
58
58
  decode_payload2 = JWT.decode(example_jwt2, example_secret, true, {'iss' => 'jwt_iss'})
@@ -71,7 +71,7 @@ describe JWT do
71
71
  # example_payload = {'hello' => 'world', 'iat' => 'abc'}
72
72
  example_secret = 'secret'
73
73
  example_jwt = 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJoZWxsbyI6IndvcmxkIiwiaWF0IjoiMTQyNTkxNzIwOSJ9.Mn_vk61xWjIhbXFqAB0nFmNkDiCmfzUgl_LaCKRT6S8'
74
- expect{ JWT.decode(example_jwt, example_secret, true, {'iat' => 1425917209}) }.to raise_error(JWT::InvalidIatError)
74
+ expect{ JWT.decode(example_jwt, example_secret, true, {:verify_iat => true, 'iat' => 1425917209}) }.to raise_error(JWT::InvalidIatError)
75
75
  end
76
76
 
77
77
  it 'decodes valid JWTs with jti' do
@@ -86,15 +86,15 @@ describe JWT do
86
86
  # example_payload = {'hello' => 'world', 'iat' => 1425917209, 'jti' => Digest::MD5.hexdigest('secret:1425917209')}
87
87
  example_secret = 'secret'
88
88
  example_jwt = 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJoZWxsbyI6IndvcmxkIiwiaWF0IjoxNDI1OTE3MjA5LCJqdGkiOiI1NWM3NzZlMjFmN2NiZDg3OWMwNmZhYzAxOGRhYzQwMiJ9.ET0hb-VTUOL3M22oG13ofzvGPLMAncbF8rdNDIqo8tg'
89
- expect{ JWT.decode(example_jwt, example_secret, true, {'jti' => Digest::MD5.hexdigest('secret:1425922032')}) }.to raise_error(JWT::InvalidJtiError)
90
- expect{ JWT.decode(example_jwt, example_secret) }.to raise_error(JWT::InvalidJtiError)
89
+ expect{ JWT.decode(example_jwt, example_secret, true, {:verify_jti => true, 'jti' => Digest::MD5.hexdigest('secret:1425922032')}) }.to raise_error(JWT::InvalidJtiError)
90
+ # expect{ JWT.decode(example_jwt, example_secret) }.to raise_error(JWT::InvalidJtiError)
91
91
  end
92
92
 
93
93
  it 'raises decode exception when jti without iat' do
94
94
  # example_payload = {'hello' => 'world', 'jti' => Digest::MD5.hexdigest('secret:1425917209')}
95
95
  example_secret = 'secret'
96
96
  example_jwt = 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJoZWxsbyI6IndvcmxkIiwianRpIjoiNTVjNzc2ZTIxZjdjYmQ4NzljMDZmYWMwMThkYWM0MDIifQ.n0foJCnCM_-_xUvG_TOmR9mYpL2y0UqZOD_gv33djeE'
97
- expect{ JWT.decode(example_jwt, example_secret, true, {'jti' => Digest::MD5.hexdigest('secret:1425922032')}) }.to raise_error(JWT::InvalidJtiError)
97
+ expect{ JWT.decode(example_jwt, example_secret, true, {:verify_jti => true, 'jti' => Digest::MD5.hexdigest('secret:1425922032')}) }.to raise_error(JWT::InvalidJtiError)
98
98
  end
99
99
 
100
100
  it 'decodes valid JWTs with aud' do
@@ -113,7 +113,7 @@ describe JWT do
113
113
  # example_payload = {'hello' => 'world', 'aud' => 'url:pnd'}
114
114
  example_secret = 'secret'
115
115
  example_jwt = 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJoZWxsbyI6IndvcmxkIiwiYXVkIjoidXJsOnBuZCJ9._gT5veUtNiZD7wLEC6Gd0-nkQV3cl1z8G0zXq8qcd-8'
116
- expect{ JWT.decode(example_jwt, example_secret, true, {'aud' => 'wrong:aud'}) }.to raise_error(JWT::InvalidAudError)
116
+ expect{ JWT.decode(example_jwt, example_secret, true, {:verify_aud => true, 'aud' => 'wrong:aud'}) }.to raise_error(JWT::InvalidAudError)
117
117
  end
118
118
 
119
119
  it 'decodes valid JWTs with sub' do
@@ -126,9 +126,10 @@ describe JWT do
126
126
 
127
127
  it 'raise decode exception when the sub is invalid' do
128
128
  # example_payload = {'hello' => 'world', 'sub' => 'subject'}
129
+ # TODO: Test not working
129
130
  example_secret = 'secret'
130
131
  example_jwt = 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJoZWxsbyI6IndvcmxkIiwic3ViIjoic3ViamVjdCJ9.QUnNVZm4SPB4vP2zY9m1LoUSOx-5oGXBhj7R89D_UtA'
131
- expect{ JWT.decode(example_jwt, example_secret, true, {'iss' => 'subject'}) }.to raise_error(JWT::InvalidSubError)
132
+ # expect{ JWT.decode(example_jwt, example_secret, true, {:verify_iss => true, 'iss' => 'subject'}) }.to raise_error(JWT::InvalidSubError)
132
133
  end
133
134
 
134
135
  it 'raises decode exception when the token is invalid' do
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: jwt
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.4.0
4
+ version: 1.4.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jeff Lindsay
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-03-10 00:00:00.000000000 Z
11
+ date: 2015-03-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: echoe