Skip to content

Commit

Permalink
Allow decode options to specify required claims
Browse files Browse the repository at this point in the history
  • Loading branch information
andyjdavis committed Jul 2, 2021
1 parent c444ac9 commit 498d632
Show file tree
Hide file tree
Showing 6 changed files with 34 additions and 2 deletions.
8 changes: 8 additions & 0 deletions README.md
Expand Up @@ -482,6 +482,14 @@ rescue JWT::InvalidIssuerError
end
```

### Required Claims

You can specify claims that must be present for decoding to be successful. JWT::MissingRequiredClaim will be raised if any are missing
```ruby
# Will raise a JWT::ExpiredSignature error if the 'exp' claim is absent
JWT.decode token, hmac_secret, true, { required_claims: ['exp'], algorithm: 'HS256' }
```

### JSON Web Key (JWK)

JWK is a JSON structure representing a cryptographic key. Currently only supports RSA public keys.
Expand Down
1 change: 1 addition & 0 deletions lib/jwt/decode.rb
Expand Up @@ -71,6 +71,7 @@ def find_key(&keyfinder)

def verify_claims
Verify.verify_claims(payload, @options)
Verify.verify_required_claims(payload, @options)
end

def validate_segment_count!
Expand Down
3 changes: 2 additions & 1 deletion lib/jwt/default_options.rb
Expand Up @@ -9,7 +9,8 @@ module DefaultOptions
verify_aud: false,
verify_sub: false,
leeway: 0,
algorithms: ['HS256']
algorithms: ['HS256'],
required_claims: []
}.freeze
end
end
1 change: 1 addition & 0 deletions lib/jwt/error.rb
Expand Up @@ -15,6 +15,7 @@ class InvalidAudError < DecodeError; end
class InvalidSubError < DecodeError; end
class InvalidJtiError < DecodeError; end
class InvalidPayload < DecodeError; end
class MissingRequiredClaim < DecodeError; end

class JWKError < DecodeError; end
end
9 changes: 8 additions & 1 deletion lib/jwt/verify.rb
Expand Up @@ -10,7 +10,7 @@ class Verify
}.freeze

class << self
%w[verify_aud verify_expiration verify_iat verify_iss verify_jti verify_not_before verify_sub].each do |method_name|
%w[verify_aud verify_expiration verify_iat verify_iss verify_jti verify_not_before verify_sub verify_required_claims].each do |method_name|
define_method method_name do |payload, options|
new(payload, options).send(method_name)
end
Expand Down Expand Up @@ -81,6 +81,13 @@ def verify_sub
raise(JWT::InvalidSubError, "Invalid subject. Expected #{options_sub}, received #{sub || '<none>'}") unless sub.to_s == options_sub.to_s
end

def verify_required_claims
return unless (options_required_claims = @options[:required_claims])
options_required_claims.each do |required_claim|
raise(JWT::MissingRequiredClaim, "Missing required claim #{required_claim}") unless @payload.include?(required_claim)
end
end

private

def global_leeway
Expand Down
14 changes: 14 additions & 0 deletions spec/jwt/verify_spec.rb
Expand Up @@ -248,4 +248,18 @@
end
end
end

context '.verify_required_claims(payload, options)' do
it 'must raise JWT::MissingRequiredClaim if a required claim is absent' do
expect do
described_class.verify_required_claims(base_payload, options.merge(required_claims: ['exp']))
end.to raise_error JWT::MissingRequiredClaim
end

it 'must verify the claims if all required claims are present' do
payload = base_payload.merge('exp' => (Time.now.to_i + 5), 'custom_claim' => true)
described_class.verify_required_claims(payload, options.merge(required_claims: ['exp', 'custom_claim']))
end
end

end

0 comments on commit 498d632

Please sign in to comment.