Facebook Graph API with FBML Canvas Apps
PublishedFacebook is now sending a new parameter to canvas applications, signed_request.
This parameter is the concatenation of a JSON object and a signature, both Base64 encoded.
The JSON object contains 4 other parameters:
| user_id | ID of the logged in user | |
| oauth_token | The users OAuth access token | |
| expires | When the token expires | |
| profile_id | ID of the profile when rendered in tab |
The signature is a HMAC-SHA265 of the JSON and is needed to verify that the request originates from Facebook.
With this new parameter it’s finally possible to use the Graph API in an affordably way with FBML apps.
Just store the access token in your users session and pass it along with your Graph API requests.
Parsing signed_request
I implemented support for the signed_request to my Facebook library for Rails.
The code I’m using for verifying the signature and adding the JSON params to the Rails params via Rack middleware looks like this (extract):
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
Using the Graph API
Using the Graph API is just as simple as this:
curl https://graph.facebook.com/me?access_token=YOUR_TOKEN
This will respond with a JSON object containing your basic user info.
Talking to the Graph API with Ruby / HTTParty is not much more complicated then using curl:
HTTParty.get("https://graph.facebook.com/me", :access_token => "YOUR TOKEN")
Old params deprecation
In the future Facebook will deprecate all other parameters than signed_request, but there’s no exact timing right now.
There’s some official documentation on how to migrate from the old params to signed_request available at developers.facebook.com.
UPDATE 2010-07-26
Facebook silently stopped sending the signed_request parameter.
You can enable them again by activating the “OAuth 2.0 for Canvas (beta)” migration in you app settings on Facebook, but this disables all other parameters. So make sure to migrate your app to only rely on signed_request.