I'm developing a Facebook app on CakePHP framework and I'm trying to do one simple thing:
// get user
$user = $this->Facebook->api('/me');
// store the user id into session
$this->Session->write('User.id', $user['id']);
But as soon as I change page the session is lost in Safari and I cannot get the id from the session no matter what.
I have found numerous solutions here and on other forums tried them all, but I haven't managed to solve this problem. Nothing works for me or I have been doing it wrong... Anyone managed to found a working solution for this?
Any help would be really appreciated, thnx.
This is the proper code which you can download from github
//Example AppController setup
public $components = array('Session',
'Auth' => array(
'authenticate' => array(
'Form' => array(
'fields' => array('username' => 'email')
)
),
'authorize' => 'Controller'
),
'Facebook.Connect' => array('model' => 'User')
);
https://github.com/webtechnick/CakePHP-Facebook-Plugin
I have found a solution. The problem is Safari cookie policy, user has to change to allow all cookies in their Safari settings.
But I have figured out that if I first reload the page outside the facebook iframe and set the session there, the session remains the same even inside the facebook iframe.
So I created another controller action just to start a new session and store its id inside the session for later use:
public function safari_session_hack()
{
$app_url = "app_url"; // the full url of your app on facebook
session_start();
$this->Session->write('Session.id', session_id());
die(header("Location:" . $app_url)); // redirect back to the FB app
}
Then on my FB app landing page I have this code:
// Session fix for Safari
if (!$this->Session->read('Session.id') && strpos($_SERVER['HTTP_USER_AGENT'], 'Safari')) {
echo '<script>top.location.href="' . Router::fullbaseUrl() . Router::url(array('controller' => 'main', 'action' => 'safari_session_hack')) . '"</script>';
die;
}
All it does is it checks if the session id is not set and if the browser is Safari. Then it redirects to the safari_session_hack() action, starts the session on the outside page, saves its id inside the session and redirects back to the page.
Now everything works fine and the session is not being lost or destroyed between pages, so you can do user login and other stuff that requires session data inside your FB app.
Related
I'm using the Webtechnick CakePHP-Facebook-Plugin in order to log my users into my CakePHP application, I need to get their user_relationship, user_relationship_details, user_religion_politics and email.
Im using something kike this to invoke the login button
echo $this->Facebook->login(array('perms' => 'email,user_religion_politics,user_relationships,user_relationship_details', 'redirect' => array('controller' => 'users', 'action' => 'facebook'), 'label' => __('<span class="icon-facebook-sign"></span> Login with facebook',true),'id' => 'facebook_btn' ));
And also in facebook on "App details" in the "Configure App Center Permissions" section I'm adding the permissions too, but its not working, when a user login into the app facebook is still requesting the default perms (public profile, friends list and email).
I solved it, It seems that I was missing $options parameter on my init function.
So I changed the call in my default.ctp file
from
$this->Facebook->init();
to
$this->Facebook->init(array('perms' => 'email,user_religion_politics,user_relationships,user_relationship_details'));
I solved it, It seems that I was missing $options parameter on my init function.
So I changed the call in my default.ctp file
from
$this->Facebook->init();
to
$this->Facebook->init(array('perms' => 'email,user_religion_politics,user_relationships,user_relationship_details'));
I've been working on a way to determine if a user likes a particular page so a tab on that page can be fangated or not. I didn't want to prompt the user for authorization for user_likes, so I avoided the JS SDK and used the PHP SDK:
<?php
require 'src/facebook.php';
$app_id = "...";
$app_secret = "...";
$facebook = new Facebook(array('appId' => $app_id, 'secret' => $app_secret, 'cookie' => true));
$signed_request = $facebook->getSignedRequest();
$like_status = $signed_request["page"]["liked"];
/* testing response */
if ($like_status) {
/* liked content */
} else {
/* not liked content */
}
?>
My problem is signed_request is passed only when the code is on the FB tab--if I hit the PHP page outside of FB, I get nothing. I wondered if there's a way to get this user info outside of Facebook.com.
You can try saving the signed_request in a session or cookie so you can use it until it expires. After which, the user will have to come through the tab again to renew it. Naturally, if you are planning to use cookies, you should keep the signed_request decoded so no one can find and use the access_token from the cookie.
Sounds like this isn't really feasible outside of the Facebook tab. We've begun deploying our tabs in PHP in order to pull this data without an action on the user's part.
Thanks!
I'm trying to redirect users to the facebook login page then back to my app without the Log In to app page displaying. Is this possible?
I've looked into the "next" parameter which is automatically generated by the PHP-SDK but cannot seem to change it.
Is there anyway to do what I'm looking for? I want to make sure users are logged in in order to check to see if they have authed my app but do not want them to if they are not already.
Thanks for any help!
No, i don't think it is possible to modify the next parameter. The only place where i saw the next parameter(in the PHP SDK) is in the getLogoutUrl() function, as seen in the source of the base_facebook.php. And that parameter defines which url to go, after logout.
For getLoginUrl() in the base_facebook.php file, we have
return $this->getUrl(
'www',
'dialog/oauth',
array_merge(array(
'client_id' => $this->getAppId(),
'redirect_uri' => $currentUrl, // possibly overwritten
'state' => $this->state),
$params));
as the last line in the function, which obviously means that the oauth-dialog will be shown, no matter what you try.
If your app is not on Facebook, then you can go for <fb:login-button>Login with Facebook</fb:login-button> in Javascript, and subsequently follow the example from this url. You'll see there that it's not possible to remove that dialog entirely, even if you don't ask for any permissions.
The Javascript SDK's FB.login() method will also bring up the auth dialog.
Hope this helps.
They have to accept permissions for the first time only. Facebook will never let you to get user's data without their knowledge/accept
If you are using php :
// Create our Application instance.
$facebook = new Facebook(array(
'appId' => $fbconfig['appid'],
'secret' => $fbconfig['secret'],
'cookie' => true
));
//Facebook Authentication part
$user = $facebook->getUser();
if (!$user) {
// user is not logged on --> redirect to the login url
} else {
// user is logged on you can do what you want
}
Hopefully this should be quick and easy.
session_start();
include("facebook.php");
$facebook = new Facebook(array(
'appId'=>'xxxxx50274xxxxx',
'secret'=>'xxxxxb932d62fbc6287feb18e5exxxxx',
'cookie'=>true
));
$fbuser = $facebook->getUser();
if (empty($fbuser)){
$fbloginurl=$facebook->getLoginURL();
echo "<html><body><a href='$fbloginurl'>Click</a></body></html>
} else {
die("Authenticated");
}
In this example, the first time I click the link to give permissions to the app to access my FB account, everything works fine. I can keep refreshing the page, and I get the "Authenticated" confirmation.
However, every time I restart the browser (starting a new session), it doesn't authenticate the app automatically and I have to click the link again. Of course as soon as I click the link I am immediately redirected back to the source page and presented with the "Authenticated" confirmation.
Is there any way of not having to click the authentication link during new browser sessions and have it authenticate automatically? I need to do this without a PHP Header directive, as I want the first time the user gives permissions to the app to be triggered by a manual click.
My FB login is persistent ("stay logged in" option is checked).
Thanks a lot for any help.
If I am understanding your scenario correctly (this is not an iframe app, correct?), this is all down to losing the website session cookie when the browser is closed. Once that cookie is gone, there is nothing to identify the user to your server-side code and so no way to know if the user has previously authorized your app.
You need to find a way to persistently identify the user, or at least identify that he has already given permissions. The simplest way would probably be to set your own (permanent) cookie once the user has first authenticated. Then whenever the session cookie is lost, check the presence of the permanent cookie and if it's there, do a PHP redirect to Facebook (which will be invisible to the user). If there is no cookie, present the HTML link to the user like you are doing now.
Comparing it to my code, the only difference I see is that I check to see if $fbuser is valid - if it isn't send me to the login screen. I'm also using top.location.href.
// Login or logout url will be needed depending on current user state.
if ($fbuser) {
$logoutUrl = $facebook->getLogoutUrl();
}
else {
$loginUrl = $facebook->getLoginUrl(array('scope' => 'publish_actions', 'canvas' => 1, 'fbconnect' => 0, 'redirect_uri'=>config_item('facebook_url').$pf));
echo "<html><body><script> top.location.href='" . $loginUrl . "'</script></body></html>";
exit(0);
}
Hope that helps.
We redirect users to below URL on mobile phones for application authorisation:
https://m.facebook.com/dialog/oauth?client_id=XXXXXX&redirect_uri=http://www.server.com/callback.php&scope=offline_access,user_likes,publish_stream,publish_checkins,user_checkins&display=wap
If the user is logged in to Facebook on his/her phone, no problem, Facebook automatically redirects to oauth dialog page.
If user is not logged in, Facebook asks them to login first.
On wap site(A Nokia phone), it redirects to oauth dialog without any problem after login.
But on touch site(An iPhone), it add hastags to URL, redirects user to his/her Facebook homepage.
Even display=wap parameter on URL doesn't help on this issue.
Any ideas on how to solve this problem?
Thank you
Actually, here's a cleaner solution. (I hadn't seen the API for getLoginUrl at the time of my previous post. http://developers.facebook.com/docs/reference/php/facebook-getLoginUrl)
require_once("facebook.php");
$config = array(
"appId" => APP_ID,
"secret" => APP_SECRET
);
$facebook = new Facebook($config);
$params = array(
"scope" => "offline_access,user_likes,publish_stream,publish_checkins,user_checkins",
"redirect_uri" => "http://www.server.com/callback.php",
"display" => "touch"
);
$url = $facebook->getLoginUrl($params);
header("Location: $url");
I experienced the same problem and had troubles isolating it since it worked in Chrome on the desktop but not while using the iPhone's Safari browser.
I did a urlencode around the redirect_url parameter and set display to touch. So to use your link above as an example, I'd try this:
https://m.facebook.com/dialog/oauth?client_id=XXXXXX&redirect_uri=http%3A%2F%2Fwww.server.com%2Fcallback.php&scope=offline_access,user_likes,publish_stream,publish_checkins,user_checkins&display=touch
I sincerely hope that works for you. It seemed to have brought me luck.