facebook sso state check: CSRF state token does not match one provided - php

What are the basic steps for setting up a pure server flow facebook SSO, the docs are as usual a little ambiguous?
I set up the flow with javascript popups only to later realise you are not allowed to customise the login buttons.. which when you stick them next google and twitter sso the signin box look terrible.
http://www.codecademy.com/ seem to direct to their own server which then forwards onto a URL like this:
https://www.facebook.com/dialog/oauth?response_type=code
&client_id=212500508799908&
redirect_uri=http%3A%2F%2Fwww.codecademy.com%2Fauth%2Ffacebook%2Fcallback&state=8aac5bc63c5afe8fbabe572021e7750579fefd898d7b4316&
scope=email%2Cpublish_actions
How is this URL being generated? In the facebook docs there is a function "getLoginUrl".. is this being called which generates the correct URL?
I tried directing the user directly from their browser to:
var href = 'https://www.facebook.com/dialog/oauth?' +
'client_id='+app_id+'&'+
'redirect_uri=http://www.mysite.net/authenticate_facebook.php&'+
'scope=email&';+
'state='+$('body').attr('unique');
But the at the facebook php then the following recieving code resulted in errors about the 'state' not matching... I am assuming that the state is not just a random value generate by my server and must be aquired from the facebook server?
require_once(WEBROOT_PRIVATE.'authenticate/facebook-php-sdk/src/facebook.php');
$config = array(
'appId' => 'xxx',
'secret' => 'xxx',
'fileUpload' => false,
'allowSignedRequest' => false
);
$facebook = new \Facebook($config);
$user_id = $facebook->getUser();
if($user_id)
{
try
{
$user_profile = $facebook->api('/me','GET');
}
catch(FacebookApiException $e)
{
error_log($e->getType(), 0);
error_log($e->getMessage(), 0);
}
}
SO, is this correct flow:
1 - Direct the user to my server facebook_auth.php
2 - facebook_auth.php generate the get url and forwards the user onto it
3 - The user, if required logs into facebook, allows my app
4 - my facebook_auth.php script then checks the tokens and talks server to server with facebook to verify the rest
5 - my website then logs the user in

I had a similar issue last week, and tracked it down to the state field being overwritten by multiple calls to getLoginUrl(). Each time you call getLoginUrl(), a new state token is generated in the SDK and stored in the $_SESSION (it's just a random value), so if you call it twice and the user uses the first link to log in, the second call will have reset the SDK's internal state token, and you will get this error in your logs.
The SDK looks for the same state token in the URL coming back after Facebook authorizes the user and redirects them back to your site, and if it doesn't match it will log this error (here's a link to the source).

Related

How to post programatically to your own facebook page?

