Skip to content

Instantly share code, notes, and snippets.

@jugyo
Created February 6, 2012 10:25
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jugyo/1751353 to your computer and use it in GitHub Desktop.
Save jugyo/1751353 to your computer and use it in GitHub Desktop.
the rack middleware that handle the facebook signed request
require 'base64'
require 'openssl'
# This is inspired by [rack-facebook-signed-request](https://github.com/gamesthatgive/rack-facebook-signed-request)
#
# Usage
#
# use Rack::FBSignedRequest, :secret => 'SECRET'
#
class Rack::FBSignedRequest
def initialize(app, options)
@app = app
@options = options
end
def call(env)
@request = Rack::Request.new(env)
if @request.POST['signed_request']
if facebook_params = parse_signed_request(@request.params['signed_request'])
@request.params['facebook_params'] = facebook_params
env['rack.request.query_hash'] = @request.params
env['REQUEST_METHOD'] = 'GET'
end
end
@app.call(env)
end
private
# The following code from omniauth
def parse_signed_request(value)
signature, encoded_payload = value.split('.')
decoded_hex_signature = base64_decode_url(signature)
decoded_payload = ActiveSupport::JSON.decode(base64_decode_url(encoded_payload))
unless decoded_payload['algorithm'] == 'HMAC-SHA256'
raise NotImplementedError, "unkown algorithm: #{decoded_payload['algorithm']}"
end
if valid_signature?(@options[:secret], decoded_hex_signature, encoded_payload)
decoded_payload
end
end
def valid_signature?(secret, 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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment