Facebook OpenGraph with Yii Framework - Authentication Issue - php

I am having an issue with the php Facebook sdk.
I have read many posts talking about the same kind of issues (Access token invalid, redirect loop etc...) but none could help.
Briefly, how my project is designed:
It is a Facebook application that is meant to run only with a user logged in Facebook.
Using the Yii Framework, I have created a Filter that is called every time a page is loaded, to ensure that the content is visible only by Facebook logged on users.
It should behave exactly like the application BranchOut on Facebook.
My issue, and how to reproduce it:
I logon to my application using the typical login process from Facebook (OAuth, access token)
I logout manually on the Facebook page, and then try to do a new action on my application
The filter checks if I am logged on Facebook, and because I am not, it redirects me to the Facebook login page.
After I login to Facebook again, I get the typical infinite loop between Facebook and my application's filter.
Here is the code of my filter:
$fb_logged = false;
try
{
$user = Yii::app()->facebook->getUser();
$me = Yii::app()->facebook->api('/me');
$fb_id = $me['id'];
$fb_logged = true;
}
catch (Exception $e)
{
$fb_logged = false;
}
if($fb_logged)
{
print_r($fb_id. ' has logged');
/* Check if user exists on MyApp
... */
}
// If user NOT logged on FB, send him to the FB login page
else
{
$loginUrl = Yii::app()->facebook->getLoginUrl(array(
'redirect_uri' => Yii::app()->getRequest()->getUrl() // I have tried many things here.
));
echo("<script> top.location.href='" . $loginUrl . "'</script>");
Yii::app()->end();
}
What is exactly happening is that after login on FB, the Filter is called again, because a request to the same URL is made. And at that point, the a call the api('/me') generates an exception, because it cannot find any valid access token, and starts looping on it.
I can add that my configuration is good (or seems to be), I have checked all my urls, domain name according to Facebook's app settings.
I have also tried many things like redirecting to a new specific URL, but anyway I need to use the filter as well because I want to make sure this is still the same user (or act consequently if the user has changed).
The only thing that works is to redirect the user to a page that has no Filter (no call to api("/me") is done). And then, clicking by hand to a new link in the application, and there the access token is found. And this is not the behavior I want.
I really hope someone can help me!
Thanks in advance.

After your new login attempt, you should get a new code in the URL that is redirect to. So look for that code parameter, and if it’s there, exchange it for a new access token.

Take a look at the yiiauth extension as well. It was posted just today, and with it you can log in with 29 different providers: Facebook, OpenID, Google, Twitter, Yahoo etc.
It uses the HybridAuth library and AFAICT it makes authentication very easy.

Related

MODx - If not logged in, redirect to a different page

I am in the process of building a website (via MODx), and I don't want "non-logged in" users to be able to see the home page, but instead be redirected to an "under construction" page.
In my snippet, this is what I have so far:
<?php
if (! $modx->user->hasSessionContext($modx->context->get('key')) ) {
$modx->sendRedirect('https://google.com');
} else {
return '';
}
Sadly, this appears to not do anything, regardless of whether or not the user is logged in. (It apppears to be a problem with the second line, the actual redirect worked fine when I tested it)
I am unable to figure out what is wrong, and any help is greatly appreciated!
The snippet that is in the page is [[!notloggedin]]
These are right out of Bob's guides, but basically what you want to do is check to see if the user has an ID or username, if not, they are not logged in.
You probably want to do a bit of digging and see if you can implement your redirect in a plugin rather than a snippet possibly an onRequest event - so you are not rendering the page/resource before you discover that the user needs to be redirected.
There are various methods. One easy method is to use this code:
if ($modx->user->get('username') == '(anonymous)') {
/* user is not logged in */
}
Here is the official method for seeing if the user is logged in to the current context:
if ($modx->user->hasSessionContext($modx->context->get('key'))) {
/* user is logged in */
}
If you know the name of the current context (e.g., web), you can use this method. The name of the context is required:
if $modx->user->isAuthenticated('web') {
/* user is logged in to web context */
}
If your site is simply not yet ready to be publicly available, MODX already allows for this.
See the following System Settings:
site_status
site_unavailable_message
site_unavailable_page
Alternatively, just set all your resources to 'unpublished', except for your custom error page. Logged in users will still be able to view all resources.

facebook getLogoutUrl returns a URL with access_token=0, when clicked redirects to Facebook user's home page

