Expo Facebook Login- Producing Invalid Tokens - facebook

I followed the docs to use the Facebook Login SDK. Everything works except for the fact that the token that is generated does not work for our API. Our API takes the user-generated token as a header so that it can make requests. I know the reason why it isn't working is that I am logging in with Facebook, but there is no account created on our API. Facebook will not give me access to a user's password (for obvious reasons), so I can't generate an account from the information provided from Facebook.
I think the answer lies with App Access Tokens. If someone could help me out I would really appreciate it!
code:
export const logInFB = () => async dispatch => {
const { type, token } = await Expo.Facebook.logInWithReadPermissionsAsync('**Blocking this out**', {
permissions: ['public_profile'],
});
console.log('token');
console.log(token);
if (type === 'success') {
// Get the user's name using Facebook's Graph API
const response = await fetch(
`https://graph.facebook.com/me?access_token=${token}`);
console.log('fb token')
console.log(response);
dispatch(fbLoginToken(token));
Alert.alert(
'Logged in!',
`Hi ${(await response.json()).name}!`,
);
}
}

Looks like you are missing the fields property in the URL. ex: &fields=id,name,email,about,picture
Please refer to this example: https://snack.expo.io/#bacon/facebook
const response = await fetch(
`https://graph.facebook.com/me?access_token=${token}&fields=id,name,email,about,picture`
);
const responseJSON = JSON.stringify(await response.json());
this.setState({ responseJSON });

Related

Facebook Profile Picture Link Changes?

Does a link to a facebook profile picture stay up to date or should I store images in storage?
I am using firebase and facebook authentication and grabbing a users profile picture link like this when they FIRST create an account:
const photoLarge = await getFacebookUserInfo().then((userResponse) => {
return userResponse.picture.data.url.toString()
}).catch((error) => {
return error
});
const userId = await firebaseService.auth().currentUser.uid;
writeUserData(
userId,
photoLarge,
);
}
For some reason I noticed in dev vs prod I have 2 different links with the dev not working.
Dev doesn't work:
https://platform-lookaside.fbsbx.com/platform/profilepic/?asid=10161383578450224&height=200&width=200&ext=1558132998&hash=AeTUIkafEn5zw5PF
Prod Does:
https://platform-lookaside.fbsbx.com/platform/profilepic/?asid=10161383578450224&height=200&width=200&ext=1558673410&hash=AeQGA8guHyxIK9du
I am trying to figure out if the facebook picture should be downloaded and stored in storage and then referenced instead and if so how to go about doing that? (/ is there a expiration date on a link)
I haven't seen if this is happening or not for Google Sign-in.
Here is my graph request:
//graph QL request to get larger facebook profile
export const getFacebookUserInfo = () => {
return new Promise((resolve, reject) => {
const infoRequest = new GraphRequest(
'/me',
{
parameters: {
fields: {
string: 'email,about,name,picture.type(large)'
}
}
},
(error, data) => {
if (error) {
reject(error);
} else {
resolve(data);
}
}
);
new GraphRequestManager().addRequest(infoRequest).start();
})
}
So somehow I finally figured this out today. Essentially the graphAPI spits back several pieces with one being a picture piece. This looks like the links I posted above https://platform-lookaside.fbsbx.com/platform/profilepic
THIS CHANGES!!! Not sure how often, but do NOT use this as eventually it will be a dead link.
However, what I missed was that you can use the ID that the graphAPI spits back instead and use the following link:
http://graph.facebook.com/{your_id_goes_here}/picture?type=large&redirect=true&width=500&height=500
More information can be found in this other post:
Get user profile picture by Id

How to get the Authentication Provider for actions-on-google on Node using account linking with Auth0?

I have Javascript App running under Node v8.11.2 which uses the Actions-On-Google library. I'm using the V2 API. I have account linking set up with Auth0 and am using the SignIn helper intent. Auth0 is set up to use Google, Facebook and Twitter.
The scopes I use are OPENID, OFFLINE_ACCESS, PROFILE and EMAIL.
Everything is working fine and when the User is authenticated I get an Access Token returned.
My question is, how do I get the Authentication Provider that was selected by the User so that I can use the Access Token correctly to retrieve profile elements such as the display name, email address etc??
The signin object passed to the Sign In Confirmation intent handler just contains the following regardless of the provider selected: -
{"#type":"type.googleapis.com/google.actions.v2.SignInValue","status":"OK"}
Any help greatly appreciated as I have a deadline and this is driving me a bit crazy now!
Thanks,
Shaun
If your question is about how to get the required information when you have your accessToken available then you could use what is shown in this answer.
In node this looks like that:
let link = "https://www.googleapis.com/oauth2/v1/userinfo?access_token="+accessToken;
return new Promise(resolve => {
request(link,(error, response, body) => {
if (!error && response.statusCode === 200) {
let data = JSON.parse(body);
let name = data.given_name ? data.given_name : '';
conv.ask(new SimpleResponse({
speech: "Hello "+ name + "!",
text: "Hello "+ name + "!"
}));
resolve();
} else {
console.log("Error in request promise: "+error);
resolve();
}
})
})
Everything you need should be in the data object.
Hope it helps.

