-
Notifications
You must be signed in to change notification settings - Fork 374
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #130 from tpickett66/hash-keys
Allow string hash keys in validation configurations
- Loading branch information
Showing
9 changed files
with
265 additions
and
243 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
module JWT | ||
class DecodeError < StandardError; end | ||
class VerificationError < DecodeError; end | ||
class ExpiredSignature < DecodeError; end | ||
class IncorrectAlgorithm < DecodeError; end | ||
class ImmatureSignature < DecodeError; end | ||
class InvalidIssuerError < DecodeError; end | ||
class InvalidIatError < DecodeError; end | ||
class InvalidAudError < DecodeError; end | ||
class InvalidSubError < DecodeError; end | ||
class InvalidJtiError < DecodeError; end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,73 +1,98 @@ | ||
require 'jwt/error' | ||
|
||
module JWT | ||
# JWT verify methods | ||
module Verify | ||
def self.verify_expiration(payload, options) | ||
return unless payload.include?('exp') | ||
|
||
if payload['exp'].to_i < (Time.now.to_i - options[:leeway]) | ||
fail(JWT::ExpiredSignature, 'Signature has expired') | ||
class Verify | ||
class << self | ||
%i[verify_aud verify_expiration verify_iat verify_iss verify_jti verify_not_before verify_sub].each do |method_name| | ||
define_method method_name do |payload, options| | ||
new(payload, options).send(method_name) | ||
end | ||
end | ||
end | ||
|
||
def self.verify_not_before(payload, options) | ||
return unless payload.include?('nbf') | ||
|
||
if payload['nbf'].to_i > (Time.now.to_i + options[:leeway]) | ||
fail(JWT::ImmatureSignature, 'Signature nbf has not been reached') | ||
end | ||
def initialize(payload, options) | ||
@payload = payload | ||
@options = options | ||
end | ||
|
||
def self.verify_iss(payload, options) | ||
return unless options[:iss] | ||
def verify_aud | ||
return unless options_aud = extract_option(:aud) | ||
|
||
if payload['iss'].to_s != options[:iss].to_s | ||
if @payload['aud'].is_a?(Array) | ||
fail( | ||
JWT::InvalidIssuerError, | ||
"Invalid issuer. Expected #{options[:iss]}, received #{payload['iss'] || '<none>'}" | ||
) | ||
JWT::InvalidAudError, | ||
'Invalid audience' | ||
) unless @payload['aud'].include?(options_aud.to_s) | ||
else | ||
fail( | ||
JWT::InvalidAudError, | ||
"Invalid audience. Expected #{options_aud}, received #{@payload['aud'] || '<none>'}" | ||
) unless @payload['aud'].to_s == options_aud.to_s | ||
end | ||
end | ||
|
||
def self.verify_iat(payload, options) | ||
return unless payload.include?('iat') | ||
def verify_expiration | ||
return unless @payload.include?('exp') | ||
|
||
if !(payload['iat'].is_a?(Integer)) || payload['iat'].to_i > (Time.now.to_i + options[:leeway]) | ||
fail(JWT::InvalidIatError, 'Invalid iat') | ||
if @payload['exp'].to_i < (Time.now.to_i - leeway) | ||
fail(JWT::ExpiredSignature, 'Signature has expired') | ||
end | ||
end | ||
|
||
def self.verify_jti(payload, _options) | ||
if _options[:verify_jti].class == Proc | ||
fail(JWT::InvalidJtiError, 'Invalid jti') unless _options[:verify_jti].call(payload['jti']) | ||
else | ||
fail(JWT::InvalidJtiError, 'Missing jti') if payload['jti'].to_s == '' | ||
def verify_iat | ||
return unless @payload.include?('iat') | ||
|
||
if !(@payload['iat'].is_a?(Integer)) || @payload['iat'].to_i > (Time.now.to_i + leeway) | ||
fail(JWT::InvalidIatError, 'Invalid iat') | ||
end | ||
end | ||
|
||
def self.verify_aud(payload, options) | ||
return unless options[:aud] | ||
def verify_iss | ||
return unless options_iss = extract_option(:iss) | ||
|
||
if payload[:aud].is_a?(Array) | ||
if @payload['iss'].to_s != options_iss.to_s | ||
fail( | ||
JWT::InvalidAudError, | ||
'Invalid audience' | ||
) unless payload['aud'].include?(options[:aud].to_s) | ||
JWT::InvalidIssuerError, | ||
"Invalid issuer. Expected #{options_iss}, received #{@payload['iss'] || '<none>'}" | ||
) | ||
end | ||
end | ||
|
||
def verify_jti | ||
options_verify_jti = extract_option(:verify_jti) | ||
if options_verify_jti.respond_to?(:call) | ||
fail(JWT::InvalidJtiError, 'Invalid jti') unless options_verify_jti.call(@payload['jti']) | ||
else | ||
fail( | ||
JWT::InvalidAudError, | ||
"Invalid audience. Expected #{options[:aud]}, received #{payload['aud'] || '<none>'}" | ||
) unless payload['aud'].to_s == options[:aud].to_s | ||
fail(JWT::InvalidJtiError, 'Missing jti') if @payload['jti'].to_s.strip.empty? | ||
end | ||
end | ||
|
||
def self.verify_sub(payload, options) | ||
return unless options[:sub] | ||
def verify_not_before | ||
return unless @payload.include?('nbf') | ||
|
||
if @payload['nbf'].to_i > (Time.now.to_i + leeway) | ||
fail(JWT::ImmatureSignature, 'Signature nbf has not been reached') | ||
end | ||
end | ||
|
||
def verify_sub | ||
return unless options_sub = extract_option(:sub) | ||
|
||
fail( | ||
JWT::InvalidSubError, | ||
"Invalid subject. Expected #{options[:sub]}, received #{payload['sub'] || '<none>'}" | ||
) unless payload['sub'].to_s == options[:sub].to_s | ||
"Invalid subject. Expected #{options_sub}, received #{@payload['sub'] || '<none>'}" | ||
) unless @payload['sub'].to_s == options_sub.to_s | ||
end | ||
|
||
private | ||
|
||
def extract_option(key) | ||
@options.values_at(key.to_sym, key.to_s).compact.first | ||
end | ||
|
||
def leeway | ||
extract_option :leeway | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.