Class: Flipper::Cloud::MessageVerifier
- Inherits:
-
Object
- Object
- Flipper::Cloud::MessageVerifier
- Defined in:
- lib/flipper/cloud/message_verifier.rb
Defined Under Namespace
Classes: InvalidSignature
Constant Summary collapse
- DEFAULT_VERSION =
"v1"
Class Method Summary collapse
Instance Method Summary collapse
- #generate(payload, timestamp) ⇒ Object
- #header(signature, timestamp) ⇒ Object
-
#initialize(secret:, version: DEFAULT_VERSION) ⇒ MessageVerifier
constructor
A new instance of MessageVerifier.
-
#verify(payload, header, tolerance: nil) ⇒ Object
Public: Verifies the signature header for a given payload.
Constructor Details
#initialize(secret:, version: DEFAULT_VERSION) ⇒ MessageVerifier
Returns a new instance of MessageVerifier.
17 18 19 20 21 22 23 |
# File 'lib/flipper/cloud/message_verifier.rb', line 17 def initialize(secret:, version: DEFAULT_VERSION) @secret = secret @version = version || DEFAULT_VERSION raise ArgumentError, "secret should be a string" unless @secret.is_a?(String) raise ArgumentError, "version should be a string" unless @version.is_a?(String) end |
Class Method Details
.header(signature, timestamp, version = DEFAULT_VERSION) ⇒ Object
11 12 13 14 15 |
# File 'lib/flipper/cloud/message_verifier.rb', line 11 def self.header(signature, , version = DEFAULT_VERSION) raise ArgumentError, "timestamp should be an instance of Time" unless .is_a?(Time) raise ArgumentError, "signature should be a string" unless signature.is_a?(String) "t=#{.to_i},#{version}=#{signature}" end |
Instance Method Details
#generate(payload, timestamp) ⇒ Object
25 26 27 28 29 30 |
# File 'lib/flipper/cloud/message_verifier.rb', line 25 def generate(payload, ) raise ArgumentError, "timestamp should be an instance of Time" unless .is_a?(Time) raise ArgumentError, "payload should be a string" unless payload.is_a?(String) OpenSSL::HMAC.hexdigest(OpenSSL::Digest.new("sha256"), @secret, "#{.to_i}.#{payload}") end |
#header(signature, timestamp) ⇒ Object
32 33 34 |
# File 'lib/flipper/cloud/message_verifier.rb', line 32 def header(signature, ) self.class.header(signature, , @version) end |
#verify(payload, header, tolerance: nil) ⇒ Object
Public: Verifies the signature header for a given payload.
Raises a InvalidSignature in the following cases:
-
the header does not match the expected format
-
no signatures found with the expected scheme
-
no signatures matching the expected signature
-
a tolerance is provided and the timestamp is not within the tolerance
Returns true otherwise.
46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 |
# File 'lib/flipper/cloud/message_verifier.rb', line 46 def verify(payload, header, tolerance: nil) begin , signatures = (header) rescue StandardError raise InvalidSignature, "Unable to extract timestamp and signatures from header" end if signatures.empty? raise InvalidSignature, "No signatures found with expected version #{@version}" end expected_sig = generate(payload, ) unless signatures.any? { |s| secure_compare(expected_sig, s) } raise InvalidSignature, "No signatures found matching the expected signature for payload" end if tolerance && < Time.now - tolerance raise InvalidSignature, "Timestamp outside the tolerance zone (#{Time.at()})" end true end |