How do I just get an email address after authenticating with oAuth2? - google-api-nodejs-client

I am trying to just get an email address after authenticating with oAuth2. After I get a code when I validate with a google account, I go and get the user from Google Plus, like this:
let oAuth2Client = new auth.OAuth2(GOOGLE_CLIENT_ID, GOOGLE_CLIENT_SECRET, GOOGLE_CLIENT_CALLBACK);
const tokens = await getToken(oAuth2Client, code);
oAuth2Client.setCredentials(tokens);
plus('v1').people.get({ userId: 'me', auth: oAuth2Client }, function(err, response) {
.... This repsonse is the full user object from Google Plus
});
How do I just get the email address, or a list of email addresses? I don't want all the other Google Plus info. I have already set my scope to email, but I still get lots of other information. I am assuming that I need to make a request to something other than plus, but I can't find what to do in the documentation.
If you have set email scope (https://www.googleapis.com/auth/userinfo.email), you can use oauth2("v2").userinfo.v2.me.get :
var google = require('googleapis');
....
google.oauth2("v2").userinfo.v2.me.get({
auth: oAuth2Client
}, function(e, profile) {
if ("email" in profile) {
console.log(profile.email);
} else {
console.log("scope email not set");
}
});

Sails Rest API using Passport-Facebook-Token Strategy Driving Me Nuts

I have a mobile front-end that already has facebook authetication working. I have a Sails REST API that stores user data, posts etc.. I want to add security where facebook users can only POST GET DELETE PUT their own data.
I've read a almost every tutorial for facebook authenticating a web-app, but haven't found many for authenticating with a mobile app to protect the user data. I've tried to get Passport-Facebook-Token working but I just don't understand the little documentation available. I'm coming from a objective-C background so in the node learning curve now.
Here's the link to what I'm working with but I'm obviously missing something: https://github.com/drudge/passport-facebook-token
I have:
AuthController.js
module.exports = {
facebook: function(req, res) {
passport.authenticate('facebook-token', function(error, user, info) {
// do stuff with user
res.ok();
})(req, res);
}
};
api/services/protocols/passport.js
(with some other stuff from default passport sails-generate-auth)
var FacebookTokenStrategy = require('passport-facebook-token');
passport.use('facebook-token', new FacebookTokenStrategy({
clientID : "<my_id>",
clientSecret : "<my_secret>"
},
function(accessToken, refreshToken, profile, done) {
// console.log(profile);
var user = {
'email': profile.emails[0].value,
'name' : profile.name.givenName + ' ' + profile.name.familyName,
'id' : profile.id,
'token': accessToken
}
// You can perform any necessary actions with your user at this point,
// e.g. internal verification against a users table,
// creating new user entries, etc.
return done(null, user); // the user object we just made gets passed to the route's controller as `req.user`
}
));
Do I have to do something with config/routes to make sure it only allows users with access_tokens? I just can't find any resources out there. Passport doesn't even list Passport-Facebook-Token strategy as an option on their site.
thank you for the help

JS SDK getLoginStatus doesn't return userID nor signedRequest

I'm using PhoneGap/Cordova with the facebook plugin. Everything seems to work except for getLoginStatus who is not working as defined here and here. When called, it returns some data, but not all: it doesn't return userID nor signedRequest.
Here is the code:
FB.getLoginStatus(function(response) {
if (response.status == 'connected') {
var fb_uid = response.authResponse.userID;
var fb_signedRequest = response.authResponse.signedRequest;
alert('logged in');
} else {
alert('not logged in');
}
});
userID is filled with ellipsis (...), while signedRequest is undefined.
I managed to get userID with a graph call to /me:
FB.api('/me', function(me){
if (me.id) {
var fb_uid = me.id;
}
});
I wasn't able to find any way in the documentation to get a signed_request, which I have to use to authenticate the facebook user to a remote service to whom the user already connected to with facebook (I already made a login call so user is OK).
Basically the problem is that my call to getLoginStatus returns
{
status: 'connected',
authResponse: {
session_key: true,
accessToken: 'a long string...',
expiresIn:'a number',
sig: '...', //exactly this string
userID:'...' //exactly this string
secret:'...' //exactly this string
expirationTime:'a long number'
}
}
instead of what documented
As a background, when authentication happens using the plugin then the JavaScript SDK API calls the iOS/Android SDK to handle the authorization and then pass response auth data back to the JS part. The native (iOS/Android) SDKs do not get signed requests back to be able to pass this on to the JS. This is why it's empty.
If you use the latest plugin you should at least now be seeing the user ID. The one from June likely did not pass this back. Otherwise as a work around, you could perform a call to the /me endpoint when authentication is successful in your JS code to get the user id. See the Hackbook example that does this.