2011-06-21 10 views
2

CakePHP、Authコンポーネント、WebTechNickのFacebook plugin、キャンバスページのOAuth(私はFacebookデベロッパーアプリオプションでこれを有効にしています)を使用して、FacebookのiFrame Canvasアプリケーションを開発しています。 http://apps.facebook.com/myapp/にアクセスするか、プロフィールのタブとしてユーザーにプロファイルに追加した後にアプリケーションを使用できるようにしたいと考えています(emailpublish_streamのアクセス許可を要求してください)。Facebookのsigned_requestをiFrame Canvasアプリケーション用に処理するにはどうすればよいですか?

アクセス許可を要求することは問題ではありません。ユーザーは、アクセス許可要求ページにリダイレクトされ、次にtutorialとしてaccess_tokenを要求するコールバックメソッドにリダイレクトされます。

このコールバックの後、ユーザーはhttp://apps.facebook.com/myapp/にリダイレクトされ、個人用インデックスページが表示されます。これは、問題が始まる場所でもあります。前述のURIがロードされるとすぐに、ブラウザはフォームの再送信を要求します。これは、http://apps.facebook.com/myapp/をリロードするたびに発生します。これは、Facebookが(予想される)signed_requestパラメータを渡そうとしているためです。私はそれをどうすればいいのでしょうか。これは空の変数ではないので、別の検証方法やリダイレクトが必要なのでしょうか?

signed_requestパラメータの手順をどのように扱うべきですか、さらに重要なのは、このフォームの再送信ダイアログを削除する方法ですか?

私の方法のいくつかは、過去のすべての実験のためにちょっと混乱するかもしれません。

beforeFilterlogincallback方法は、私のUserController.phpに:loginメソッドでJavaScriptを有効にしてjQueryの関数を参照

function beforeFilter() { 
    parent::beforeFilter(); 
    if (empty($this->permissions)) { 
     $this->Auth->allow('login', 'logout', 'callback'); 
    } 
    } 

    function login() { 
    $session = $this->facebook->getSession(); 
    $login_url = 'https://graph.facebook.com/oauth/authorize?client_id=' . FACEBOOK_APP_ID . '&redirect_uri=' . MY_APP_URL . '/users/callback/&type=user_agent&&display=page&scope=' . FACEBOOK_APP_PERMISSIONS; 
    if($session){ 
     try { 
     $uid = $facebook_client->getUser(); 
     $me = $facebook_client->api('/me', $params); 
     print($me); 
     } catch (FacebookApiException $e) { 
     error_log($e); 
     } 
     } else { 
     $this->set('authorise', true); 
     $script = '$(document).ready(function() { facebookRequestPermissions("'.$login_url.'");});'; 
     $this->set('script', $script); 
     } 
    } 

    function callback() { 
    function callFb($url, $params) { 
     $ch = curl_init(); 
     curl_setopt_array($ch, array(
      CURLOPT_URL => $url, 
      CURLOPT_POSTFIELDS => http_build_query($params), 
      CURLOPT_RETURNTRANSFER => true, 
      CURLOPT_VERBOSE => true 
     )); 
     $result = curl_exec($ch); 
     curl_close($ch); 
     return $result; 
    } 

    $params=array('client_id'=>FACEBOOK_APP_ID, 'type'=>'client_cred', 'client_secret'=>FACEBOOK_APP_SECRET); 
    $url = "https://graph.facebook.com/oauth/access_token"; 
    $access_token = callFb($url, $params); 
    $access_token = substr($access_token, strpos($access_token, "=")+1, strlen($access_token)); 

    if ($access_token) { 
     $this->redirect(FACEBOOK_APP_URL); 
    } else { 
     echo 'An error has occurred'; 
    } 
    } 

は、FacebookのJavaScriptのSDKは$(document).ready()に初期化される:

function facebookRequestPermissions(login_url) { 
    FB.getLoginStatus(function(response) { 
    if (response.status !== 'unknown') { 
     top.location.href=login_url; 
    } 
    }); 
} 

JavaScript関数は、ユーザーがログインしているときにのみ起動する必要があります。ログインしていない場合は、別のランディングページが表示されます。

私は、全体のAppControlerでいくつかのメソッドを使用します。

class AppController extends Controller { 
    var $components = array('RequestHandler', 'Session', 'Auth', 'Facebook.Connect'); 
    var $helpers = array('Form', 'Time','Html','Javascript', 'Session', 'Facebook.Facebook'); 
    protected $facebook; 
    protected $permissions; 
    private $user; 

    function beforeRender() { 
    //Save the username if it isn't already present 
    if ((int)$this->Auth->user('id') != '' && (string)$this->Auth->user('username') == '') { 
     $data = array('id' => (int)$this->Auth->user('id'), 'username' => (string)$this->user['username']); 
     $this->loadModel('User'); 
     $this->User->save($data); 
    } 
    if (!empty($this->user) && !empty($this->permissions)) { 
     $this->set('currentUser', $this->Auth->user()); 
    } 
    } 

    function beforeFilter() { 
    $this->Auth->autoRedirect = false; 
    $this->Auth->loginAction = array('controller' => 'users', 'action' => 'login'); 
    $this->Auth->loginRedirect = array('controller' => 'users', 'action' => 'index'); 
    $this->Auth->logoutRedirect = array('controller' => 'users', 'action' => 'login'); 
    App::import('Lib', 'Facebook.FB'); 
    $this->facebook = new FB(); 
    $this->user = $this->facebook->api('/me'); 
    $this->permissions = $this->facebook->api('/me/permissions'); 
    } 
} 

EDIT: これはFirefoxのみで問題だが。 Chromeではダイアログは表示されませんが、代わりにsigned_requestのパラメータが空白であることがわかっています。これはFirefoxでは当てはまりませんが、signed_requestのパラメータは、(iFrameのコンテンツがキャッシュされていない限り)すべてのプロンプトの更新後も変わらず、無限にループしています。

EDIT 2: まだこれに苦しんで、私は、フォームの再提出の問題を解決したFacebookの開発者アプリケーションでキャンバスオプションののOAuth 2.0を無効にすることになりました。もちろん、これは本当の解決策ではありません。なぜなら、OAuth 2.0はFacebookのキャンバスアプリケーションの必須要素となっているからです。

答えて

1

私はすべてのことをテストすることができませんので、これが正しいかどうかはわかりませんが、最初の視点ではJavaScriptの機能は私にとって奇妙に見えます。ユーザーが許可を与えても、ログインURLに常にリダイレクトされるようです。Facebook JavaScript SDKに参照のうえ

、関数は次のようになります。

function facebookRequestPermissions(login_url) { 
    FB.getLoginStatus(function(response) { 
    if (!response.session) { 
     top.location.href=login_url; 
    } 
    }); 
} 

か、あなたは.statusをコールする場合:

if (response.status == 'unknown') 

signed_requestに関するご質問について:取得するために使用されますいくつかの情報、Authentication - Signed Requestを見て、正確に何かを見てください。別の検証方法は必要ありません。

+0

あなたは、機能がそれを見ていないように見えることは間違いありません。ユーザーがログインしていないときは、「不明」ステータスが返されます。ユーザーがFacebookにログインしてアプリケーションを追加していない場合にのみ、アプリケーションをリダイレクトします。ユーザーが既にアプリケーションを追加したときにJS関数が起動されず、ユーザーがログインしていないときにリダイレクトされません。この関数を使用しても、フォーム再送信ダイアログは削除されません。 – mensch

関連する問題