Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Claims Validation #295

Merged
merged 3 commits into from
Jan 26, 2019
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
Prev Previous commit
Next Next commit
Extract claims validation into class
  • Loading branch information
jamesstonehill committed Jan 26, 2019
commit b2315c854274c1e00e2cb86fcee9dec2212b892e
31 changes: 31 additions & 0 deletions lib/jwt/claims_validator.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
require_relative './error'

module JWT
class ClaimsValidator
INTEGER_CLAIMS = %i[
jamesstonehill marked this conversation as resolved.
Show resolved Hide resolved
exp
]

def initialize(payload)
@payload = payload.each_with_object({}) { |(k, v), h| h[k.to_sym] = v }
jamesstonehill marked this conversation as resolved.
Show resolved Hide resolved
jamesstonehill marked this conversation as resolved.
Show resolved Hide resolved
jamesstonehill marked this conversation as resolved.
Show resolved Hide resolved
end

def validate!
validate_int_claims

true
end

private

def validate_int_claims
INTEGER_CLAIMS.each do |claim|
validate_is_int(claim) if @payload.key?(claim)
end
end

def validate_is_int(claim)
raise InvalidPayload, "#{claim} claim must be an integer" unless @payload[:exp].is_a?(Integer)
end
end
end
21 changes: 6 additions & 15 deletions lib/jwt/encode.rb
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
# frozen_string_literal: true

require_relative './claims_validator'

# JWT::Encode module
module JWT
# Encoding logic for JWT
class Encode
ALG_NONE = 'none'.freeze
ALG_KEY = 'alg'.freeze
EXP_KEY = 'exp'.freeze
EXP_KEYS = [EXP_KEY, EXP_KEY.to_sym].freeze

def initialize(options)
@payload = options[:payload]
Expand All @@ -22,18 +22,6 @@ def segments

private

def validate_payload!
return unless @payload && @payload.is_a?(Hash)

validate_exp!
end

def validate_exp!
return if EXP_KEYS.all? { |key| !@payload.key?(key) || @payload[key].is_a?(Integer) }

raise InvalidPayload, 'exp claim must be an integer'
end

def encoded_header
@encoded_header ||= encode_header
end
Expand All @@ -55,7 +43,10 @@ def encode_header
end

def encode_payload
validate_payload!
if @payload && @payload.is_a?(Hash)
ClaimsValidator.new(@payload).validate!
end

encode(@payload)
end

Expand Down
33 changes: 33 additions & 0 deletions spec/jwt/claims_validator_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
require 'spec_helper'
require 'jwt/claims_validator'

RSpec.describe JWT::ClaimsValidator do
describe '#validate!' do
it 'returns true if the payload is valid' do
valid_payload = { 'exp' => 12345 }
subject = described_class.new(valid_payload)

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' })
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 })
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 })
expect { symbol.validate! }.to raise_error JWT::InvalidPayload

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