diff --git a/.travis.yml b/.travis.yml index 0d9c7495..1f8285d4 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,3 +1,6 @@ +sudo: required +cache: bundler +dist: trusty language: ruby rvm: - 2.3 @@ -10,6 +13,7 @@ rvm: gemfile: - gemfiles/standalone.gemfile - gemfiles/openssl_2.1.gemfile + - gemfiles/rbnacl.gemfile script: - bundle exec rspec - bundle exec codeclimate-test-reporter diff --git a/Appraisals b/Appraisals new file mode 100644 index 00000000..f818a160 --- /dev/null +++ b/Appraisals @@ -0,0 +1,10 @@ +appraise 'standalone' do +end + +appraise 'openssl' do + gem 'openssl', '~> 2.1' +end + +appraise 'rbnacl' do + gem 'rbnacl' +end \ No newline at end of file diff --git a/gemfiles/openssl.gemfile b/gemfiles/openssl.gemfile new file mode 100644 index 00000000..94ce8660 --- /dev/null +++ b/gemfiles/openssl.gemfile @@ -0,0 +1,7 @@ +# This file was generated by Appraisal + +source "https://rubygems.org" + +gem "openssl", "~> 2.1" + +gemspec path: "../" diff --git a/gemfiles/openssl_2.1.gemfile b/gemfiles/openssl_2.1.gemfile deleted file mode 100644 index e69de29b..00000000 diff --git a/gemfiles/rbnacl.gemfile b/gemfiles/rbnacl.gemfile new file mode 100644 index 00000000..ad523a89 --- /dev/null +++ b/gemfiles/rbnacl.gemfile @@ -0,0 +1,7 @@ +# This file was generated by Appraisal + +source "https://rubygems.org" + +gem "rbnacl" + +gemspec path: "../" diff --git a/ruby-jwt.gemspec b/ruby-jwt.gemspec index ac41e2ae..a0415b7d 100644 --- a/ruby-jwt.gemspec +++ b/ruby-jwt.gemspec @@ -20,6 +20,7 @@ Gem::Specification.new do |spec| spec.test_files = spec.files.grep(%r{^(test|spec|features)/}) spec.require_paths = %w[lib] + spec.add_development_dependency 'appraisal' spec.add_development_dependency 'bundler' spec.add_development_dependency 'rake' spec.add_development_dependency 'rspec' diff --git a/spec/jwt_spec.rb b/spec/jwt_spec.rb index e49f8dee..440d4823 100644 --- a/spec/jwt_spec.rb +++ b/spec/jwt_spec.rb @@ -7,7 +7,7 @@ let(:payload) { { 'user_id' => 'some@user.tld' } } let :data do - { + data = { :secret => 'My$ecretK3y', :rsa_private => OpenSSL::PKey.read(File.read(File.join(CERT_PATH, 'rsa-2048-private.pem'))), :rsa_public => OpenSSL::PKey.read(File.read(File.join(CERT_PATH, 'rsa-2048-public.pem'))), @@ -19,8 +19,6 @@ 'ES384_public' => OpenSSL::PKey.read(File.read(File.join(CERT_PATH, 'ec384-public.pem'))), 'ES512_private' => OpenSSL::PKey.read(File.read(File.join(CERT_PATH, 'ec512-private.pem'))), 'ES512_public' => OpenSSL::PKey.read(File.read(File.join(CERT_PATH, 'ec512-public.pem'))), - 'ED25519_private' => RbNaCl::Signatures::Ed25519::SigningKey.new('abcdefghijklmnopqrstuvwxyzABCDEF'), - 'ED25519_public' => RbNaCl::Signatures::Ed25519::SigningKey.new('abcdefghijklmnopqrstuvwxyzABCDEF').verify_key, 'NONE' => 'eyJhbGciOiJub25lIn0.eyJ1c2VyX2lkIjoic29tZUB1c2VyLnRsZCJ9.', 'HS256' => 'eyJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoic29tZUB1c2VyLnRsZCJ9.kWOVtIOpWcG7JnyJG0qOkTDbOy636XrrQhMm_8JrRQ8', 'HS512256' => 'eyJhbGciOiJIUzUxMjI1NiJ9.eyJ1c2VyX2lkIjoic29tZUB1c2VyLnRsZCJ9.Ds_4ibvf7z4QOBoKntEjDfthy3WJ-3rKMspTEcHE2bA', @@ -36,6 +34,14 @@ 'PS384' => '', 'PS512' => '' } + + if defined?(RbNaCl) + data.merge!( + 'ED25519_private' => RbNaCl::Signatures::Ed25519::SigningKey.new('abcdefghijklmnopqrstuvwxyzABCDEF'), + 'ED25519_public' => RbNaCl::Signatures::Ed25519::SigningKey.new('abcdefghijklmnopqrstuvwxyzABCDEF').verify_key, + ) + end + data end after(:each) do @@ -99,7 +105,7 @@ expect(validator).to receive(:validate!) { true } payload = {} - JWT.encode payload, "secret", JWT::Algos::Hmac::SUPPORTED.sample + JWT.encode payload, "secret", 'HS256' end it 'does not validate the payload if it is not present' do @@ -107,11 +113,14 @@ expect(JWT::ClaimsValidator).not_to receive(:new) { validator } payload = nil - JWT.encode payload, "secret", JWT::Algos::Hmac::SUPPORTED.sample + JWT.encode payload, "secret", 'HS256' end end - %w[HS256 HS512256 HS384 HS512].each do |alg| + algorithms = %w[HS256 HS384 HS512] + algorithms << 'HS512256' if defined?(RbNaCl) + + algorithms.each do |alg| context "alg: #{alg}" do it 'should generate a valid token' do token = JWT.encode payload, data[:secret], alg @@ -180,38 +189,40 @@ end end - %w[ED25519].each do |alg| - context "alg: #{alg}" do - before(:each) do - data[alg] = JWT.encode payload, data["#{alg}_private"], alg - end + if defined?(RbNaCl) + %w[ED25519].each do |alg| + context "alg: #{alg}" do + before(:each) do + data[alg] = JWT.encode payload, data["#{alg}_private"], alg + end - let(:wrong_key) { OpenSSL::PKey.read(File.read(File.join(CERT_PATH, 'ec256-wrong-public.pem'))) } + let(:wrong_key) { OpenSSL::PKey.read(File.read(File.join(CERT_PATH, 'ec256-wrong-public.pem'))) } - it 'should generate a valid token' do - jwt_payload, header = JWT.decode data[alg], data["#{alg}_public"], true, algorithm: alg + it 'should generate a valid token' do + jwt_payload, header = JWT.decode data[alg], data["#{alg}_public"], true, algorithm: alg - expect(header['alg']).to eq alg - expect(jwt_payload).to eq payload - end + expect(header['alg']).to eq alg + expect(jwt_payload).to eq payload + end - it 'should decode a valid token' do - jwt_payload, header = JWT.decode data[alg], data["#{alg}_public"], true, algorithm: alg + it 'should decode a valid token' do + jwt_payload, header = JWT.decode data[alg], data["#{alg}_public"], true, algorithm: alg - expect(header['alg']).to eq alg - expect(jwt_payload).to eq payload - end + expect(header['alg']).to eq alg + expect(jwt_payload).to eq payload + end - it 'wrong key should raise JWT::DecodeError' do - expect do - JWT.decode data[alg], wrong_key - end.to raise_error JWT::DecodeError - end + it 'wrong key should raise JWT::DecodeError' do + expect do + JWT.decode data[alg], wrong_key + end.to raise_error JWT::DecodeError + end - it 'wrong key and verify = false should not raise JWT::DecodeError' do - expect do - JWT.decode data[alg], wrong_key, false - end.not_to raise_error + it 'wrong key and verify = false should not raise JWT::DecodeError' do + expect do + JWT.decode data[alg], wrong_key, false + end.not_to raise_error + end end end end