1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 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
|
require 'openssl'
module OmniAuth
module Facebook
class SignedRequest
class UnknownSignatureAlgorithmError < NotImplementedError; end
SUPPORTED_ALGORITHM = 'HMAC-SHA256'
attr_reader :value, :secret
def self.parse(value, secret)
new(value, secret).payload
end
def initialize(value, secret)
@value = value
@secret = secret
end
def payload
@payload ||= parse_signed_request
end
private
def parse_signed_request
signature, encoded_payload = value.split('.')
return if signature.nil?
decoded_hex_signature = base64_decode_url(signature)
decoded_payload = JSON.parse(base64_decode_url(encoded_payload))
unless decoded_payload['algorithm'] == SUPPORTED_ALGORITHM
raise UnknownSignatureAlgorithmError, "unknown algorithm: #{decoded_payload['algorithm']}"
end
if valid_signature?(decoded_hex_signature, encoded_payload)
decoded_payload
end
end
def valid_signature?(signature, payload, algorithm = OpenSSL::Digest::SHA256.new)
OpenSSL::HMAC.digest(algorithm, secret, payload) == signature
end
def base64_decode_url(value)
value += '=' * (4 - value.size.modulo(4))
Base64.decode64(value.tr('-_', '+/'))
end
end
end
end
|