Getting the Facebook Access Token OUTSIDE of the function - javascript

So I am using a function as such to get the access token of the already authenticated user that is currently on my website:
var token;
FB.getLoginStatus(
function(response){
if (response.session) {
alert(response.session.access_token);
//This correctly shows the access token. <-----GOOD
token = response.session.access_token;
}
else{
//Other stuff.
}
}
);
alert(token);
//This shows undefined. <------PROBLEM
The only way to know the access token it seems is to be within the anonymous function called within the call to FB.getLoginStatus.
I have determined that the problem is that the anonymous function inside of FB.getLoginStatus is not executed until the end of all other scripts on the page. Therefore, the variable "token" will not be set until everything is done executing, rendering it useless.
Is there a way then to extract the access token into a universally accessible variable? I don't want to have to write all my code which requires knowledge of the access token in a single anonymous function.

Ye the issue is that the getLoginStatus is an asynchronous call that connects to the FB api. But in the meanwhile your script continues running and so the alert(token); gets called before the getLoginStatus() finished. So the token is not set yet.
I don't know what you want to do exactly with the token, but my way to do this would be to call a function inside the getLoginStatus() as soon as the token has been loaded, and then proceed with the functionality you want. So...
var token;
FB.getLoginStatus(
function(response){
if (response.session) {
alert(response.session.access_token);
//This correctly shows the access token. <-----GOOD
token = response.session.access_token;
continueScript();
}
else{
//Other stuff.
}
}
);
function continueScript() {
....
doSomeMoreFunctionalitiesWithToken();
....
}
function doSomeMoreFunctionalitiesWithToken() {
alert(token);
}
You could for example just show a "loading..." indicator on the screen and only remove it and show the actual content after the getLoginStatus() finished its task and thus after the token has been set.
Hope this helps you.

Try using the expression FB._session.access_token to get the access token from any other location.

Related

Unit test for a sub-method which called from main method and include http-request authoraztion

I faced to a really complicated scenario, hope you guys give me a hint.
So I have a main method, which is a api endpoint, this method call another method to check if the user is authorized to use this endpoint or not.
The sub-endpoint which I called it apiAuthorazation send a get request to a thirdparty url, and this third-party return a response which says this user is authorized, or not!
So I already have a unit test for the main method, but now I want add this authorization part to it. I know I can use muck libs like Nock or other similar libraries, but my problem is how can I add this sub-method to my uit test.
This is my api endpoint method :
module.exports.api = (event, context, callback) => {
// Authorization
let getBearertoken = event.headers.Authorization.replace("Bearer ", '');
let isAuhtorized = utilities.apiAuthorazation(getBearertoken);
//Some other Codes
}
As you can see I passed a bearer token to my sub-method, and apiAuthorazation method will going to send this token to a third-party api, and the method is like this :
module.exports.apiAuthorazation = function (token){
let url = process.env.authApiUrl
requestLib(`${url}/${token}`, function (error, response, body) {
if (error) console.log('Error while checking token :', error);
if(response.isValidUser){
return true;
}
else{
return false;
}
});
}
Now my question is how can I include this sub-method to my main method unit test. I use mocha and chai for unit testing, bceause the berear token will expire soon, so when I run the test, I send a sample event which have the berear token in it, but it's already expired, so its kind of useless.
When you unit test Api, you can mock apiAuthorization for the two scenarios (true or false) and test if Api behaves as expected. Dont worry about what happens inside the sub method at all for the Api tests as you are testing Api here and the focus is not on what is happening inside the sub method, apiAuthorization.

Javascript: Change Global Var Locally

Easy question. Just an explict look:
var token = "12345"
function einloggen(){
var test = particle.login({username: userName, password: passWord});
test.then(
function (data) {
token = data.body.access_token;
console.log('tokenoutprint1:', token);
},
function (err) {
console.log('LoggingIn Failed', err);
}
);
console.log('tokenoutprint2:', token);
}
einloggen();
after that i want to reuse the "new" token in a different Function...
callFunctionAVC(token);
The third last line will print me 12345. But I want print out the "new" token, defined in. Like in "normal" java
I don't know why because the first console.log shows me the right token.
SO HOW DO I GET THE "TOKEN" TO A GLOBAL VARIABLE. Thats my "real" Question. Please send full codes only otherwise i won't get it.
Sorry for not being a pro, I'm just learning in school.
Greetings.
The einloggen function is not (visibly) being called before the console.log, which means you set token = "12345", console.log() it and some time later you may or may not call the einloggen function.
I think what you wanted to do is:
function einloggen() {
//your code
}
einloggen(); // Execute the method
console.log(token);
There's a possibility this won't work as expected as well because you're using Promises in your einloggen function.
You could also try to execute console.log(token) from the developer console of your browser.

