Facebook still getting access token while logged out ( JS and PHP ) - javascript

i am currently building a website and my Wordpress theme already supports login to Facebook via the JS SDK. Below is my FB.init
window.fbAsyncInit = function(){
FB.init({
appId : 'xxxxxxxx'
, status : true
, cookie : true
, xfbml : true
, oauth : true
, version : 'v2.2'
});
};
Since i want to do some background checks before outputting stuff on HTML i'm also using the PHP SDK. ( I do not use the PHP for login purposes due to having more redirects while the JS one is straight forward (pop up and you're done).
To make the requests i am using the FacebookJavascriptLoginHelper with the below code to get the session i need for the request.
$helper = new FacebookJavaScriptLoginHelper();
try {
$session = $helper->getSession();
} catch(FacebookRequestException $ex) {
// When Facebook returns an error
} catch(\Exception $ex) {
// When validation fails or other local issues
}
All good so far. Each time i refresh the page i'm getting a new access token from the JS SDK and use it in the case i need to make a request.
Problem is on the logout part of all this.
If i use the FB.logout the user is logged out of the facebook, even in his browser and has to login again which is absolutely not acceptable.
I can by pass this "issue" by simply checking if there is a logged in user before going on and start asking for new Facebook sessions but is that the way i should go ?
When i loggout of the wordpress i can still receive access tokens and make requests to the server for some time. Close to 10-15 minutes i think. After that i do not receive anything and have to log in again.
EDIT: Also i noticed that even if i don't log out, if i don't refresh for a short period of time i get no session (access token). If i refresh once and then the second time i do get one

Related

FB.getLoginStatus returns status unknown

