Skip to content

Commit

Permalink
Validate iat and nbf claims like we are doing for exp
Browse files Browse the repository at this point in the history
  • Loading branch information
jamesstonehill committed Jan 26, 2019
1 parent b2315c8 commit 9f9913e
Show file tree
Hide file tree
Showing 3 changed files with 35 additions and 30 deletions.
6 changes: 4 additions & 2 deletions lib/jwt/claims_validator.rb
Expand Up @@ -4,7 +4,9 @@ module JWT
class ClaimsValidator
INTEGER_CLAIMS = %i[
exp
]
iat
nbf
].freeze

def initialize(payload)
@payload = payload.each_with_object({}) { |(k, v), h| h[k.to_sym] = v }
Expand All @@ -25,7 +27,7 @@ def validate_int_claims
end

def validate_is_int(claim)
raise InvalidPayload, "#{claim} claim must be an integer" unless @payload[:exp].is_a?(Integer)
raise InvalidPayload, "#{claim} claim must be an Integer but it is a #{@payload[claim].class}" unless @payload[claim].is_a?(Integer)
end
end
end
28 changes: 20 additions & 8 deletions spec/jwt/claims_validator_spec.rb
Expand Up @@ -10,24 +10,36 @@
expect(subject.validate!).to eq(true)
end

context "exp validation" do
it 'raises an error when the value of the exp claim is a string' do
subject = described_class.new({ exp: '1' })
shared_examples_for 'an integer claim' do |claim|
it "raises an error when the value of the #{claim} claim is a string" do
subject = described_class.new({ claim => '1' })
expect { subject.validate! }.to raise_error JWT::InvalidPayload
end

it 'raises an error when the value of the exp claim is a Time object' do
subject = described_class.new({ exp: Time.now })
it "raises an error when the value of the #{claim} claim is a Time object" do
subject = described_class.new({ claim => Time.now })
expect { subject.validate! }.to raise_error JWT::InvalidPayload
end

it 'validates the exp when the exp key is either a string or a symbol' do
symbol = described_class.new({ exp: true })
it "validates the #{claim} claim when the key is either a string or a symbol" do
symbol = described_class.new({ claim.to_sym => true })
expect { symbol.validate! }.to raise_error JWT::InvalidPayload

string = described_class.new({ 'exp' => true })
string = described_class.new({ claim.to_s => true })
expect { string.validate! }.to raise_error JWT::InvalidPayload
end
end

context 'exp claim' do
it_should_behave_like 'an integer claim', :exp
end

context 'iat claim' do
it_should_behave_like 'an integer claim', :iat
end

context 'nbf claim' do
it_should_behave_like 'an integer claim', :nbf
end
end
end
31 changes: 11 additions & 20 deletions spec/jwt_spec.rb
Expand Up @@ -60,30 +60,21 @@
end

context 'payload validation' do
subject { JWT.encode(payload, nil, 'none') }
let(:payload) { { 'exp' => exp } }
it 'validates the payload with the ClaimsValidator if the payload is a hash' do
validator = double()
expect(JWT::ClaimsValidator).to receive(:new) { validator }
expect(validator).to receive(:validate!) { true }

context 'when exp is given as a non Integer' do
let(:exp) { Time.now.to_i.to_s }
it 'raises an JWT::InvalidPayload error' do
expect { subject }.to raise_error(JWT::InvalidPayload, 'exp claim must be an integer')
end
end

context 'when exp is given as an Integer' do
let(:exp) { 1234 }

it 'encodes the payload' do
expect(subject).to be_a(String)
end
payload = {}
JWT.encode payload, "secret", JWT::Algos::Hmac::SUPPORTED.sample
end

context 'when the key for exp is a symbol' do
let(:payload) { { :exp => 'NotAInteger' } }
it 'does not validate the payload if it is not present' do
validator = double()
expect(JWT::ClaimsValidator).not_to receive(:new) { validator }

it 'raises an JWT::InvalidPayload error' do
expect { subject }.to raise_error(JWT::InvalidPayload, 'exp claim must be an integer')
end
payload = nil
JWT.encode payload, "secret", JWT::Algos::Hmac::SUPPORTED.sample
end
end

Expand Down

0 comments on commit 9f9913e

Please sign in to comment.