yam.platform.getLoginStatus invokes callback without response.user

When I call yam.platform.getLoginStatus right after logging in using yam.platform.login (shows the popup etc.) I get a different object passed to the callback than when the user is already logged in. Specifically, the 'user' field is missing on the LoginStatus response object, otherwise it looks the same as far as I can see.
I have the following controller for a 'login with yammer' area on my angular app:
function YammerLoginController($scope, $compile) {
$scope.isLoggedIn = false;
$scope.userName = "-";
$scope.login = function () {
yam.platform.login(function (response) {
if (response.authResponse) {
console.log("logged in");
}
refreshLoginStatus();
});
}
refreshLoginStatus(); // initialize values
function refreshLoginStatus() {
yam.getLoginStatus(function (response) {
console.dir(response);
if (response.authResponse) {
if (response.user) {
console.log("YammerLogin: Logged in as " + response.user.full_name);
console.dir(response);
$scope.$apply(function () {
$scope.isLoggedIn = true;
$scope.userName = response.user.full_name;
});
}
else {
console.log("WTF Yammer API!"); // THIS HAPPENS.
}
}
else {
console.log("YammerLogin: Not logged in.");
$('#loggedInView').popover("hide");
$scope.$apply(function () {
$scope.isLoggedIn = false;
$scope.userName = "-";
});
}
});
}
When the controller is created it already queries the current login status using the refreshLoginStatus function. If a yammer user is already logged in the app will display the user name and a logout button on the page (done with ng-show="isLoggedIn"). If the user is not logged in, a login button will be shown instead. When the user clicks on that login button, the $scope.login function will be called, invoking yam.platform.login and, if successful, calls refreshLoginStatus again in order to retrieve and set the user's name. In this scenario, the object returned from both, login and getLoginStatus do not contain the user information like in the 'user is already logged in' scenario. I tried calling the SDK-API again after some timeout, but apparently the response is cached - I always get the same. Only refreshing the whole page clears out the current response, querying the status again and receiving a 'complete' response object.
I thought it could be a scoping problem, but by now I'm not sure whether it's a problem in the SDK itself. :S
EDIT: I kind of found a solution, which however only gives me worse problems. Apparently the request is indeed cached. A refresh can be forced by using 'force refresh' on yam.platform.getLoginStatus(callback, [forceRefresh]). This, however gives me the following error on the browser console:
XMLHttpRequest cannot load
https://www.yammer.com/platform/login_status.json?client_id=2h4U2Hndg5kdWQ8xxxxxx.
No 'Access-Control-Allow-Origin' header is present on the requested
resource. Origin 'http://localhost:9000' is therefore not allowed
access.
Basically, the SDK fails to getLoginStatus, completely, and reports this back to my code as 'no connection'. I'm not sure what's worse... or, what am I doing wrong?
It appears that is just an inconsistency in the yam.platform.getLoginStatus API or the corresponding Yammer service called. If the user logs in, you get the user info, if he is alreaddy logged in, you don't get it. That is just weird but apparently can't be helped.
However, I solved this problem by simply always getting the user login data using a separate REST service call on /users/current.json once the session is authenticated (once I have the token from getLoginStatus).

Why does my FB.api request always produce an error response?

I have a Facebook app with namespace 'thenovel'. It has an action 'rate' assigned to an object 'sentence'. When the 'dofacebookstuff()' function is called, I want the user's rating of a sentence - 'testsentence', for the moment - to be published to their timeline. 'Rating' doesn't require an access token.
Whenever the dofacebookstuff() is called, the error alert pops up. I have tested whether the '!response' or 'response.error' was causing it, and it is the 'response.error' every time.
I can get the user id, name etc. fine with FB.login but the api call just does not work. If I go straight to 'https://graph.facebook.com/me/thenovel:rate?sentence=testsentence&access_token=XXXXX', I see the following:
{
"data": [ ],
"paging": {
"next": "https://graph.facebook.com/me/thenovel:rate?sentence=testsentence&access_token=XXXXX&offset=25&limit=25"
}
}
I have checked my HTML and all the Facebook-related stuff is there and in the right place. None of the other scripts on the page produce errors. Here is the function in question:
function dofacebookstuff() {
FB.api(
'/me/thenovel:rate?sentence=hello&access_token=' + accesstoken,
'post',
function(response) {
if (!response || response.error) {
alert('Error occured');
} else {
alert('Action ID: ' + response.id);
}
});
}
Could anyone explain where I'm going wrong? Where is my response data?
If you're posting to /me you need an active access token for that user - do you have one? it may have expired already, but i think the message is specifically referring to the fact that you haven't provided one, as there'd be a specific message if the token is invalid or expired.
You should be able to post to /USER_ID/thenovel:rate with the app access token if you're doing offline publishing of some kind
Try logging in using FB connect first.

FB.logout() called without an access token

I'm trying to log out of a website i've created with Facebook integrated.
Logging in works fine, but when I want to log out Firebug consistently gives me this error:
FB.logout() called without an access token.
I'm using the Facebook JavaScript SDK, and the code I've got to logout looks like this:
$(document).ready($(function () {
$("#fblogout").click(facebooklogout);
}));
function facebooklogout() {
FB.logout(function (response) {
}
)};
This is the logout code specified at the Facebook Developers Documentation just with a button being assigned the method on document.ready
Before this code I have the FB.init() method, that all runs fine.
If anyone's got a solution as to why FB.logout doesn't have an access token, it'd be appreciated.
To logout from the application which uses facebook graph API, use this JavaScript on the logout page just after the <form> tag:
window.onload=function()
{
// initialize the library with your Facebook API key
FB.init({ apiKey: 'b65c1efa72f570xxxxxxxxxxxxxxxxx' });
//Fetch the status so that we can log out.
//You must have the login status before you can logout,
//and if you authenticated via oAuth (server side), this is necessary.
//If you logged in via the JavaScript SDK, you can simply call FB.logout()
//once the login status is fetched, call handleSessionResponse
FB.getLoginStatus(handleSessionResponse);
}
//handle a session response from any of the auth related calls
function handleSessionResponse(response) {
//if we dont have a session (which means the user has been logged out, redirect the user)
if (!response.session) {
window.location = "/mysite/Login.aspx";
return;
}
//if we do have a non-null response.session, call FB.logout(),
//the JS method will log the user out of Facebook and remove any authorization cookies
FB.logout(handleSessionResponse);
}
The code works and is live on my site.
I went for the less trivial solution:
function facebookLogout(){
FB.getLoginStatus(function(response) {
if (response.status === 'connected') {
FB.logout(function(response) {
// this part just clears the $_SESSION var
// replace with your own code
$.post("/logout").done(function() {
$('#status').html('<p>Logged out.</p>');
});
});
}
});
}
Figured it out after so many tries.
Generally response.authResponse.accessToken contains token. So, its error about the accessToken not being there.
Think logically, where does that response come from in your code? Out of nowhere.
So, we need to get that response object from a function and get this working.
I don't know how it worked for others, but this worked for me.
Just replace the code with this
function logout(){
FB.getLoginStatus(function(response) {
FB.logout(function(response){
console.log("Logged Out!");
window.location = "/";
});
});
}
What we do here is, get the login status if the user is logged in and get the corresponding response in return, which contains all the necessary tokens and data. Once this is fetched, the token is used to log out the user.
I've tried something like this:
function fbLogout(){
if(typeof FB.logout == 'function'){
if (FB.getAuthResponse()) {
FB.logout(function(response) { window.location.href = PROJECT_PATH + '/index/logout'; });
return;
}
};
window.location.href = PROJECT_PATH + '/index/logout';
return;
}
Should be something more like this. There was a change to the JS API where you have to use authResponse instead of just session.
//handle a session response from any of the auth related calls
function handleSessionResponse(response) {
//if we dont have a session (which means the user has been logged out, redirect the user)
if (!response.authResponse) {
return;
}
//if we do have a non-null response.session, call FB.logout(),
//the JS method will log the user out of Facebook and remove any authorization cookies
FB.logout(response.authResponse);
}
The error says that you don't have an access token, you have to check for one using the FB.getAccessToken() function.
If there is no access token the function returns null. See example below:
function facebooklogout() {
try {
if (FB.getAccessToken() != null) {
FB.logout(function(response) {
// user is now logged out from facebook do your post request or just redirect
window.location.replace(href);
});
} else {
// user is not logged in with facebook, maybe with something else
window.location.replace(href);
}
} catch (err) {
// any errors just logout
window.location.replace(href);
}
}
With Typescript this function do work fine ..
signOutFacebook(): void {
/*SIGN OUT USER FACEBOOK.*/
FB.getLoginStatus(function (response) {
if (response.status === 'connected') {
FB.logout(function (response) {
console.log("Logged Out!");
});
} else {
console.log("The person is not logged into your webpage or we are unable to tell. !");
}
});
}/*FINAL 'signOutFacebook()'. */

Categories