Skip to content

Commit

Permalink
Update code style
Browse files Browse the repository at this point in the history
Fix some rubocop issues (default configuration)
Change hash syntax
Change `raise` to `fail` syntax
  • Loading branch information
excpt committed Sep 16, 2015
1 parent 1c4901f commit c490860
Show file tree
Hide file tree
Showing 3 changed files with 64 additions and 64 deletions.
6 changes: 3 additions & 3 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@
source 'https://rubygems.org'

gem 'json', '>= 1.2.4'
gem 'multi_json', '~> 1.0', :platforms => :ruby_18
gem 'jruby-openssl', :platforms => :jruby
gem 'multi_json', '~> 1.0', platforms: :ruby_18
gem 'jruby-openssl', platforms: :jruby

gem 'rubysl', '~> 2.0', :platforms => :rbx
gem 'rubysl', '~> 2.0', platforms: :rbx

group :development do
gem 'echoe', '>= 4.6.3'
Expand Down
86 changes: 43 additions & 43 deletions lib/jwt.rb
Original file line number Diff line number Diff line change
Expand Up @@ -30,14 +30,14 @@ class InvalidJtiError < DecodeError; end
module_function

def sign(algorithm, msg, key)
if ['HS256', 'HS384', 'HS512'].include?(algorithm)
if %w(HS256 HS384 HS512).include?(algorithm)
sign_hmac(algorithm, msg, key)
elsif ['RS256', 'RS384', 'RS512'].include?(algorithm)
elsif %w(RS256 RS384 RS512).include?(algorithm)
sign_rsa(algorithm, msg, key)
elsif ['ES256', 'ES384', 'ES512'].include?(algorithm)
elsif %w(ES256 ES384 ES512).include?(algorithm)
sign_ecdsa(algorithm, msg, key)
else
fail NotImplementedError.new('Unsupported signing method')
fail NotImplementedError, 'Unsupported signing method'
end
end

Expand All @@ -48,7 +48,7 @@ def sign_rsa(algorithm, msg, private_key)
def sign_ecdsa(algorithm, msg, private_key)
key_algorithm = NAMED_CURVES[private_key.group.curve_name]
if algorithm != key_algorithm
fail IncorrectAlgorithm.new("payload algorithm is #{algorithm} but #{key_algorithm} signing key was provided")
fail IncorrectAlgorithm, "payload algorithm is #{algorithm} but #{key_algorithm} signing key was provided"
end

digest = OpenSSL::Digest.new(algorithm.sub('ES', 'sha'))
Expand All @@ -62,7 +62,7 @@ def verify_rsa(algorithm, public_key, signing_input, signature)
def verify_ecdsa(algorithm, public_key, signing_input, signature)
key_algorithm = NAMED_CURVES[public_key.group.curve_name]
if algorithm != key_algorithm
fail IncorrectAlgorithm.new("payload algorithm is #{algorithm} but #{key_algorithm} verification key was provided")
fail IncorrectAlgorithm, "payload algorithm is #{algorithm} but #{key_algorithm} verification key was provided"
end

digest = OpenSSL::Digest.new(algorithm.sub('ES', 'sha'))
Expand All @@ -82,7 +82,7 @@ def base64url_encode(str)
Base64.encode64(str).tr('+/', '-_').gsub(/[\n=]/, '')
end

def encoded_header(algorithm='HS256', header_fields={})
def encoded_header(algorithm = 'HS256', header_fields = {})
header = { 'typ' => 'JWT', 'alg' => algorithm }.merge(header_fields)
base64url_encode(encode_json(header))
end
Expand All @@ -100,7 +100,7 @@ def encoded_signature(signing_input, key, algorithm)
end
end

def encode(payload, key, algorithm='HS256', header_fields={})
def encode(payload, key, algorithm = 'HS256', header_fields = {})
algorithm ||= 'none'
segments = []
segments << encoded_header(algorithm, header_fields)
Expand All @@ -109,10 +109,10 @@ def encode(payload, key, algorithm='HS256', header_fields={})
segments.join('.')
end

