Я смог заставить это работать безобразно.Было бы замечательно, если бы кто-то, кто имеет больше знаний о внутренней работе этих модулей, предложил бы правильный способ сделать это - есть много способов, которых я просто недостаточно знаю, чтобы обеспечить чистую реализацию.Я установил исправление помощника oauth, чтобы извлечь токен oauth из подписанного запроса.Я все еще не завершил реализацию, так что, возможно, у меня будет больше проблем.Это также может использовать user_id (facebook uid), который включен в подписанный запрос, вместо вызова графа api.
Я обновил это, чтобы включить перенаправление, если пользователь еще не авторизованкак указано здесь:
http://developers.facebook.com/docs/authentication/
"Если объект JSON не содержит параметр user_id, вы должны перенаправить пользователя на экран авторизации приложения в соответствии с обычным веб-приложением OAuth 2.0flow. "
Однако вместо этого отображается логотип facebook со ссылкой на этот URL, а затем выскакивает пользователя из iframe - что-то вроде поражения iframe от facebook, которого, как мне кажется, быть не должно.
module Devise
module Oauth
module InternalHelpers
def callback_action
access_token = nil
if params[:signed_request]
signed_data = FacebookSignedRequest.new(params[:signed_request]).valid?
if signed_data['oauth_token']
access_token = oauth_config.access_token_by_token(signed_data['oauth_token'])
else
return redirect_to oauth_config.authorize_url(:redirect_uri => oauth_redirect_uri)
end
elsif params[:code]
access_token = oauth_config.access_token_by_code(params[:code], oauth_redirect_uri)
else
return redirect_to oauth_config.authorize_url(:redirect_uri => oauth_redirect_uri)
end
self.resource = resource_class.send(oauth_model_callback, access_token, signed_in_resource) if access_token
if resource && resource.persisted? && resource.errors.empty?
set_oauth_flash_message :notice, :success
sign_in_and_redirect resource_name, resource, :event => :authentication
else
session[oauth_session_key] = access_token.token
clean_up_passwords(resource)
render_for_oauth
end
end
def valid_oauth_callback?
return !!params[:signed_request]
end
end
end
end
### For parsing the signed request
require 'base64'
require 'json'
require 'openssl'
# the code is copied from
# http://forum.developers.facebook.net/viewtopic.php?pid=250261
class FacebookSignedRequest
attr_reader :signed_request
def initialize(signed_request)
@signed_request = signed_request
end
def base64_url_decode str
encoded_str = str.gsub('-','+').gsub('_','/')
encoded_str += '=' while !(encoded_str.size % 4).zero?
Base64.decode64(encoded_str)
end
def valid?
secret = "facebook-secret"
#decode data
encoded_sig, payload = signed_request.split('.')
sig = base64_url_decode(encoded_sig).unpack("H*")[0]
data = JSON.parse base64_url_decode(payload)
if data['algorithm'].to_s.upcase != 'HMAC-SHA256'
# Rails.logger.error 'Unknown algorithm. Expected HMAC-SHA256'
return false
end
#check sig
expected_sig = OpenSSL::HMAC.hexdigest('sha256', secret, payload)
if expected_sig != sig
# Rails.logger.error 'Bad Signed JSON signature!'
return false
end
data
end
end