My situation is the following.
I am the owner of a facebook app,and a facebook page.I would like to programatically(from code) post to this facebook page.
As far as I know I need a facebook app to do that so I created one.
I am using the facebook php sdk and code igniter.(I am not using the javascript sdk).
I have the facebook object.I printed it's methods and tried printint the user id while I was logged into facebook.
This did not work.
My questions are the following:
1)Why does it not work to print the facebook id?
2)What is the most simplest solution to programatically post to my facebook page ?(from my app,or from my user)
What am I doing wrong ?
This is my code
$config = array(
'appId' => 'xxxx',
'secret' => 'xxxx',
'cookie' => true,
);
$this->load->library('facebook', $config);
echo '<pre>';print_r(get_class_methods($this->facebook));
$id = $this->facebook->getAppId();
$secret =$this->facebook->getApiSecret();
$uri = "http://tipsterscorner.com/stats/display/facebook1";//callback_url se pare ca nu e bun
//i build the facebook url.If I use this in the browser ,I get a series of popups(do you allow the application to blabla)
//I read somewhere that if I change the last parametere to code,and use curl,I will get the token in the response
//printed on the screen of the return url,but that does not happen
$facebook_url = "https://www.facebook.com/dialog/oauth?`client_id=$id&client_secret=$secret&redirect_uri=$uri&scope=publish_stream,offline_access,read_stream,manage_pages&response_type=token";`
$curl = curl_init();
// Set some options - we are passing in a useragent too here
curl_setopt_array($curl, array(
CURLOPT_RETURNTRANSFER => 1,
CURLOPT_URL => $facebook_url,
CURLOPT_USERAGENT => 'Codular Sample cURL Request'
));
// Send the request & save response to $resp
$resp = curl_exec($curl);
This is the url.
http://tipsterscorner.com/stats/display/facebook1
Thank you very much.
To post on facebook by yourself and on behalf of other's using the app you need to obtain user access token. There are two kinds of Access Tokens namely App Access Token and User Access Token. When app is posting on user's behalf User Access Token is required. User Access Token is generated when a User gives permissions for the app(The dialog popup which you experienced when entering the facebook url in browser). Its solely upon user whether or not to grant permission to the app to post on their behalf. App should be developed to handle both the situations. Once User have given permission(Basic Permission which includes all publicly available info of the user), user access token will be generated. You can either store it in database table or in SESSION. Sometimes user access tokens may become invalid and new token has to be retrieved. During that time curl can be used to retrieve because user has already granted permission for the app.
http://developers.facebook.com/blog/post/2011/05/13/how-to--handle-expired-access-tokens/

What is Facebook API error 191 [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Facebook API error 191
I am getting the following error with some code that I am using. The error is
API Error Code: 191
API Error Description: The specified URL is not owned by the application
Error Message: redirect_uri is not owned by the application.
<?php
$facebook = new Facebook(array('appId' => $app_id,'secret' => $app_secret,'cookie' => true));
if($facebook->getUser() < 1)
{
$red_url = $page_url.'?sk=app_'.$app_id;
$redir = $facebook->getLoginUrl(array('redirect_uri'=>$red_url,'next'=>$red_url,'scope'=>'offline_access,publish_stream,status_update,photo_upload,user_birthday'));
echo "<script>top.location.href='".$redir."';</script>";
exit;
}
$user = $facebook->api('/me');
Can any one explain how to get around this and why this happens?
When you open a Facebook application you need to set the domain/s under which your application is intended to run - and (almost) every place that your app gets in contact with facebook (especially client side) must be from a url from the same domain (or a subdomain of it)
in your case you told asked facebook to authorize the app for the user and then redirect him to $red_url which I understand to be the page where your app is installed - BUT this link is not under the domain of your application (unless you registered facebook.com as your app domain in the application dashboard
if you want to redirect the user to that specific tab - you may create a proxy file under the domain of your application that will redirect the user to the tab, for example:
lets say you registered mydomain.com as your app domain in the app dashboard . then - create a file named redirect.php for example that will conatin the following script and put it under http://www.mydomain.com/my_directory/redirect.php :
<?php
$app_id ="ENTER_YOUR_APP_ID_HERE";
$page_url = "ENTER_THE_PAGE_URL_HERE"; //for example: http://www.facebook.com/techmarketing.co.il
$red_url = $page_url.'?sk=app_'.$app_id;
header("Location: {$red_url}");
and your script will change to be:
<?php
$facebook = new Facebook(array('appId' => $app_id,'secret' => $app_secret,'cookie' => true));
if($facebook->getUser()==0)
{
$red_url = "http://www.mydomain.com/my_directory/redirect.php";
$redir = $facebook->getLoginUrl(array('redirect_uri'=>$red_url,'next'=>$red_url,'scope'=>'offline_access,publish_stream,status_update,photo_upload,user_birthday'));
echo "<script>top.location.href='".$redir."';</script>";
exit;
}
$user = $facebook->api('/me');
Can you say "cross site scripting" ;)?
WORKAROUND:
Browser, Edit Setting, Web Site
<= add site URL to the app settings
Here's a bit more background:
*
http://techblog.hybris.com/2012/06/05/oauth2-the-implicit-flow-aka-as-the-client-side-flow/
redirect_uri: The server configured a redirect_uri (which we strongly recommend)
which needs to match the settings for the client_id. Client_id and
redirect_uri are both server-side settings that the app developer
needs to get at beforehand.
You need to tell Facebook that your app is allowed access to that website.
Edit your app settings (via the FB developer dashboard). On the basic settings page, click on 'Website with Facebook Login' and enter your site address.

Facebook social graph API call for authenticated user

I'm trying to grab data about a user in Facebook that can only be fetched if the app is authenticated (for example /likes).
However, I can't seem to grab this data despite the fact that the user has authenticated the Facebook app (and the applicable specific permissions). I can only get data from a public context.
I'm assuming I must be missing some sort of authentication step, but I can't figure out how. When I call $fb->getAccessToken(), it returns a string value, so it seems like it does get an access token for making requests. I see some solutions to force the user to click on a login URL to authenticate, but hasn't that already been done if they have authenticated the FB dialog previous (via Javascript)?
Besides that, I need the script to run without any input from the user.
Current code:
$fbConfig = array(
'appId' => 'xx',
'secret' => 'xx',
);
//get facebook configuration parameters defined in admin backend
$fb = new facebook($fbConfig);
$access_token = $fb->getAccessToken();
$fbUid = '123456789'; // Known Facebook User Id
$likes = $fb->api('/' . $fbUid . '/likes&access_token=' . $access_token);
var_dump($likes);
// Result is always: array(0) { }
Here you just want to get a likes of user of your application, i m giving you some code which have been created from me and it's working, i test it. you don't have need to get access token because it will be taken at every time.
<?php
set_time_limit(0);
include_once '../src/facebook.php';
$config=array(
'appId'=>"xxxxxxx",
'secret'=>"xxxxxxx",
'cookie'=>true
);
$facebook = new Facebook($config);
$user=$facebook->getUser();
$accessToken=$facebook->getAccessToken();
$likes=$facebook->api('/me/likes');
var_dump($likes);
?>
Here, set time limit=0 because it'll take more time to get a every likes of user.

Facebook PHP SDK - User not authenticated

I am using Facebook PHP SDK to authenticate the user. After generating the LoginUrl using the PHP SDK, the user clicking on that LoginUrl gets redirected to the Facebook page asking for permission. After clicking on the Go to App link, the user gets redirected back to my website http://www.mydomain.com/login/facebook_connect.
Problem: After being 'authenticated' by Facebook, the PHP script at http://www.mydomain.com/login/facebook_connect is unable to determine that the user has logged in via Facebook. At this point, $user = $facebook->getUser(); is 0.
Did I do something wrong? Thanks!
PHP Code for page that generates LoginUrl
require 'libs/fb-php-sdk/facebook.php';
// Create our Application instance
$facebook = new Facebook(array(
'appId' => '123',
'secret' => '123'
));
// Get User ID
$user = $facebook->getUser();
// Get Login URL
$loginUrl = $facebook->getLoginUrl(array(
"scope" => "email,user_education_history,user_work_history",
"redirect_uri" => "http://www.mydomain.com/login/facebook_connect/"
));
$data['fb_login_url'] = $loginUrl;
$this->load->view('splash', $data);
PHP Code for page user is redirected to after Facebook authentication
*http://www.mydomain.com/login/facebook_connect/*
require 'libs/fb-php-sdk/facebook.php';
$facebook = new Facebook(array(
'appId' => '123',
'secret' => '123',
));
// See if there is a user from a cookie
$user = $facebook->getUser();
// We may or may not have this data based on whether the user is logged in.
//
// If we have a $user id here, it means we know the user is logged into
// Facebook, but we don't know if the access token is valid. An access
// token is invalid if the user logged out of Facebook.
if ($user) {
try {
// Proceed knowing you have a logged in user who's authenticated.
$user_profile = $facebook->api('/me');
} catch (FacebookApiException $e) {
error_log($e);
$user = null;
}
}
print_r($user_profile);
echo $user;
All seems correct.
Questions:
1.- I supposed that http://www.mydomain.com/ contains all your scripts, right?
2.- Are you using codeigniter? Or a codeigniter-based CMS? In that case maybe you have a session problem (very common in CI). Check it and we continue...
EDIT 2: In case of being a cookie related problem. Here is an image showing as you can use firebug with a cookie module to easily track your cookies:
So you can check how facebook cookies are being generated.
EDIT 3: Ok. So you are using CI and your FB cookies are being deleted. Maybe is a session problem. Here is a related answer where I explain how to use a session CI library replacement that generally solve all these kind of painful issues. Believe me, give it a try!
a.- Here it is: Codeigniter's Native session (there is a download link at the bottom)
b.- BUT, due that it is an old library you MUST made some hacks. You can check those simple hacks in the library's forum
c.- Just drop this file in codeigniter's library directory.
$facebook->getUser() uses a cookie to get the user. If you use CodeIgniter, or another library that "eats" cookies that PHP assigns automatically, you need to create a proxy page outside CI, that would pick up the cookie the redirect back into CI.
In other words, take to code you currently have in
http://www.mydomain.com/login/facebook_connect/
and create a copy in a regular PHP file:
http://www.mydomain.com/facebook_pickup.php
do not echo anything from the script (remove print_r), just redirect to
http://www.mydomain.com/login/facebook_connect/
and it would magically start working.

Twitter OAuth + auto login + MYSQL

I'm using https://github.com/abraham/twitteroauth library. I already created my app on Twitter, the callbacks are working fine (even on localhost), but one thing that is bugging me is HOW the auto-login happens? I know there's "user_id" that is stored in the MYSQL database, along with oauth_token and oauth_token_secret, but how do I obtain user_id as soon as the user enters the site, so I can query the database to see if it already exists and what not, without having to popup the authorize twitter popup then reaching the callback, over and over again?
I've seen a lot of questions like this one, but no one ever answered it in a satisfying way.
The ones that should be saved to be used in verifying the user automatically are the oauth_access_token and oauth_access_secrete . Have you managed to get them from twitter?
The Oauth steos are:
Acquiring a request token
Sending the user to authorization
Exchanging a request token for an access token
Using out-of-band/PIN code mode for desktop & mobile applications
please refer to :
http://dev.twitter.com/pages/auth
actually, it needs to be a mix of PHP own $_SESSION with OAuth callbacks. After the callback, set the current user ID you inserted on the database or query for "user_id" from Twitter OAuth response (that you should ALSO store on the database, along with the username), then use that for future reference, and using $_SESSION containing the registered user data on your own database.
So, for a quick example
function action_login()
{
if ( ! $this->user->is_logged())
{
// Create TwitterOAuth object with our Twitter provided keys
$tOAuth = new TwitterOAuth($this->config->get('consumer_key'), $this->config->get('consumer_secret'));
// Generate request tokens
$requestToken = $tOAuth->getRequestToken(url::site('auth/twitter','http'));
$_SESSION["oauth_token"] = $requestToken["oauth_token"];
$_SESSION["oauth_token_secret"] = $requestToken["oauth_token_secret"];
// Display Twitter log in button with encoded link
$this->view->set('url', $tOAuth->getAuthorizeURL($requestToken["oauth_token"]));
$_SESSION['current_url'] = Request::detect_uri();
}
echo $this->view->render();
}
public function action_twitter()
{
if ( empty($_GET["denied"]) && isset($_GET["oauth_token"]))
{
if ($_GET["oauth_token"] == #$_SESSION["oauth_token"])
{
// Use generated request tokens (from session) to construct object
$tOAuth = new TwitterOAuth($this->config->get('consumer_key'), $this->config->get('consumer_secret'), $_SESSION["oauth_token"], $_SESSION["oauth_token_secret"]);
// Retrieve access token from Twitter
$accessToken = $tOAuth->getAccessToken();
// Check we have valid response
if(is_numeric($accessToken["user_id"])) {
// Remove request token session variables
if ($this->user->loaded() || $this->user->where('user_id', '=', $accessToken['user_id'])->find()->loaded())
{
$this->user->values(array(
'oauth_token' => $accessToken['oauth_token'],
'oauth_token_secret' => $accessToken['oauth_token_secret'],
'screen_name' => $accessToken['screen_name'],
))->update();
}
else
{
$this->user->values(array(
'user_id' => $accessToken['user_id'],
'oauth_token' => $accessToken['oauth_token'],
'oauth_token_secret' => $accessToken['oauth_token_secret'],
'screen_name' => $accessToken['screen_name'],
))->create();
}
unset($_SESSION["oauth_token"]);
unset($_SESSION["oauth_token_secret"]);
echo $this->view->render();
// Redirect to main page
}
}
}
$this->request->redirect($_SESSION['current_url']);
}
so basically, the AUTO LOGIN (like the user is already logged to twitter, and already registered to your website) can't be done without him clicking the LOGIN WITH TWITTER button, unless you set the lifetime of your $_SESSION pretty high (like it happens with twitpic for example).
$this->user->is_logged() is checking for $_SESSION['id'] (auto increment on MYSQL) and $_SESSION['twitter']['user_id'] from twitter info
EDIT: Also, the quickest and cleanest way to do it, is to make an AJAX call on the page load with the Twitter credentials using the Javascript SDK, then set the $_SESSION variables with the info the SDK provided.

Categories