def raw_segments(jwt, verify=true)
def raw_segments(jwt, verify = true)
segments = jwt.split('.')
required_num_segments = verify ? [3] : [2, 3]
fail JWT::DecodeError.new('Not enough or too many segments') unless required_num_segments.include? segments.length
fail(JWT::DecodeError, 'Not enough or too many segments') unless required_num_segments.include? segments.length
segments
end

Expand All @@ -122,66 +122,66 @@ def decode_header_and_payload(header_segment, payload_segment)
[header, payload]
end

def decoded_segments(jwt, verify=true)
def decoded_segments(jwt, verify = true)
header_segment, payload_segment, crypto_segment = raw_segments(jwt, verify)
header, payload = decode_header_and_payload(header_segment, payload_segment)
signature = base64url_decode(crypto_segment.to_s) if verify
signing_input = [header_segment, payload_segment].join('.')
[header, payload, signature, signing_input]
end

def decode(jwt, key=nil, verify=true, options={}, &keyfinder)
fail JWT::DecodeError.new('Nil JSON web token') unless jwt
def decode(jwt, key = nil, verify = true, options = {}, &keyfinder)
fail(JWT::DecodeError, 'Nil JSON web token') unless jwt

header, payload, signature, signing_input = decoded_segments(jwt, verify)
fail JWT::DecodeError.new('Not enough or too many segments') unless header && payload
fail(JWT::DecodeError, 'Not enough or too many segments') unless header && payload

default_options = {
:verify_expiration => true,
:verify_not_before => true,
:verify_iss => false,
:verify_iat => false,
:verify_jti => false,
:verify_aud => false,
:verify_sub => false,
:leeway => 0
verify_expiration: true,
verify_not_before: true,
verify_iss: false,
verify_iat: false,
verify_jti: false,
verify_aud: false,
verify_sub: false,
leeway: 0
}

options = default_options.merge(options)

if verify
algo, key = signature_algorithm_and_key(header, key, &keyfinder)
if options[:algorithm] && algo != options[:algorithm]
fail JWT::IncorrectAlgorithm.new('Expected a different algorithm')
fail JWT::IncorrectAlgorithm, 'Expected a different algorithm'
end
verify_signature(algo, key, signing_input, signature)
end

if options[:verify_expiration] && payload.include?('exp')
fail JWT::ExpiredSignature.new('Signature has expired') unless payload['exp'].to_i > (Time.now.to_i - options[:leeway])
fail(JWT::ExpiredSignature, 'Signature has expired') unless payload['exp'].to_i > (Time.now.to_i - options[:leeway])
end
if options[:verify_not_before] && payload.include?('nbf')
fail JWT::ImmatureSignature.new('Signature nbf has not been reached') unless payload['nbf'].to_i <= (Time.now.to_i + options[:leeway])
fail(JWT::ImmatureSignature, 'Signature nbf has not been reached') unless payload['nbf'].to_i <= (Time.now.to_i + options[:leeway])
end
if options[:verify_iss] && options['iss']
fail JWT::InvalidIssuerError.new("Invalid issuer. Expected #{options['iss']}, received #{payload['iss'] || '<none>'}") unless payload['iss'].to_s == options['iss'].to_s
if options[:verify_iss] && options[:iss]
fail(JWT::InvalidIssuerError, "Invalid issuer. Expected #{options[:iss]}, received #{payload['iss'] || '<none>'}") unless payload['iss'].to_s == options[:iss].to_s
end
if options[:verify_iat] && payload.include?('iat')
fail JWT::InvalidIatError.new('Invalid iat') unless payload['iat'].is_a?(Integer) && payload['iat'].to_i <= (Time.now.to_i + options[:leeway])
fail(JWT::InvalidIatError, 'Invalid iat') unless payload['iat'].is_a?(Integer) && payload['iat'].to_i <= (Time.now.to_i + options[:leeway])
end
if options[:verify_aud] && options['aud']
if payload['aud'].is_a?(Array)
fail JWT::InvalidAudError.new('Invalid audience') unless payload['aud'].include?(options['aud'].to_s)
if options[:verify_aud] && options[:aud]
if payload[:aud].is_a?(Array)
fail(JWT::InvalidAudError, 'Invalid audience') unless payload['aud'].include?(options[:aud].to_s)
else
fail JWT::InvalidAudError.new("Invalid audience. Expected #{options['aud']}, received #{payload['aud'] || '<none>'}") unless payload['aud'].to_s == options['aud'].to_s
fail(JWT::InvalidAudError, "Invalid audience. Expected #{options[:aud]}, received #{payload['aud'] || '<none>'}") unless payload['aud'].to_s == options[:aud].to_s
end
end
if options[:verify_sub] && payload.include?('sub')
fail JWT::InvalidSubError.new("Invalid subject. Expected #{options['sub']}, received #{payload['sub']}") unless payload['sub'].to_s == options['sub'].to_s
fail(JWT::InvalidSubError, "Invalid subject. Expected #{options[:sub]}, received #{payload['sub'] || '<none>'}") unless payload['sub'].to_s == options[:sub].to_s
end
if options[:verify_jti] && payload.include?('jti')
fail JWT::InvalidJtiError.new('need iat for verify jwt id') unless payload.include?('iat')
fail JWT::InvalidJtiError.new('Not a uniq jwt id') unless options['jti'].to_s == Digest::MD5.hexdigest("#{key}:#{payload['iat']}")
fail(JWT::InvalidJtiError, 'need iat for verify jwt id') unless payload.include?('iat')
fail(JWT::InvalidJtiError, 'Not a uniq jwt id') unless options[:jti].to_s == Digest::MD5.hexdigest("#{key}:#{payload['iat']}")
end