When calling FB.getLoginStatus using a valid Facebook App the response status is always unknown. Exact response is {authResponse: undefined, status: "unknown"}.
<html>
<body>
<div id="fb-root"></div>
<script>
window.fbAsyncInit = function(){
FB.init({ appId:'1484134468466778', status:true, cookie:true, xfbml:true});
FB.getLoginStatus(function(response){
console.log(response);
});
};
(function(d){
var js, id = 'facebook-jssdk'; if (d.getElementById(id)) {return;}
js = d.createElement('script'); js.id = id; js.async = true;
js.src = "//connect.facebook.net/en_US/all.js";
d.getElementsByTagName('head')[0].appendChild(js);
}(document));
</script>
</body>
</html>
Example URL:
http://media.tuentifotos.com/simple_test.html
Here a screenshot of the Facebook App Settings.
This was happening for me in Chrome, and was because Chrome was configured to block third-party cookies and data.
Once I made that configuration change, FaceBook is able to log me into my app without a problem.
Chrome Settings
Show advanced settings...
Privacy
Content settings...
uncheck Block third-party cookies and site data
I too faced this problem in Chrome. However, in Firefox it worked as expected with the status returned as connected when the user had logged in previously.
I found a clue about this from an answer to the similar question here.
The root cause of this issue is, on FB.logout(), Chrome is not removing the cookie fblo_<your-app-id> which is somehow affecting FB.getLoginStatus() function to return unknown
Fix: On calling FB.logout(), you may programmatically delete the cookie fblo_<your-app-id>
FB.logout(function(response) {
deleteCookie("fblo_" + fbAppId); // fblo_yourFBAppId. example: fblo_444499089231295
});
function deleteCookie(name) {
document.cookie = name +'=; Path=/; Expires=Thu, 01 Jan 1970 00:00:01 GMT;';
}
When I checked, the status is showing "not_authorized" and that's fine, since I've not authorized the app yet.
To complete the flow, you should add the FB.login whenever user id is not authorized or not logged-in to facebook:
window.fbAsyncInit = function(){
FB.init({ appId:'{APP-ID}', status:true, cookie:true, xfbml:true});
FB.getLoginStatus(function(response){
if (response.status === 'connected') {
//proceed
} else if (response.status === 'not_authorized') {
login();
} else {
login();
}
});
};
function login(){
FB.login(function(response) {
if (response.authResponse) {
// proceed
} else {
// not auth / cancelled the login!
}
});
}
For me this meant "on my login page" I needed to specify cookies.
window.fbAsyncInit = function() {
FB.init({
version: 'v2.8',
cookie : true,
});
};
But don't ask me why this was the case. It also fixed it needing to click twice on the login button to actually login, and doesn't even require an appId, seemingly, FWIW...
The final answer
Ok so I think I've finally figured this damn issue out.
What you need to know:
1) You authenticate with Facebook via an app ID. This sets various cookies, where your app ID is tagged on the end:
fblo_000000000000
fbm_000000000000
fbsr_000000000000
2) If you delete these cookies, you're still authenticated to facebook as a regular user (unless you log out completely). And on Facebook's servers they still know you are authorized on this app.
So when you run FB.getLoginStatus() again it will just recreate them and put them back again. This is not what your user expects. This is bad. They clicked 'Log out'.
3) The docs explicitly say this:
The user is either not logged into Facebook or explicitly logged out of your application so it doesn't attempt to connect to Facebook and thus, we don't know if they've authenticated your application or not. (unknown)
So they don't even TRY to check if this cookie is set. That's why you get null or undefined. So the fblo cookie is considered like an 'opt-out'. You're NOT ACTUALLY LOGGED OUT by what any regular person would consider being logged out as to mean. There's just a cookie saying you are! Of course if the user logs back in with the login button then the cookie will be deleted, which is what you and your user wants.
Therefore I believe the only thing that makes sense to do (if you truly need to know the user's status) is to:
Manually check the existance of fblo_<APPID> cookie before you run FB.getLoginStatus.
If the cookie doesn't exist then do nothing and run your normal flow.
If the cookie does exist you have several options :
1) Option 1
Do absolutely nothing. You now understand the issue, you understand not to delete the cookie and perhaps you don't need to do anything other than show the Facebook login button.
2) Option 2
You assume the person is a user of your app, and do whatever you need to do to show the UI. But you won't be running your full normal logic - this will be application specific to you .
3) Option 3
Manually set the cookie value fblo_<APPID> to n (instead of 'y'). Remember this cookie is set on your domain so you're allowed to change it. *Depending upon your development environment this will vary, but it needs to be done client side, and you may need to specify path of `/' and your cookie domain).
Run the getLoginStatus(..., true) - it will not be blocked now because the cookie is now n. However you must not run your normal logic here - because all you want to do is check if the user is actually a Facebook user and/or still authenticated with your app.
Manually set the cookie value back to y
Unfortunately I can't recommend this solution due to weird race conditions. It almost almost works, but FB could deliberately or accidentally break it at any time - and it actually ends up still getting confused thinking you're really logged in when you aren't. Plus it could have all kinds of complications with other plugins I haven't even observed.
I wish the getLoginStatus would just always run and give accurate information, but this is the only true solution I see. And it's been this way for 8 years so I think we're stuck with it.
4) Option 4 - Set your own cookie
You always have the option to set your own cookies to indicate certain things, like 'this user has at some point logged into Facebook' or 'this user is authenticated with my app'. But I'm cautious about doing this because it can quickly get complicated.
Incidentally I revisited this issue because I'm using the Messenger plugin for my website and I don't want it to display at all unless I know the person has a Facebook account. So I need an accurate response to login status.
This was happening to me until I turn on my browser to allow third-party websites to save and read cookies.
To do this go to
settings > advanced > site settings > Cookies and site data
Then uncheck the option blocking third-party websites from saving and reading cookies.
This might not be a good option but it solves these issues for me.
You just need make your site URL from http to https
DO NOT use http
I had the same issue in IE. Flimzy's answer got me thinking. I tried running IE as administrator and it worked.
I had the same problem, I fixed this by clearing all cache and cookies.
You have to test it from the live domain (which you provided in the app).
I had the same problem when testing locally (using local domain).
In my case I was using Brave browser which didn't allow cookies due to which it was giving status unknown. I switched to chrome and now it is working.

