Class: StraightServer::SignatureValidator

Inherits:
Object
  • Object
show all
Includes:
Goliath::Constants
Defined in:
lib/straight-server/signature_validator.rb

Constant Summary collapse

SignatureValidatorError =
Class.new(StandardError)
InvalidNonce =
Class.new(SignatureValidatorError)
InvalidSignature =
Class.new(SignatureValidatorError)

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(gateway, env) ⇒ SignatureValidator

Returns a new instance of SignatureValidator.



14
15
16
17
# File 'lib/straight-server/signature_validator.rb', line 14

def initialize(gateway, env)
  @gateway = gateway
  @env     = env
end

Instance Attribute Details

#envObject (readonly)

Returns the value of attribute env.



12
13
14
# File 'lib/straight-server/signature_validator.rb', line 12

def env
  @env
end

#gatewayObject (readonly)

Returns the value of attribute gateway.



12
13
14
# File 'lib/straight-server/signature_validator.rb', line 12

def gateway
  @gateway
end

Class Method Details

.signature(nonce:, body:, method:, request_uri:, secret:) ⇒ Object

Should mirror StraightServerKit.signature



63
64
65
66
67
# File 'lib/straight-server/signature_validator.rb', line 63

def self.signature(nonce:, body:, method:, request_uri:, secret:)
  sha512  = OpenSSL::Digest::SHA512.new
  request = "#{method.to_s.upcase}#{request_uri}#{sha512.digest("#{nonce}#{body}")}"
  Base64.strict_encode64 OpenSSL::HMAC.digest(sha512, secret.to_s, request)
end

Instance Method Details

#last_nonce_keyObject



48
49
50
# File 'lib/straight-server/signature_validator.rb', line 48

def last_nonce_key
  "#{Config[:'redis.prefix']}:LastNonce:#{gateway.id}"
end

#signatureObject



52
53
54
55
56
57
58
59
60
# File 'lib/straight-server/signature_validator.rb', line 52

def signature
  self.class.signature(
    nonce:       env["#{HTTP_PREFIX}X_NONCE"],
    body:        env[RACK_INPUT].kind_of?(StringIO) ? env[RACK_INPUT].string : env[RACK_INPUT].to_s,
    method:      env[REQUEST_METHOD],
    request_uri: env[REQUEST_URI],
    secret:      gateway.secret,
  )
end

#valid_nonce?Boolean

Returns:

  • (Boolean)


25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
# File 'lib/straight-server/signature_validator.rb', line 25

def valid_nonce?
  nonce = env["#{HTTP_PREFIX}X_NONCE"].to_i
  redis = StraightServer.redis_connection
  loop do
    redis.watch last_nonce_key do
      last_nonce = redis.get(last_nonce_key).to_i
      if last_nonce < nonce
        result = redis.multi do |multi|
          multi.set last_nonce_key, nonce
        end
        return true if result[0] == 'OK'
      else
        redis.unwatch
        return false
      end
    end
  end
end

#valid_signature?Boolean

Returns:

  • (Boolean)


44
45
46
# File 'lib/straight-server/signature_validator.rb', line 44

def valid_signature?
  signature == env["#{HTTP_PREFIX}X_SIGNATURE"]
end

#validate!Object

Raises:



19
20
21
22
23
# File 'lib/straight-server/signature_validator.rb', line 19

def validate!
  raise InvalidNonce unless valid_nonce?
  raise InvalidSignature unless valid_signature?
  true
end