Facebook 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.
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:
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.
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.