Reputation: 481
I created a sinatra based facebook app on Heroku by initiating it with the feature provided by Facebook (Get Cloud App or something like that). Everything worked fine, but when I tried to use the Scores from Facebook, I realized that the Facebook API used by Heroku (which is Mogli) does not support Scores. So I tried to rewrite the code to use fb_graph. But since that created more confusion than everything I started with an empty file. But I just can't make it work.
So basically I would like a simple example for a Sinatra based app on heroku which uses fb_graph. The samples should only contain authentication, since everything else seems pretty straight forward and has a lot of documentation. Just the initial authentication just doesn't work.
I would like to use the default oauth2 approach with the callback, since it just feels more natural to me, but I'm open for everything. I know there is a Rails example, but I just can't get my head around it and since my app will be very simple Rails seems a bit overpowered.
It would be great if anyone could give me just the few lines necessary for what I would like to do!
Upvotes: 0
Views: 390
Reputation: 1106
I've found this to be a bit of a mess. Old tutorials and code just don't make sense anymore.
You can use the Heroku + Facebook OmniAuth example to do an external website (not a canvas app) that does server-side Facebook (and many others) authentication.
When you do that, OmniAuth will provide you with the token you need you need to pass to fb_graph. In the provided example you could add another url:
get '/me' do
me = FbGraph::User.me(session['fb_token']).fetch
"Hello " + me.name
end
For canvas apps, I added the following code to 'rack-facebook-request.rb' to my repo based on this gist
require 'base64'
require 'openssl'
require 'json'
# 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'
puts 'Valid signed request. Changed REQUEST_METHOD to GET.'
if facebook_params['user_id']
env['fb_user_id'] = facebook_params['user_id']
env['fb_access_token'] = facebook_params['oauth_token']
puts 'Request has been authorized.'
else
puts 'Request is not authorized.'
end
else
puts 'Not a valid signed request'
end
else
puts 'Not a signed_request'
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 = JSON(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
This will give you the current fb_user_id and fb_access_token if your app is authorised. Remember that you have to use javascript or a link in the iFrame to request app authorisation in this case.
Upvotes: 1