How can I get user email when logging in through Facebook in parse.com - facebook-javascript-sdk

I need to obtain a user email for business purposes in my parse.com application. Is it possible to fetch it during Facebook sign-up/login process?
For example I have the following login code
var signupLoginFB = function() {
Parse.FacebookUtils.logIn("email", {
success: function(user) {
//do something on successful login
},
error: function(user, error) {
//do something on error
}
});
}
I looked at the "user" object passed to the callback, and I didn't see any email there. Should I call some other FB or Parse API to fetch these data?

You'll want to make a call to FB.api() as follows:
var signupLoginFB = function() {
Parse.FacebookUtils.logIn("email", {
success: function(user) {
//do something on successful login
FB.api('/me', function(me) {
user.set("displayName", me.name);
user.set("email", me.email);
user.save();
console.log("/me response", me);
});
},
error: function(user, error) {
//do something on error
}
});
}
You'll see in the console all the fields returned. Note that they'll vary based on what they have decided to share, for example my Facebook profile doesn't include my email as public so it isn't returned in the "/me" call.
Consider also only doing the extra call if it is a new user, ie wrap that code in if (!user.existed()) {...}.

Related

Office web add-in in JS and login with SSAL : interaction_in_progress after login

I'm trying to get an access token from Microsoft to connect to Graph API, by using a client that is a web add-in in Word 365 desktop (pure JS, not made with Angular or Node).
To authenticate, this is the code I'm using:
window.Office.onReady(() => {
initMsalInstance();
});
function initMsalInstance() {
myMSALObj = new msal.PublicClientApplication({
auth: {
clientId: "...",
authority: "...",
redirectUri: "",
},
cache: {
cacheLocation: 'localStorage',
storeAuthStateInCookie: true
}
});
myMSALObj.handleRedirectPromise()
.then((response) => {
if (response) {
console.log(response);
} else {
console.log('noresp');
}
})
.catch((error) => {
console.log(error)
});
}
function signIn() {
myMSALObj.loginRedirect({
scopes: ['user.read', 'files.read.all']
});
}
I just have a button that calls the "signIn()" method, then it opens Chrome, I'm loggin in, and I'm redirected to the page I selected.
Unfortunately, in the add-in, nothing happens, my handleRedirectPromise() doesn't seem to get called, so I don't have the response and the token.
If I'm trying to click on "sign in" again, then this is the error I get:
interaction_in_progress: Interaction is currently in progress. Please ensure that this interaction has been completed before calling an interactive API. For more visit: aka.ms/msaljs/browser-errors.
What can I do to complete the process and get my token into my Office 365 Word Web add-in?
You are getting this error because of this piece of code:
msalInstance.loginRedirect(loginRequest);
This code looks into the session storage for the key MSAL.[clientId].interaction.status and other temp values required for redirection process.
If such value exist and it's value equals the 'interaction_in_progress' then error will be thrown.
This is the known issue in MSAL.
Follow these steps to resolve this issue.
Account selection logic is app dependent and adjust as needed for different use cases. Set active account on page load.
const accounts = msalInstance.getAllAccounts();
if (accounts.length > 0) {
msalInstance.setActiveAccount(accounts[0]);
}
msalInstance.addEventCallback((event) => {
if (event.eventType === EventType.LOGIN_SUCCESS && event.payload.account) {
const account = event.payload.account;
msalInstance.setActiveAccount(account);
}
}, error=>{
console.log('error', error);
});
console.log('get active account', msalInstance.getActiveAccount());
// handle auth redirect/do all initial setup for MSAL
msalInstance.handleRedirectPromise().then(authResult=>{
// Check if user signed in
const account = msalInstance.getActiveAccount();
if(!account){
// redirect anonymous user to login page
msalInstance.loginRedirect();
}
}).catch(err=>{
// TODO: Handle errors
console.log(err);
});

How can I have a seperate login page using Durandal that has a different layout then the shell?