Set Javascript API accessToken

I am developing a Facebook app. I have a server side OAuth flow which allows me to authenticate a user without requiring him to click on any button. I hence retrieve his accessToken as long as other information and use those ones on the server side before to generate the page.
In my application, I now need to use the Javascript API which could technically share the same Oauth token.
Is it possible to instantiate the FB javascript Object with a given Oauth token ?
I know it is possible to do the contrary meaning doing the Oauth process on the client side and share the Oauth key with the server side via the cookie but this has two many drawbacks in my opinion :
_ First, it implies to have this "login" button which is to me not a good user experience for a facebook app.
_ Also, I don't get how this Oauth process is supposed to behave if my application is composed of two different pages. Going from one page to another reloads entirely the javascript. Will this Oauth process (with the popup and so forth) be done on each page reloading ?
Thanks for your help !
I had a similar problem once, Facebook has an older method called FB.getLoginStatus which you can use to check if the user has given permission without a popup -
FB.init({appId: 'XXXXXXXXXXXXXX', xfbml: true, cookie: true, oauth: true});
FB.getLoginStatus(function(response) {
if (response.authResponse) {
token = response.authResponse.accessToken;
FB.api('/me', function(response) {
console.log(response);
// do something here they are logged in and have given you perms
});
} else {
// no user session available, someone you dont know
}
});
hope that helps!

Final re-direct for FB.login of Facebook's JavaScript SDK fails, displaying and returning an error

Users have been able to log into my website using their Facebook account, but then it suddenly stopped working properly.
I use the following standard Facebook JavaScript SDK code:
window.fbAsyncInit = function() {
FB.init({
appId : '<MY_APP_ID>',
status : true, // check login status immediately
cookie : true, // enable cookies to allow the server to access the session
xfbml : false // because I don't use XFBML
});
FB.login(function(response) {
// code that deals with `response`, whether null or not
});
}
But if I cleared the browser cache, and triggered this code (after the Facebook library had loaded), the following would happen:
Facebook's login dialog would pop up.
After entering credentials of a user that has access to this Facebook app, a dialog would ask whether I want to register a new login location.
Regardless of the action taken in the previous step, the dialog box displays the following error message:
An error may have occurred as part of the login process. You can close this window and try returning to the application, though it may ask you to log in again. This is probably due to a bug in the application.
FB.login's response contains an error message. Inspecting the browser's state, I can see that login information is stored within a Facebook cookie. Triggering the above code again, without clearing the cache, now succeeds.
Why doesn't it work the first time around?
Due to Facebook's OAuth 2.0 and HTTPS Migration, not using OAuth 2.0 after October 1, 2011 within JavaScript SDK will not work (properly).
To make the above example work, make sure that:
your FB.init call sets oauth to true (see example usage):
in the code that deals with the response:
you are reading the authResponse (not session) field of the FB.login's response;
you are calling FB.getAuthResponse (not FB.getSession), and reading signedRequest from its response.

Using Facebook Javascript SDK to get Graph Data