[payload, header]
Expand All @@ -193,17 +193,17 @@ def signature_algorithm_and_key(header, key, &keyfinder)
end

def verify_signature(algo, key, signing_input, signature)
if ['HS256', 'HS384', 'HS512'].include?(algo)
fail JWT::VerificationError.new('Signature verification failed') unless secure_compare(signature, sign_hmac(algo, signing_input, key))
elsif ['RS256', 'RS384', 'RS512'].include?(algo)
fail JWT::VerificationError.new('Signature verification failed') unless verify_rsa(algo, key, signing_input, signature)
elsif ['ES256', 'ES384', 'ES512'].include?(algo)
fail JWT::VerificationError.new('Signature verification failed') unless verify_ecdsa(algo, key, signing_input, signature)
if %w(HS256 HS384 HS512).include?(algo)
fail(JWT::VerificationError, 'Signature verification raiseed') unless secure_compare(signature, sign_hmac(algo, signing_input, key))
elsif %w(RS256 RS384 RS512).include?(algo)
fail(JWT::VerificationError, 'Signature verification raiseed') unless verify_rsa(algo, key, signing_input, signature)
elsif %w(ES256 ES384 ES512).include?(algo)
fail(JWT::VerificationError, 'Signature verification raiseed') unless verify_ecdsa(algo, key, signing_input, signature)
else
fail JWT::VerificationError.new('Algorithm not supported')
fail JWT::VerificationError, 'Algorithm not supported'
end
rescue OpenSSL::PKey::PKeyError
raise JWT::VerificationError.new('Signature verification failed')
fail JWT::VerificationError, 'Signature verification raised'
ensure
OpenSSL.errors.clear
end
Expand Down
36 changes: 18 additions & 18 deletions spec/jwt_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -98,14 +98,14 @@
example_secret = 'secret'

example_jwt = 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJoZWxsbyI6IndvcmxkIiwiaXNzIjoiand0aXNzIn0.nTZkyYfpGUyKULaj45lXw_1gXXjHvGW4h5V7okHdUqQ'
expect { JWT.decode(example_jwt, example_secret, true, :verify_iss => true, 'iss' => 'jwt_iss') }.to raise_error(JWT::InvalidIssuerError, /Expected jwt_iss, received jwtiss/)
expect { JWT.decode(example_jwt, example_secret, true, verify_iss: true, iss: 'jwt_iss') }.to raise_error(JWT::InvalidIssuerError, /Expected jwt_iss, received jwtiss/)
end

it 'raises invalid issuer when "iss" claim is missing in payload' do
example_secret = 'secret'