I'm integrating Facebook with my site and I've added a Logout button whose URL is taken from:
$facebook->getLogoutUrl(array('next' => 'http://mydomain.com/logout.php'));
The problem is that logout.php is never called. Instead, on click of the Logout button, it redirects to the logged-in user's Facebook home page. It doesn't log the user out of Facebook, and it doesn't call my next URL.
I noticed that the URL generated by getLogoutURL() looks like:
https://www.facebook.com/logout.php?next=http://mydomain.com/logout.php&access_token=0
Notice there is an access_token=0. Should that value not be zero? That's the only thing I can think of that might be causing the problem.
I've already set my FB app's Site URL to http://mydomain.com. While testing locally, I've also edited my hosts file. I've also googled a lot and I haven't found a solution. The only one that worked was adding an onclick to my logout button using FB.logout(). But I would need to use PHP.
Any ideas as to why the logout URL is not working?
Okay, I've solved this by creating my own logout URL and adding an access token
$logoutUrl = 'https://www.facebook.com/logout.php?next=http://mydomain.com/logout.php&access_token=' . $facebook->getAccessToken();
I hope you've found a solution! But if not, try with the following code. It worked for me!
$facebook->getLogoutUrl(array('next' =>'http://example.com/logout.php', 'access_token'=>$facebook->getAccessToken()));`
If you check out the official documentation you'll see it says nothing about setting the access token option in the parameter array but it really works! Good Luck!!
The problem is that you need to call getAccessToken BEFORE ask for the logout url.
$facebook->getAccessToken();
Don't need to call it inside as a getLogoutURL parameter. Just call it one line before:
$user = $facebook->getUser();
$access_token = $facebook->getAccessToken();
$logoutUrl = $facebook->getLogoutUrl();
I had the same problem too (access_token=0), but then I realized I was clearing Facebook cookies before calling getLogoutURL(). If you get the getLogoutURL() result first, access_token should not be zero.
In v5.0.0 the first parameter of getLogoutUrl() is the access token of the Facebook user's session.
public string getLogoutUrl(string $accessToken, string $next, string $separator = '&')
Pass it and Facebook will add it to your "next" URL.
Source

I can't get the session of user facebook, getUser return 0 - codeigniter

Regards,
I have a problem with Facebook SDK-PHP and Codeigniter.
I do not get the user's session when I try to capture and obtain basic data for that user.
The error I get is: "An active access token must be used to query information about the current user."
And when I apply the "getUser ()", I get "0".
NOTE: I download the php-sdk and put on my directory libraries the files base_facebook.php and facebook.php
In my application/config/config.php I put the key and app_secret of my facebook application.
Config.php :
$config['base_url'] = 'http://localhost/myapp_local';
$config['app_id'] = 'xxxxxxxxxxxxxx';
$config['secret'] = 'xxxxxxxxxxxxxxxxxxxxxxxx';
$config['app_name'] = 'http://apps.facebook.com/myapp_local/';
In my Controller Main.php i have the follow code:
class Main extends CI_Controller {
public function __construct() {
parent::__construct();
$fb_config = array(
'appId' => $this->config->item('app_id'),
'secret' => $this->config->item('secret')
);
$this->load->library('facebook', $fb_config);
private function _getInfoUserFB() {
try {
$fb_id = $this->facebook->getUser();
if ($fb_id) {
$fb_data = $this->facebook->api('/me');
return $fb_data;
}
} catch (Exception $exc) {
echo $exc;
}
}
[....]
}
Now, in my variables $fb_id , where obtain the bool value, always i have "0".
So, when i try to get the data of the current user facebook always i have a Exception with the message: "An active access token must be used to query information about the current user."
$fb_data['id'] = NULL
$fb_data['first_name'] = NULL
$fb_data['last_name'] = NULL
What i doing wrong here? Any step or setting I miss?
NOTE 2: I don't have some button Login with Facebook, my app connect directly to facebook via the configuration of my app on facebook. (Canvas URL, Secure Canvas URL, Canvas Page, Site URL)
Note 3: My application have some permission that need require, So I put the necessary permissions on Settings-Permissions BUT don't show me the option of "Auth Referrals" to show Dialog confirm permissions.
I use CodeIgniter version 2.1.3 and PHP-SDK v 3.2.0
You have to go to Facebook Developer Site -> Apps -> Permission. And set the basic info permission for your app.
Then in your function getLoginUrl(array("scope" => "user_about_me))), you have to give the parameters.
Finally you have to save the access token $this->facebook->getAccessToken();
If you have problems you can ask me. I have setup my Codeigniter with nearly all Social Media Platforms :)
Facebook does really bad with localhost. I've experienced this several times too. The solution I've found, which lets me develop locally, is to edit my hosts file (C:\Windows\system32\drivers\etc\hosts or /etc/hosts), and add something like the following line in there:
127.0.0.1 myfbapp.local
Using this, if you point your browser to http://myfbapp.local/, it will actually go to 127.0.0.1 and that means localhost. Of course, you would have to update your CI config too, and change your base URL to http://myfbapp.local.
As far as I can tell, the Facebook PHP SDK is having trouble setting cookies if there is no dot (.) in the domain name, so that's exactly what my solution does.
OK!, i resolved it. The fixed was the interaction with the newer version have to this form:
http://www.galalaly.me/index.php/2012/04/using-facebook-php-sdk-3-with-codeigniter-2-1/
And then, you must be call the function that obtain the information of current user for first time when your app load for first time. In other words, you call the function in the MAIN, INDEX view of your website.
If you call in other time, your function can't obtain the access_token of current user.

Get user facebook login status but don't want the redirect

I am building a website that uses the php facebook libraries. At the beginning of every page I am checking to see if the user is logged into facebook or not (or trying to) with the $facebook->getLoginStatusUrl($params) function. The issue I have is that the only real way to check with that function is to have the user redirected to a page based on their statues (by directing them to the url given back by that function). I cant use file_get_contents or cURL because the URL returned by that function uses https. Is their anyway I can get the contents of that URL with a server-side method? Or is the absolute only way to do this with a redirect? I would much prefer not to make this a client side action (via Javascript). Any ideas?
You can use the facebook getUser() function to check if the user is logged and has given permisssions to your web. After that you can use getLoginUrl() or getLogoutUrl() to show the user the right button:
$user = $facebook->getUser();
if (!$user)
{
$loginUrl = $facebook->getLoginUrl(array(
'redirect_uri' => REDIRECT_URL,
'scope' => APP_PERMS,
'display' => 'page'
));
//do something with $loginUrl, for example:
echo 'Login with facebook';
}
else
{
//check that this user is still valid
$realUser = $facebook->api('me');
...
You can learn more about this functions in facebook docs:
https://developers.facebook.com/docs/reference/php/
Is their anyway I can get the contents of that URL with a server-side method?
That won’t help you, because it’s not your server that the client uses to log in to Facebook, but his browser.
And therefor the check if the user is logged in must happen in their browser – that’s why the browser gets redirected to Facebook, because this is the only way to read the cookies that are set under Facebook’s domain.
I would much prefer not to make this a client side action (via Javascript).
It already is kind of a client-side action, because of the redirect.
There is absolutely no way to have your server alone figure out if the user is logged in to Facebook in their browser.

How can I deny users access to parts of my Backbone App if they have not logged in?

So I've got a Backbone application + web homepage. Right now, if you login to my website, I create a global object with your user details from the database. However, you can still just hit one of the routes in the application directly.
How should I handle users who are not "logged in" and redirect them to a "you must login page"?
Is this a standard operation? Basically, I have a REST url setup that returns just
{ sessionId: [php-session-id-here] }
If they are logged in, it would return something more like this:
{
sessionId: [php-sess-id],
userId: [user-id-from-db],
firstName: [f-name],
lastName: [l-name]
}
Ideas? Thanks!
What I've done in the past is to include on every page along with jQuery (actually, added to the jQuery file) an extension on the AJAX method to check for a custom code that I send when a user isn't logged in. When that value was seen it redirected the user to the login page regardless of what was going down.
This was because that site had a time out on login, so a user could get logged out while sitting on a page and then the AJAX request would just fail. If you don't have a timeout on the login the odds of ever seeing this issue are slim. Just ignore requests that come from users that aren't logged in.
If you need help coding this, start here: Extending Ajax: Prefilters, Converters, and Transports.
Really shouldn't require anything as complex as pseudo-code:
JS needs to do some AJAX, so JS talks to server
PHP checks for login if needed
If not logged in, send back the abort message (I used a converter to catch a "notLoggedIn" dataType. However this could also be done with a transport, they are just more complex.)
JS sees the abort message and does a window.location redirect rather than return AJAX message.
If you want, you could load a lightbox with a login form and send that via AJAX to PHP where a re-login can take place, if you remember the AJAX attempt that failed you can send it again after login. Then the user doesn't even need to leave the page to log back in.
If you're using jQuery, you can set a global ajaxSetting that allows you to do certain things upon certain http codes. Some pages I read recommend adding to your JSON a url field to point to where to login, but I figure that's just up to you. So the only modifications you'd need to implement what I've mentioned is 1. change the http code to something reasonable like 401 (unauthorized) and implement the http code handler. But I wouldn't call this standard, I'd just say that's what several people have done (including myself).
<?php
function IsLoggedIn()
{
if(isset($_SESSION['id'])) // Change that to what you want
{
return 1;
}
else
{
return 0;
}
}
?>
Then in your code, you could use something like:
if(isLogged()){ header('Location: http://google.com'); }

Categories