I've read through Durandal login page redirect pattern wow, lots of code to do what I'd think would be pretty simple.
I've also read through https://groups.google.com/forum/#!topic/durandaljs/RdGpwIm1oOU as I'd like the login page to have a simple logo with a login form, but I'd also like routing for a registration and about page as well. The rest of my site will have a menu, header, etc which I don't want to show until the user is logged in. Also, I'm not sure how this approach would update when the user logs in.
Another code example that almost does what I want to do: https://github.com/Useful-Software-Solutions-Ltd/Durandal451/blob/master/Durandal451v2/App/global/session.js
So, what should I do? Is there an official way to do this? There seems to be a mish mash of things out there that people have tried. I would think this would be a really common occurrence but couldn't find anything on the main docs.
I'm not sure this is the simplest way, but this is what I got
you will need to add some extra function after app.start() is triggered.
main.js
var auth = require('authentication'); // Authentication module
app.start().then(function()
{
// This function will wait for the promise
auth.init().then(function(data)
{
// When successfully authenticate, set the root to shell
app.setRoot('views/shell');
}
});
authentication.js
define(function(require)
{
var app = require('durandal/app');
return {
init: function()
{
// Initialize authentication...
return system.defer(function(dfd)
{
// Check if user is authenticate or if there has stored token
var isAuthenticate = someOtherFunctiontoCheck();
if (isAuthenticate)
{
dfd.resolve(true); // return promise
}
else
{
// When not authenticate, set root to login page
app.setRoot('views/login');
}
}
}
};
});
good luck! :)
UPDATE
login.js
define(function(require)
{
var ko = require('knockout');
var auth = require('authentication');
var username = ko.observable();
var password = ko.observable();
return {
username: username,
password: password,
submitForm: function()
{
// Do a login, if success, auth module will take care of it
// and here will take of the error
auth.login(username(), password()).error(function()
{
// notify user about the error (e.g invalid credentials)
});
}
};
});
Authentication.js
define(function(require)
{
var app = require('durandal/app');
return {
init: function()
{
// Initialize authentication...
return system.defer(function(dfd)
{
// Check if user is authenticate or if there has stored token
var isAuthenticate = someOtherFunctiontoCheck();
if (isAuthenticate)
{
dfd.resolve(true); // return promise
}
else
{
// When not authenticate, set root to login page
app.setRoot('views/login');
}
}
},
login: function(username, password)
{
// do authenticate for login credentials (e.g for retrieve auth token)
return $.ajax({
url : 'api/login',
type : 'POST',
data : {
username: username,
password: password
}
}).then(function(token){
// on success, stored token and set root to shell
functionToStoreToken(token);
// Set root to shell
app.setRoot('views/shell');
});
}
};
});

Express REST API - Delete Method

I am getting stuck on the delete method for my API. My application requires a user to log in and then he can add courses. The courses are stored in a nested array inside the User model. I want the user to be able to cancel (delete) a course from the view and then have the course deleted from the user's profile on the server. I am getting a 404 response event though the variables I am comparing are identical.
This is my ajax call to delete a specific course:
jQuery.ajax({
url: "/test/signups/5387c1a0fb06e48f4658170c",
type: "DELETE",
success: function (data, textStatus, jqXHR) {
console.log("Post resposne:");
console.dir(data);
console.log(textStatus);
console.dir(jqXHR);
}
});
This is my delete method:
app.delete('/test/signups/:id', isLoggedIn, function(req, res) {
User.findOne({'_id': req.user.id }, function(err, user) {
if (err)
return done(err);
if (user) {
var found = false;
var singlesignup = user.signup.filter(function(e){ return e._id == req.params.id })[0]
user.signup.forEach(function (singlesignup, index) {
if (singlesignup._id === req.params.id) {
found = index;
}
});
if(found) {
user.signup.splice(found, 1);
res.json(200, {status: 'deleted'});
} else {
res.json(404, {status: 'invalid survey question deletion'});
}
}
});
});
The _id values in mongodb are not strings, they are instances of the ObjectId class and they don't work correctly with the == or === operators. It's completely a nuisance. But anyway try converting them to strings before comparing: singlesignup._id.toString() === req.params.id. To get it truly correct in the long run, make sure you handle all the cases of null, string or ObjectId. Consider a helper library such as objectid.

Authentication and OpenGraph

this is my first attempt playing around with facebook apps and OpenGraph. I've followed the example at developers.facebook.com. So far, so good.
What I am trying to do though is:
When clicking a certain image, check so that the user is logged and have authenticated your app. I want the user to be able to use the page without going through authentication. Only one specific action (clicking that image) requires that the user authenticate.
If the user is logged in and have authenticated your app then publish a message on the user's stream.
If the user is not logged in and/or have not authenticated your app show the authentication dialog if the user clicks on the image. Once accepted, post a message on the user's stream.
<a onclick="fb_login();" href="#" class="productlink1"><img id="product1" onclick="postCook()" alt="" src="img/fressko_heart_black.png"/></a> <a class="productlink2"><img id="product2" alt="" src="img/fressko_checked_black.png"/></a>
I know this is not the ultimate piece of code, especially as it has two onclick="" that will trigger at the same time. So, I need a different solution to that.
The JavaScript function to post on the user's feed looks like this:
function postCook()
{
FB.api(
'/me/xxxxxx:cook',
'post',
{ recipe: 'http://www.zzzzzzz.com/test/' },
function(response) {
if (!response || response.error) {
alert('Error occured');
} else {
alert('Cook was successful! Action ID: ' + response.id);
}
});
}
The JavaScript to authenticate the user looks like this:
window.fbAsyncInit = function() {
FB.init({
appId : 'xxxxxx',
oauth : true,
status : true, // check login status
cookie : true, // enable cookies to allow the server to access the session
xfbml : true // parse XFBML
});};
function fb_login(){
FB.login(function(response) {
if (response.authResponse) {
console.log('Welcome! Fetching your information.... ');
//console.log(response); // dump complete info
access_token = response.authResponse.accessToken; //get access token
user_id = response.authResponse.userID; //get FB UID
FB.api('/me', function(response) {
user_email = response.email; //get user email
// you can store this data into your database
});
} else {
//user hit cancel button
console.log('User cancelled login or did not fully authorize.');
}
}, {
scope: 'publish_stream'
});
}(function() {
var e = document.createElement('script');
e.src = document.location.protocol + '//connect.facebook.net/en_US/all.js';
e.async = true;
document.getElementById('fb-root').appendChild(e);}());
Does anyone have any good solution to my problem? Or a kick in the right direction. I prefer using PHP usually, but for this mission JavaScript seems to be the weapon of choise.
Regards,

FB.Event.subscribe('auth.login', function(response) { }) issue

FB.Event.subscribe('auth.login', function(response) {
FB.api('/me', function(response){
//Some operation
});});
Above piece of JavaScript code runs when user logs-in through Facebook
or
when user is already logged-in the browser and you open the page containing the above JavaScript.
Is there any way to execute the operation only when user logs-in for first time and escape the operation when user is already logged-in in the browser?
Run FB.getLoginStatus to see if the user is already connected to your app and logged in.
https://developers.facebook.com/docs/reference/javascript/FB.getLoginStatus/
FB.getLoginStatus(function(response) {
if (response.session) {
// logged in and connected user, someone you know
} else {
// no user session available, someone you dont know
}
});
Try subscribing to the event if and only if the user is not connected.
function listen_for_authorization (cb) {
FB.getLoginStatus(function (res) {
if (!res || res.status !== "connected") {
FB.Event.subscribe('auth.login', cb);
}
}
}
We reproduced this in Safari/Mac, Firefox/Windows, Internet Explorer.
See http://developers.facebook.com/bugs/255767001140894