example_jwt = 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJoZWxsbyI6IndvcmxkIn0.bqxXg9VwcbXKoiWtp-osd0WKPX307RjcN7EuXbdq-CE'
expect { JWT.decode(example_jwt, example_secret, true, :verify_iss => true, 'iss' => 'jwt_iss') }.to raise_error(JWT::InvalidIssuerError, /received <none>/)
expect { JWT.decode(example_jwt, example_secret, true, verify_iss: true, iss: 'jwt_iss') }.to raise_error(JWT::InvalidIssuerError, /received <none>/)
end

it 'does not raise invalid issuer when verify_iss is set to false (default option)' do
Expand All @@ -124,38 +124,38 @@
end

it 'decodes valid JWTs with iat' do
example_payload = { 'hello' => 'world', 'iat' => 1425917209 }
example_payload = { 'hello' => 'world', 'iat' => 1_425_917_209 }
example_secret = 'secret'
example_jwt = 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJoZWxsbyI6IndvcmxkIiwiaWF0IjoxNDI1OTE3MjA5fQ.m4F-Ugo7aLnLunBBO3BeDidyWMx8T9eoJz6FW2rgQhU'
decoded_payload = JWT.decode(example_jwt, example_secret, true, 'iat' => true)
decoded_payload = JWT.decode(example_jwt, example_secret, true, iat: true)
expect(decoded_payload).to include(example_payload)
end

it 'raises decode exception when iat is invalid' do
# example_payload = {'hello' => 'world', 'iat' => 'abc'}
example_secret = 'secret'
example_jwt = 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJoZWxsbyI6IndvcmxkIiwiaWF0IjoiMTQyNTkxNzIwOSJ9.Mn_vk61xWjIhbXFqAB0nFmNkDiCmfzUgl_LaCKRT6S8'
expect { JWT.decode(example_jwt, example_secret, true, :verify_iat => true, 'iat' => 1425917209) }.to raise_error(JWT::InvalidIatError)
expect { JWT.decode(example_jwt, example_secret, true, verify_iat: true, 'iat' => 1_425_917_209) }.to raise_error(JWT::InvalidIatError)
end

it 'raises decode exception when iat is in the future' do
invalid_payload = @payload.clone
invalid_payload['iat'] = Time.now.to_i + 3
secret = 'secret'
jwt = JWT.encode(invalid_payload, secret)
expect { JWT.decode(jwt, secret, true, :verify_iat => true) }.to raise_error(JWT::InvalidIatError)
expect { JWT.decode(jwt, secret, true, verify_iat: true) }.to raise_error(JWT::InvalidIatError)
end

it 'performs normal decode if iat is within leeway' do
invalid_payload = @payload.clone
invalid_payload['iat'] = Time.now.to_i + 3
secret = 'secret'
jwt = JWT.encode(invalid_payload, secret)
expect { JWT.decode(jwt, secret, true, :verify_iat => true, :leeway => 3) }.to_not raise_error
expect { JWT.decode(jwt, secret, true, verify_iat: true, leeway: 3) }.to_not raise_error
end

it 'decodes valid JWTs with jti' do
example_payload = { 'hello' => 'world', 'iat' => 1425917209, 'jti' => Digest::MD5.hexdigest('secret:1425917209') }
example_payload = { 'hello' => 'world', 'iat' => 1_425_917_209, 'jti' => Digest::MD5.hexdigest('secret:1425917209') }
example_secret = 'secret'
example_jwt = 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJoZWxsbyI6IndvcmxkIiwiaWF0IjoxNDI1OTE3MjA5LCJqdGkiOiI1NWM3NzZlMjFmN2NiZDg3OWMwNmZhYzAxOGRhYzQwMiJ9.ET0hb-VTUOL3M22oG13ofzvGPLMAncbF8rdNDIqo8tg'
decoded_payload = JWT.decode(example_jwt, example_secret, true, 'jti' => Digest::MD5.hexdigest('secret:1425917209'))
Expand Down Expand Up @@ -194,14 +194,14 @@
# example_payload = {'hello' => 'world', 'aud' => 'url:pnd'}
example_secret = 'secret'
example_jwt = 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJoZWxsbyI6IndvcmxkIiwiYXVkIjoidXJsOnBuZCJ9._gT5veUtNiZD7wLEC6Gd0-nkQV3cl1z8G0zXq8qcd-8'
expect { JWT.decode(example_jwt, example_secret, true, :verify_aud => true, 'aud' => 'wrong:aud') }.to raise_error(JWT::InvalidAudError)
expect { JWT.decode(example_jwt, example_secret, true, verify_aud: true, aud: 'wrong:aud') }.to raise_error(JWT::InvalidAudError)
end

