Please tell me if I\'m understanding correctly. (because I might not be.)
Like @ThinkingStiff said, the key point is that you need to call FB.getLoginStatus() on the client to get the latest access token
These days, all the cool kids are handling their logins and retrieving their access tokens via JavaScript with the SDK. And hey, why not? The users love it!
After the JavaScript SDK retrieves the access token, all AJAX requests to your server will have access to that access token as well. That is, it is automatically passed along with each AJAX request in the form of a cookie.
So, on the server side, you can retrieve the access token via cookies (our friend StackOverflow has some Answers related to finding that cookie). However, if you do the other cool thing and use the PHP SDK you won't even have to give it a second thought, because it will automatically grab the cookie for you, if it's there!
Before posting to the server, call FB.getLoginStatus()
on the client to get the latest access token. There is no flash when using this method and no user interaction, as it simply grabs a new access token.
FB.getLoginStatus( function ( response ) {
if ( response.authResponse ) {
var accessToken = response.authResponse.accessToken;
//post to server
};
} );
UPDATE
well you are doing something wrong you do not need to renew access token even if its expired all you need is sending user facebook id & content you want to post together to your server by ajax then post it without access token Just check up here
if you have publish_stream permission you dont need access token this is documentation for publish_stream https://developers.facebook.com/docs/reference/api/permissions/
Enables your app to post content, comments, and likes to a user's stream and to the streams of the user's friends. With this permission, you can publish content to a user's feed at any time, without requiring offline_access. However, please note that Facebook recommends a user-initiated sharing model.
I hope you known that if you have publish_stream permission you don't need access token here is documentation for publish_stream and Below is the solution for four scenarios
1.The token expires after expires time (2 hours is the default).
2.The user changes his/her password which invalidates the access token.
3.The user de-authorizes your app.
4.The user logs out of Facebook.
To ensure the best experience for your users, your app needs to be prepared to catch errors for the above scenarios. The following PHP code shows you how to handle these errors and retrieve a new access token.
When you redirect the user to the auth dialog, the user is not prompted for permissions if the user has already authorized your application. Facebook will return you a valid access token without any user facing dialog. However if the user has de-authorized your application then the user will need to re-authorize your application for you to get the access_token.
<?php
$app_id = "YOUR_APP_ID";
$app_secret = "YOUR_APP_SECRET";
$my_url = "YOUR_POST_LOGIN_URL";
// known valid access token stored in a database
$access_token = "YOUR_STORED_ACCESS_TOKEN";
$code = $_REQUEST["code"];
// If we get a code, it means that we have re-authed the user
//and can get a valid access_token.
if (isset($code)) {
$token_url="https://graph.facebook.com/oauth/access_token?client_id="
. $app_id . "&redirect_uri=" . urlencode($my_url)
. "&client_secret=" . $app_secret
. "&code=" . $code . "&display=popup";
$response = file_get_contents($token_url);
$params = null;
parse_str($response, $params);
$access_token = $params['access_token'];
}
// Attempt to query the graph:
$graph_url = "https://graph.facebook.com/me?"
. "access_token=" . $access_token;
$response = curl_get_file_contents($graph_url);
$decoded_response = json_decode($response);
//Check for errors
if ($decoded_response->error) {
// check to see if this is an oAuth error:
if ($decoded_response->error->type== "OAuthException") {
// Retrieving a valid access token.
$dialog_url= "https://www.facebook.com/dialog/oauth?"
. "client_id=" . $app_id
. "&redirect_uri=" . urlencode($my_url);
echo("<script> top.location.href='" . $dialog_url
. "'</script>");
}
else {
echo "other error has happened";
}
}
else {
// success
echo("success" . $decoded_response->name);
echo($access_token);
}
// note this wrapper function exists in order to circumvent PHP’s
//strict obeying of HTTP error codes. In this case, Facebook
//returns error code 400 which PHP obeys and wipes out
//the response.
function curl_get_file_contents($URL) {
$c = curl_init();
curl_setopt($c, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($c, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($c, CURLOPT_URL, $URL);
$contents = curl_exec($c);
$err = curl_getinfo($c,CURLINFO_HTTP_CODE);
curl_close($c);
if ($contents) return $contents;
else return FALSE;
}
?>
for more details info you can visit this link
Thanks
I've got the problem in another project.
The way I handle it is to create a hidden iframe. The first time you need the user to accept the privilege, use your main window to redirect. then, when you are sure that the user has already accepted the privilege, use the hidden iframe to communicate with facebook.
The user will not see the "flash" because it will done in an iframe.
I've done it with GWT. Here is the code I used : it communicates with Facebook via the iframe and do a check on access token every 500ms to see if the token is valid.
The code is in java (compiled in javascript using gwt).
public class FacebookConnector extends Composite
{
public static final String ARG_ACCESS_TOKEN_EXPIRES = "fb_accessTokenExpires";
public static final String ARG_GAME_FACEBOOK_NAME = "gameFBName";
public static final String ARG_GAME_FACEBOOK_ID = "gameFBId";
private static FacebookConnectorUiBinder uiBinder = GWT.create(FacebookConnectorUiBinder.class);
interface FacebookConnectorUiBinder extends UiBinder<Widget, FacebookConnector>
{
}
private static FacebookConnector me;
public static FacebookConnector getInstance()
{
if (me == null)
{
me = new FacebookConnector();
}
return me;
}
@UiField
IFrameElement iframe;
private Date accessToken;
private Timer timer;
protected FacebookConnector()
{
initWidget(uiBinder.createAndBindUi(this));
if (ArgManager.getArg(ARG_ACCESS_TOKEN_EXPIRES) != null)
{
accessToken = new Date(Long.parseLong(ArgManager.getArg(ARG_ACCESS_TOKEN_EXPIRES)));
}
}
public void checkAccessToken(final AbstractAsyncCallback<Void> callback)
{
if (accessToken == null || accessToken.before(new Date()))
{
// send authentication
String url = "https://graph.facebook.com/oauth/authorize?client_id="
+ ArgManager.getArg(ARG_GAME_FACEBOOK_ID) + "&scope=user_birthday,email&redirect_uri="
+ ArgManager.getArg(ArgManager.ARG_URL_FACEBOOK_BASE) + "page/facebook-step2%3FgameName%3D"
+ ArgManager.getGameShortcut();
iframe.setSrc(url);
// check url
timer = new Timer() {
@Override
public void run()
{
ClientFactory.getInstance().getService().getAccessTokenExpires(new AbstractAsyncCallback<Date>() {
@Override
public void onSuccess(Date result)
{
super.onSuccess(result);
if (result != null && result.after(new Date()))
{
accessToken = result;
// call the callback
callback.onSuccess(null);
}
else
{
// try again in one second
timer.schedule(1000);
}
}
});
}
};
// launch timer in 500 milliseconds
timer.schedule(500);
}
else
{
callback.onSuccess(null);
}
}
}
Hope it will help you.
The idea is to make use of the Facebook JS-SDK methods:
FB.getLoginStatus()
)FB.api
method oraccess_token
to your server to complete the post process thereFB.login()
methodHere's a quick example (with a Live Demo!) for you to get started:
<!DOCTYPE html>
<html xmlns:fb="http://www.facebook.com/2008/fbml">
<body>
<div id="fb-root"></div>
<script>
var fbLoaded = false;
window.fbAsyncInit = function() {
FB.init({
appId : 'YOUR_APP_ID', // App ID
//channelUrl : '//WWW.YOUR_DOMAIN.COM/channel.html', // Channel File
status : true, // check login status
cookie : true, // enable cookies to allow the server to access the session
xfbml : true // parse XFBML
});
fbLoaded = true;
// Additional initialization code here
};
function postForm() {
var msg = document.myForm.msg.value;
// do form validation here, e.g:
if(!msg.length) {
alert("You should enter a message!");
return false;
}
// do we need to post to Facebook?
if(document.myForm.toFB.checked) {
// is the library loaded?
if(!fbLoaded) {
alert("Facebook JS-SDK is not yet loaded. Please try again later or uncheck Post To Facebook option");
return false;
}
FB.getLoginStatus(function(response) {
if (response.status === 'connected') {
var uid = response.authResponse.userID;
var accessToken = response.authResponse.accessToken;
/*
* message can be posted to Facebook directly
* using the FB.api method or accessToken
* can be sent to the server and do the call
* from there
*/
myAjaxCall(msg, accessToken);
} else {
// status is either not_authorized or unknown
FB.login(function(response) {
if (response.authResponse) {
var accessToken = response.authResponse.accessToken;
myAjaxCall(msg, accessToken);
} else {
alert('User cancelled login or did not fully authorize.');
}
}, {scope: 'publish_stream'});
}
});
} else {
myAjaxCall(msg);
}
return false;
}
function myAjaxCall(m,a) {
alert("Here you make the ajax call\nMessage: " + m + "\nAccess Token: " + a);
}
// Load the SDK Asynchronously
(function(d){
var js, id = 'facebook-jssdk', ref = d.getElementsByTagName('script')[0];
if (d.getElementById(id)) {return;}
js = d.createElement('script'); js.id = id; js.async = true;
js.src = "//connect.facebook.net/en_US/all.js";
ref.parentNode.insertBefore(js, ref);
}(document));
</script>
<form id="myForm" name="myForm" action="post" onSubmit="return postForm()">
<p><label>Your Message:</label><br/><textarea name="msg"></textarea></p>
<p><label>Post to Facebook?</label><input type="checkbox" value="1" name="toFB" /></p>
<p><input type="submit" value="Submit"></p>
</form>
</body>
</html>