Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Decoding Facebook's signed request in Ruby/Sinatra

Due to Facebook deprecating new FBML, I'm looking for a new way to create a "reveal" tab (a page tab that shows one version to fans and another to non-fans). Facebook has added data to the signed_request:

When a user selects your app in the left-hand menu, the app will receive the signed_request parameter with one additional parameter, page, a JSON array which contains the ‘id’ of the Facebook Page your Tab is hosted within, a boolean (‘liked’) indicating whether or not a user has liked the Page, and a boolean (‘admin’) indicating whether or not the user is an ‘admin’ of the Page along with the user info array.

I'm able to read the signed_request fine, but then I need to process it with base64url decoding to get the correct JSON. Additionally, I've found in my research that the JSON is improperly formatted for Ruby so needs to be modified prior to decoding it. Here's the current code (I'm just printing the signed request in index.erb for now):

helpers do
  def base64_url_decode str
    encoded_str = str.gsub('-','+').gsub('_','/')
    encoded_str += '=' while !(encoded_str.size % 4).zero?
    Base64.decode64(encoded_str)
  end

  def decode_data str
    encoded_sig, payload = str.split('.')
    data = ActiveSupport::JSON.decode base64_url_decode(payload)
  end
end

get '/' do
  signed_request = params[:signed_request]
  @signed_request = decode_data(signed_request)
  erb :index
end

I'm trying to keep the application as light as possible and avoid using a full Facebook library as this won't be a full application (just a tab) and won't require any additional permissions from users. Any recommendations as to my method for detecting fans are welcome as well.

like image 200
Anders H Avatar asked Feb 14 '11 00:02

Anders H


2 Answers

I've run into this before. You just need to pad the end of the payload string with = marks until its length is divisible by 4.

This will work:

payload += '=' * (4 - payload.length.modulo(4))

(I'm not sure where/if this is documented by Facebook, but someone on IRC told me about it in early 2011, and sure enough, I've since found such padding in the source code of various Facebook client libraries)

like image 187
Kyle Wild Avatar answered Sep 30 '22 14:09

Kyle Wild


I use fbgraph library which has working parse_signed_request method.

like image 30
Mika Tuupola Avatar answered Sep 30 '22 15:09

Mika Tuupola