Class: Pagaris::Signature

Inherits:
Object
  • Object
show all
Defined in:
lib/pagaris/signature.rb

Overview

Signatures (SHA256 HMACs) are used inside the ‘Authorization` header of API calls. This class extracts the signature building process.

Constant Summary collapse

HEADER_REGEXP =
/\A(Pagaris\s)?(.+):(.+):(.+)\z/

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(path:, timestamp: Time.now.to_i, body: nil, method: 'POST') ⇒ Signature

Constructs a signature that should be included in the Authorization header of requests made by ‘Client` to the API.

Parameters:

  • path (String)

    The path on your app where this webhook was received. It must match the path of the URL that you set in your Pagaris

  • timestamp (Integer, String) (defaults to: Time.now.to_i)

    Defaults to current time. Seconds since the Unix epoch

  • body (String, NilClass) (defaults to: nil)

    ‘nil` by default. Raw body string.

  • method (String) (defaults to: 'POST')

    ‘’POST’‘ by default, but could be changed (e.g. `’GET’‘)



25
26
27
28
29
# File 'lib/pagaris/signature.rb', line 25

def initialize(path:, timestamp: Time.now.to_i, body: nil, method: 'POST')
  @timestamp = timestamp
  data = "#{@timestamp}-#{method}-#{path}-#{body}"
  @value = OpenSSL::HMAC.hexdigest('SHA256', Pagaris.private_key, data)
end

Instance Attribute Details

#valueObject (readonly)

Returns the value of attribute value.



11
12
13
# File 'lib/pagaris/signature.rb', line 11

def value
  @value
end

Class Method Details

.valid?(header_value:, path:, body:, method: 'POST') ⇒ Boolean

Checks if a given ‘Authorization` header’s value contains a valid signature, by comparing it to an expected signature that would be generated with the configured ‘Pagaris.private_key`. Useful for verifying a signature of a received webhook.

Examples:

Signature.valid?(
  header_value: request.authorization, # e.g. 'Pagaris a:b:c'
  path: request.fullpath, # e.g. '/path/for/receiving/webhooks'
  body: request.raw_post # e.g. '{"order": {"amount": "9876.54"}}'
) # => true or false

Parameters:

  • header_value (String)

    The value of the ‘Authorization` header. It may include the `Pagaris ` prefix as the Authentication type or not.

  • path (String)

    The path on your app where this webhook was received. It must match the path of the URL that you set in your Pagaris Application (e.g. if you use a trailing slash on your Application, you should include it here too).

  • body (String, NilClass)

    Raw body string.

  • method (String) (defaults to: 'POST')

    ‘’POST’‘ by default, but could be changed (e.g. `’GET’‘)

Returns:

  • (Boolean)


63
64
65
66
67
68
69
70
# File 'lib/pagaris/signature.rb', line 63

def self.valid?(header_value:, path:, body:, method: 'POST')
  timestamp, signature = header_value&.match(HEADER_REGEXP)&.captures
    &.[](2..3)

  expected_signature = self.new(timestamp: timestamp, path: path,
    body: body, method: method)
  expected_signature.value == signature
end

Instance Method Details

#header_valueObject

Constructs the value of an ‘Authorization` HTTP header, from its calculated value when initializing, as well as the timestamp that was used to calculate it.



36
37
38
# File 'lib/pagaris/signature.rb', line 36

def header_value
  "Pagaris #{Pagaris.application_id}:#{@timestamp}:#{@value}"
end