Module: Ibanity::Webhook::Signature

Defined in:
lib/ibanity/webhook.rb

Class Method Summary collapse

Class Method Details

.verify!(payload, signature_header, tolerance) ⇒ Object

Verifies the signature header for a given payload.

Raises an Ibanity::Error in the following cases:

  • the header does not match the expected format

  • the digest does not match the payload

  • the issued at or expiration timestamp is not within the tolerance

  • the audience or issuer does not match the application config

Returns true otherwise

Raises:



28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
# File 'lib/ibanity/webhook.rb', line 28

def self.verify!(payload, signature_header, tolerance)
  begin
    key_details = JOSE::JWT.peek_protected(signature_header).to_hash
    raise unless key_details["alg"] == SIGNING_ALGORITHM && key_details["kid"]
  rescue
    raise Ibanity::Error.new("Key details could not be parsed from the header", nil)
  end

  key = Ibanity.webhook_keys.find { |key| key.kid == key_details["kid"] }

  if key.nil?
    raise Ibanity::Error.new("The key id from the header didn't match an available signing key", nil)
  end
  signer = JOSE::JWK.from(key.to_h {|key, value| [key.to_s, value] })
  verified, claims_string, _jws = JOSE::JWT.verify_strict(signer, [SIGNING_ALGORITHM], signature_header)

  raise Ibanity::Error.new("The signature verification failed", nil) unless verified

  jwt = JOSE::JWT.from(claims_string)

  validate_digest!(jwt, payload)
  validate_issued_at!(jwt, tolerance)
  validate_expiration!(jwt, tolerance)
  validate_issuer!(jwt)
  validate_audience!(jwt)

  true
end