How to properly use FB.logout/getLoginStatus - javascript

I have a webpage where when the user logins in, I execute FB.login:
FB.login(
(response) => {
if (response && response.authResponse) {
console.log(response.authResponse);
} else {
throw new Error('Login failed');
}
},
{ scope: 'permissions,that,I,ask,for' }
);
Running that code, I successfully get back an authResponse with status: "connected". I don't save the tokens in the response in any way.
When the user goes to logout, I call FB.logout:
FB.logout((response) => console.log('Logged out', response));
This gives me the error FB.logout() called without an access token. Now, there are many SO questions (here and here for example) and blog posts that deal with how to handle that error. Specifically, most of them recommend wrapping your logout call in a FB.getLoginStatus call, the idea being that the FB SDK needs to have an internal copy of the access token.
FB.getLoginStatus((response) => {
if (response && response.status === 'connected') {
FB.logout((logoutResponse) => console.log('Logged out, logoutResponse));
}
});
However, when I do that, the response coming back from FB.getLoginStatus has status: "unknown".
How can the status be unknown when 1) I just called FB.login, and then 2), I literally just called FB.getLoginStatus?
What do I need to do to get FB.logout to work properly?
(Tested in a Chrome 66 Incognito tab with no script blockers of any kind running.)
Here is the FB.init call we use:
FB.init({
appId: env.FACEBOOK_APP_ID,
version: 'v2.9',
});
If it's helpful: we wrap all async FB.* API calls with a Promise so that we can chain off of when they finish. For example:
return new Promise((resolve, reject) => {
FB.login((response) => {
if (response && response.authResponse) {
resolve(response);
} else {
reject(new Error('FB.Login failed'));
}
});
});

Related

Why does this javascript code not redirect the user after the metamask transaction?

I want to make a javascript code that does a metamask transaction and redirects the user to another page after the transation is completed. How easy this may sound, I can not figure it out.
My current code lets the user complete the transaction, but it does not redirect the user to another page. Instead, it gives this error: "MetaMask - RPC Error: invalid argument 0: json: cannot unmarshal non-string into Go value of type common.Hash"
I have looked it up, but I could not find any possible fix for my problem.
This is my code:
try {
// send the transaction
ethereum.send({
method: 'eth_sendTransaction',
params: [
{
to: contractAddress,
from: userAddress,
value: amt
},
],
}, (error, transactionHash) => {
if (error) {
console.error(error);
} else {
// check the status of the transaction using the transaction hash
ethereum.request({
method: 'eth_getTransactionReceipt',
params: [transactionHash],
}).then((receipt) => {
// check if the transaction was successful
if (receipt.status === '0x1') {
console.log(`Transaction was successful`);
// redirect to another page
window.location.href = "page.php";
} else {
console.log(`Transaction failed`);
}
}).catch((error) => {
// This is the line of code the error is assigned to:
console.error(error);
});
}
});
} catch (error) {
console.error(error);
}
});
} else {
document.getElementById("bericht").innerHTML = "Install Metamask before you continue";
return;
}
I have tried looking the error up on internet, but nothing significant showed up. Could anyone help? Thank you in advance!

Reducing Google Analytics API Usage

