Created
July 14, 2014 14:16
-
-
Save oleriesenberg/43e973ccacfd3c7cf96d to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class ParamsParser | |
def initialize(app, &condition) | |
@app = app | |
@condition = condition | |
end | |
def call(env) | |
request = Rack::Request.new(env) | |
signed_request = request.params["signed_request"] | |
signature, signed_params = signed_request.split('.') | |
# Verify signature | |
unless signed_request_is_valid?(Buddy.current_config['secret'], signature, signed_params) | |
return Rack::Response.new(["Invalid Facebook signature"], 400).finish | |
end | |
# Parse JSON | |
signed_params = Yajl::Parser.new.parse(base64_url_decode(signed_params)) | |
# Add JSON parameters to Rails params | |
signed_params.each do |k,v| | |
request.params[k] = v | |
end | |
@app.call(env) | |
end | |
private | |
def signed_request_is_valid?(secret, signature, params) | |
signature = base64_url_decode(signature) | |
expected_signature = OpenSSL::HMAC.digest('SHA256', secret, params.tr("-_", "+/")) | |
return signature == expected_signature | |
end | |
# Stolen from mini_fb. | |
# Ruby's implementation of base64 decoding reads the string in multiples of 6 and ignores any extra bytes. | |
# Since facebook does not take this into account, this function fills any string with white spaces up to | |
# the point where it becomes divisible by 6, then it replaces '-' with '+' and '_' with '/' (URL-safe decoding), | |
# and decodes the result. | |
def base64_url_decode(str) | |
str = str + "=" * (6 - str.size % 6) unless str.size % 6 == 0 | |
return Base64.decode64(str.tr("-_", "+/")) | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment