Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions .codeclimate.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,13 @@ engines:
rubocop:
enabled: true
golint:
enabled: true
enabled: false
gofmt:
enabled: true
enabled: false
eslint:
enabled: true
enabled: false
csslint:
enabled: true
enabled: false

# Engines can analyze files and report issues on them, but you can separately
# decide which files will receive ratings based on those issues. This is
Expand Down
9 changes: 0 additions & 9 deletions .rubocop.yml

This file was deleted.

152 changes: 0 additions & 152 deletions .rubocop_todo.yml

This file was deleted.

5 changes: 2 additions & 3 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
sudo: false
cache: bundler
language: ruby
rvm:
- 1.8.7
- 1.9.2
- 1.9.3
- 2.0.0
- 2.1.0
- 2.2.0
- jruby
- ree
script: "bundle exec rake test"
addons:
code_climate:
Expand Down
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
Loading