I use the Analytics Real Time Reporting API to pull the top stories on my employer's website each hour to put in a trending items module on our homepage. For the last several weeks I've been getting emails from Google saying:
8.65% of the requests resulted in rateLimitExceeded or userRateLimitExceeded error. This error means that your project is hitting the QPS limit. Lowering the frequency of the calls to the Analytics API will reduce the number of errors and save daily quota.
The odd thing is, as far as I know, my app should only be making one call per hour, as I store the response in Redis and reference the cached data until it expires. And the stats from the Google API Dashboard would seem to reflect this (Screencap from GA Dashboard).
I also added exponential backoff, as a prior email from Google had recommended, to ensure I wasn't retrying too frequently after a request fails:
const params = {
'auth': jwtClient,
'ids': process.env.GA_ID,
'metrics': 'rt:pageViews',
'dimensions': 'rt:pagePath',
'max-results': '50',
'sort': '-rt:pageViews',
'key': process.env.GA_KEY
}
function fetchTrending() {
return new Promise ((resolve, reject) => {
jwtClient.authorize(err => { if (err) { reject(err) } })
const getAnalytics = backoff.call(analytics.data.realtime.get, params, (error, body) => {
if (body != null && error == null) {
resolve(body)
} else {
reject(error)
}
})
getAnalytics
.retryIf(err => { return err.status == 503 })
.setStrategy(new backoff.ExponentialStrategy())
.failAfter(10)
.start()
})
}
function trending () {
return new Promise ((resolve, reject) => {
cache('gaData', 3600, () => {
return new Promise ((resolve, reject) => {
fetchTrending()
.then(gaData => {
resolve(gaData)
}).catch(error => {
reject(error)
})
})
})
[etc.]
The caching script basically says, check whether the key is present in Redis and if it is, return that data, otherwise, execute the passed function.
So, why would I be hitting Google's API limits with so few requests? And what can I do to mitigate this problem so that I reduce my "unauthorized" error rate?

MobileServices.web.js unauthorized api call

When I leave my WinJS app dormant for a while and then come back to it, and i click on a button, for some reason my calls to my backend aren't working.
I get an "Unauthorized" error from the server.
How do I modify the invokeApi so that it reauthenticates the user or something?
Does anybody have any experience using mobileservices.web.js and how to keep the end user perpetually logged in without having to reauthenticate themselves?
Thankyou.
client.invokeApi("getTopForumsTotal", {
method: "post"
}).then(function (results) {
// do something
}, function (error) {
WinJS.log(error);
});
I use winjs mobileService to authenticate the user.
client.login("microsoftaccount").done(function (results) {
// Create a credential for the returned user.
credential = new Windows.Security.Credentials.PasswordCredential("myapp", results.userId, results.mobileServiceAuthenticationToken);
vault.add(credential);
completeDispatcher();
}, function (error) {
WinJS.log(JSON.stringify(error));
errorDispatcher(error);
});
and this is what I use to refresh the end users token.
client._request("GET", "/.auth/refresh", null, null, {
accept: "application/json",
"ZUMO-API-VERSION": "2.0.0"
}, [], (error, response) => {
if (!error) {
var userObject = JSON.parse(response.responseText)
if (userObject.authenticationToken) {
client.currentUser.mobileServiceAuthenticationToken = userObject.authenticationToken;
testCall().done(function (success) {
if (success) {
credential = new Windows.Security.Credentials.PasswordCredential("myapp", userObject.user.userId, userObject.authenticationToken);
vault.add(credential);
authenticated = true;
completeDispatcher();
}
else errorDispatcher('testCall API does not exist');
});
}
else errorDispatcher('no authentication token returned');
}
else errorDispatcher(error);
});
Instead of wrapping a promise around every API call I just incorporated an idle routine on the client that refreshes the user token when they return to the app as well as refreshes the token every 59 seconds that they are idle.
So for all intense and purposes they will always have an valid token or perpetual state.
$(document).idle({
onIdle: function () {
// refresh user token
if (User.Person !== null)
User.Person.reauthenticate().done();
},
onActive: function () {
// when the user returns refresh their token 1 more time
if (User.Person !== null)
User.Person.reauthenticate().done();
},
idle: 59000, // 59 seconds
recurIdleCall: true // will keep refreshing every 59 seconds
});
https://github.com/kidh0/jquery.idle

How to preserve user logged in using Parse JS and Facebook SDK

I'm using Parse Server + Parse JS Sdk to handle user login through Facebook. Everything works fine until I refresh web browser. What data should I store after login process is done? I belive that FB AccessToken is important to keep Facebook Session, but what about Parse Session.
Current code:
login: function (callback) {
console.log('loggin in...')
Parse.FacebookUtils.logIn('user_likes,email', {
success: function (parseUser) {
if (!parseUser.existed()) {
console.log('signed up and logged in!')
} else {
console.log('logged in!')
}
console.log('parse user is: ', parseUser.id)
if (callback) { callback() }
},
error: function (parseUser, error) {
console.log('login cancelled: ', error.message)
}
})
}
You don't need to manually store anything. You can use the parse function:
Parse.User.current()
To see if there is already a user logged-in.
We made this function:
function userAuthenticated(){
if(Parse.User.current() === null){
return false;
}
if(Parse.User.current().authenticated()){
return true;
}
else{
return false
}
}

Promise either never get called, or is rejected (Parse JS SDK)

I am trying to write a function that add or edit some fields on a User object.
The problem come when I try to save the user, if I use user.save, the Promise is rejected with error 206 UserCannotBeAlteredWithoutSessionError.
However, if I get the session id (and documentation about that is scarce), the promise never get resolve, nor rejected. The app seems to just jump to the callback.
My function:
function update(user, callback) {
let query = new Parse.Query(Parse.User);
query.equalTo("username", user.email);
query.find().then(
(users) => {
if(users.length === 0) {
callback('Non existent user');
} else {
let user = users[0];
// user.set('some', 'thing');
console.log('save');
user.save(/*{
sessionToken: user.getSessionToken()
}*/).then(
(test) => {
console.log('OK - ' + test);
callback();
}, (err) => {
console.log('ERR- ' + require('util').inspect(err));
// console.log(callback.toString());
callback(error.message);
}
);
}
},
(error) => {
callback(error.message);
}
);
}
Called with:
var async = require('async'),
baas = require('./baas.js');
async.waterfall([
(callback) => {
callback(null, {
email: 'user#test.com',
password: 'password'
});
},
(user, callback) => {
console.log('connect');
baas.connect(() => { //Initialize the connection to Parse, and declare use of masterKey
callback(null, user);
});
},
(user, callback) => {
console.log('update');
baas.update(user, (err) => {
callback(err);
});
}
], (err) => {
console.log('Error: ' + err);
});
The logs become:
Without session token:
connect
update
save
ERR- ParseError { code: 206, message: 'cannot modify user sA20iPbC1i' }
With session token:
connect
update
save
I do not understand how it is possible that the promise just callback without printing anything, nor why no error are raised anywhere.
Edit:
Following #user866762 advice, I tried to replace the query with Parse.User.logIn and use the resulting User object.
While this solution give me a sessionToken, the end result is the same, parse crash if I don t provide the session token, or give me a error if I do.
According to the Parse Dev guide:
...you are not able to invoke any of the save or delete methods unless the Parse.User was obtained using an authenticated method, like logIn or signUp.
You might also try becoming the user before saving, but I have my doubts that will work.
When you're "get[ting] the session id" my guess is that you're really breaking something. Either Parse is having a heart attack at you asking for the session token, or when you're passing it in save you're causing something there to explode.

Categories

Resources