it 'raises deode exception when aud is missing' do
# JWT.encode('hello' => 'world', 'secret')
example_secret = 'secret'
example_jwt = 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJoZWxsbyI6IndvcmxkIn0.bqxXg9VwcbXKoiWtp-osd0WKPX307RjcN7EuXbdq-CE'
expect { JWT.decode(example_jwt, example_secret, true, :verify_aud => true, 'aud' => 'url:pnd') }.to raise_error(JWT::InvalidAudError)
expect { JWT.decode(example_jwt, example_secret, true, verify_aud: true, aud: 'url:pnd') }.to raise_error(JWT::InvalidAudError)
end
end

Expand Down Expand Up @@ -302,12 +302,12 @@

it 'raises exception when decoded with a different algorithm than it was encoded with' do
jwt = JWT.encode(@payload, 'foo', 'HS384')
expect { JWT.decode(jwt, 'foo', true, :algorithm => 'HS512') }.to raise_error(JWT::IncorrectAlgorithm)
expect { JWT.decode(jwt, 'foo', true, algorithm: 'HS512') }.to raise_error(JWT::IncorrectAlgorithm)
end

it 'does not raise exception when encoded with the expected algorithm' do
jwt = JWT.encode(@payload, 'foo', 'HS512')
JWT.decode(jwt, 'foo', true, :algorithm => 'HS512')
JWT.decode(jwt, 'foo', true, algorithm: 'HS512')
end

it 'encodes and decodes plaintext JWTs' do
Expand Down Expand Up @@ -357,7 +357,7 @@
expired_payload['exp'] = Time.now.to_i - 1
secret = 'secret'
jwt = JWT.encode(expired_payload, secret)
decoded_payload = JWT.decode(jwt, secret, true, :verify_expiration => false)
decoded_payload = JWT.decode(jwt, secret, true, verify_expiration: false)
expect(decoded_payload).to include(expired_payload)
end

Expand All @@ -366,7 +366,7 @@
expired_payload['exp'] = Time.now.to_i - 2
secret = 'secret'
jwt = JWT.encode(expired_payload, secret)
decoded_payload = JWT.decode(jwt, secret, true, :leeway => 3)
decoded_payload = JWT.decode(jwt, secret, true, leeway: 3)
expect(decoded_payload).to include(expired_payload)
end

Expand All @@ -383,15 +383,15 @@
mature_payload['nbf'] = Time.now.to_i
secret = 'secret'
jwt = JWT.encode(mature_payload, secret)
decoded_payload = JWT.decode(jwt, secret, true, :verify_expiration => false)
decoded_payload = JWT.decode(jwt, secret, true, verify_expiration: false)
expect(decoded_payload).to include(mature_payload)
end

it 'doesnt raise error when after nbf' do
mature_payload = @payload.clone
secret = 'secret'
jwt = JWT.encode(mature_payload, secret)
decoded_payload = JWT.decode(jwt, secret, true, :verify_expiration => false)
decoded_payload = JWT.decode(jwt, secret, true, verify_expiration: false)
expect(decoded_payload).to include(mature_payload)
end

Expand All @@ -408,7 +408,7 @@
immature_payload['nbf'] = Time.now.to_i + 2
secret = 'secret'
jwt = JWT.encode(immature_payload, secret)
decoded_payload = JWT.decode(jwt, secret, true, :verify_not_before => false)
decoded_payload = JWT.decode(jwt, secret, true, verify_not_before: false)
expect(decoded_payload).to include(immature_payload)
end

Expand All @@ -417,7 +417,7 @@
immature_payload['nbf'] = Time.now.to_i - 2
secret = 'secret'
jwt = JWT.encode(immature_payload, secret)
decoded_payload = JWT.decode(jwt, secret, true, :leeway => 3)
decoded_payload = JWT.decode(jwt, secret, true, leeway: 3)
expect(decoded_payload).to include(immature_payload)
end

Expand Down

0 comments on commit c490860

Please sign in to comment.