FIXED NOW! But I can't answer my own question yet. See my comment below. And thanks for helping.
I've searched and searched and read the docs and still can't figure this out.
I have a web page about an event. There's also a public Facebook "event" for my event. I'm trying to use the FB Javascript SDK to get the number of attendees for the Facebook event and add it to the number of people who've registered through the website.
I've created an app and I have an appID and secret string. I can get an access token from:
https://graph.facebook.com/oauth/access_token?client_id=XXXX&client_secret=XXXXX&grant_type=client_credentials
and I can then use that access token to get the attendees for a public event:
https://graph.facebook.com/331218348435/attending?access_token=XXXXXXXXX
That's all fine.
I'm now trying to do this same thing using the Javascript SDK.
I've loaded the SDK and done an init:
FB.init({
appId : 'XXXXXXXX',
status : true, // check login status
cookie : true, // enable cookies to allow the server to access the session
xfbml : true // parse XFBML
});
and I know the SDK is working because I can get an object with the data that doesn't need an access token:
FB.api( '/331218348435', function (response) { console.log ( response ) } );
but when I try to get the attendee data that needs the access token:
FB.api( '/331218348435/attending', function (response) { console.log ( response ) } );
I get an OAuthException: "An access token is required to request this resource."
All the tutorials and information I can find all refers to using the .login method, but I don't want a user to login, I want to login using my app ID without any user interaction.
I'd assumed that the API took the SDK's init request and granted me an access token when I called the .init method, the authentication being done against my website's address (the HTTP referrer - yes I have set my website URL in the Facebook app settings).
Any ideas what might be causing this to not work? How can I get the access token using the Javascript SDK without doing a .login? Am I missing a step? Is this even possible?
Thanks
Form what the rather circular documentations says, getting the attending feed requires a 'generic access_token`. In Facebook terms:
Any valid access_token
Any valid access token returned by our APIs. An access token may not be valid if, for example, it has expired. No special permissions are required. Occasionally, this is referred to as a generic access_token.
So this means that you can use any token you like to access the attending feed, as long as the event is public. The easiest access token to get seems to be an app token: http://developers.facebook.com/docs/authentication/#applogin. You can get this token using only your App ID and Secret, and no user interaction is required.
To summerise the link content: You can get an application access token by sending a GET request to
https://graph.facebook.com/oauth/access_token?client_id=YOUR_APP_ID&client_secret=YOUR_APP_SECRET&grant_type=client_credentials
You can then use that access_token to make the call for you attending list
FB.api('MyEvent/attending?access_token=ACCESS_TOKEN');
Oh. OK.
Well, for whatever reason, I went away and had my dinner and when I come back it's working fine.
When I updated the settings for my app Facebook said it might take a few minutes for the change to get around the servers. Turned out to take over an hour!
My code was fine.
Thanks for your help.

Does Facebook FB.logout() still have a dialog box?

Using the new JS SDK from FB, I notice that there is no dialog telling the user they will be logged out from Facebook when logging out from my app.
What happens now is somewhat of a UI/UX problem: the user logs out from my app but also automatically logged out from Facebook without warning, which can be annoying.
Has anyone resolved this using FB SDK methods or some other function within FB.logout();?
Thanks for helping.
You will have to make your own UI dialog for this (or use the deprecated connect javascript sdk). You could either pop up a UI dialog warning that they will be logged out of both your app & out of facebook, or specify a callback method in the FB.logout function which tells them afterwards that they have been logged out of both.
Unfortunately this is as designed as noted here: http://developers.facebook.com/docs/reference/javascript/FB.logout/. As this is as designed in the Javascript SDK, I'm fairly confident in making an assumption that a server-side library will yield the same results.
I found a trick, that logs the user out of your application just client side, but leaves him logged in on facebook:
FB._authResponse = null;
FB._userStatus = null;
After that, calls to FB.api will return the proper error:
>>> FB.api('me', log)
{"error":{"message":"An active access token must be used to query information about the current user.","type":"OAuthException"}}
Also FB.getLoginStatus and FB.getAuthResponse are returning null or behave like the user is not logged in:
>>> FB.getLoginStatus(log)
{"status":null,"authResponse":null}
You can even log in the User again with FB.login()
But after a reload, the User will be logged in again automatically, if you have status : true in your FB.init config:
FB.init({
appId : 'yourappid',
status : false, // will not load the user automatically on pageload/refresh
cookie : true, // will leave the userid in FB._userID
oauth : true,
xfbml : true
});
Hope that helps a bit.

Categories