How to get user access token in Meteor.JS after logging in by facebook - facebook

After I'm logged in using facebook account I have access to Meteor.userId()
So I tried to publish user data this way from the server:
Meteor.publish('getUserAccessToken', function(userId) {
return Meteor.users.find(userId).fetch();
});
And receive it on client:
Meteor.subscribe("getUserAccessToken",Meteor.userId());
then I would like to dig through returned user object to it's accessToken
console.log([Object].services.facebook.accessToken);
but since I remove autopublish services.facebook disappear for client.
Thanks in advance for any help.

Related

HWIOAuthBundle, how to manually authenticate User with a Facebook access token?

I have a website (Symfony2) with HWIOauthBundle used to connect with Facebook and everything works fine.
Now, I'm trying to build an iOS app with Cordova and Ionic framework (AngularJS) and I want to authenticate my user with Facebook :
With $cordovaFacebook, I authenticate my user and get a valid Facebook access token, that's ok
I try to use this access token to authenticate my user on the server-side with HWIOauthBundle :
GET http://..../login/facebook?code=MY_FACEBOOK_ACCESS_TOKEN
Symfony rejects my request with this log :
INFO - Matched route "facebook_login" (parameters: "_route": "facebook_login")
INFO - Authentication request failed: OAuth error: "Invalid verification code format."
So my question is : how can I authenticate my user on both front and back end with Facebook connect?
Thanks :)
I've also been wondering how to implement a server side login with the HWIOAuthBundle.
I didn't find any solution on the web, so I coded the functionnality based on hints I've read on the net.
Basically, you have to :
authenticate the user on your app
make an http request to your server with the Facebook token.
ont the server side, check if the token is for your Facebook app, and retrieve the user's Facebook ID.
Get your user from the DB based on the fetched ID.
Here's my Symfony controller:
public function getSecurityFbAction($token)
{
// Get the token's FB app info.
#$tokenAppResp = file_get_contents('https://graph.facebook.com/app/?access_token='.$token);
if (!$tokenAppResp) {
throw new AccessDeniedHttpException('Bad credentials.');
}
// Make sure it's the correct app.
$tokenApp = json_decode($tokenAppResp, true);
if (!$tokenApp || !isset($tokenApp['id']) || $tokenApp['id'] != $this->container->getParameter('oauth.facebook.id')) {
throw new AccessDeniedHttpException('Bad credentials.');
}
// Get the token's FB user info.
#$tokenUserResp = file_get_contents('https://graph.facebook.com/me/?access_token='.$token);
if (!$tokenUserResp) {
throw new AccessDeniedHttpException('Bad credentials.');
}
// Try to fetch user by it's token ID, create it otherwise.
$tokenUser = json_decode($tokenUserResp, true);
if (!$tokenUser || !isset($tokenUser['id'])) {
throw new AccessDeniedHttpException('Bad credentials.');
}
$userManager = $this->get('fos_user.user_manager');
$user = $userManager->findUserBy(array('facebookId' => $tokenUser['id']));
if (!$user) {
// Create user and store its facebookID.
}
// Return the user's JSON web token for future app<->server communications.
}
I throw the Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException exceptions to handle login errors on my app.
Of course, you really should use https because you will be exchanging sensible information.
I don't know if it's the best way to do it but it works well.
Hope it helps !
Well, I think that Symfony doesn't actually reject your request. Facebook is. I'm not sure if this might help, but I know that a bunch a problems can happen when dealing with the Facebook Auth :
Do you know if the tool sends, along with the code parameter, a redirect_uri parameter ? If so :
Did you check that your redirect_uri HAS a trailing slash at the end ? See this
Silly question, but did you check that your app_id is the same when you got authorized via Cordova ?
Check that your redirect_uri DOES NOT have any query parameter.
Check that the redirect_uri that you use during the whole process is the same all the time.
Overall, it seems that your issue is almost all the time related to the redirect_uri URI format.

Ember Torii facebook authentication not able to get user email

I am using Ember CLI + ember simple auth torii link
to get authentication code from facebook for my ember app.
This is my environment.js file
ENV['torii'] = {
providers: {
'facebook-oauth2': {
apiKey: '865549306850377',
scope: 'email',
//redirectUri: window.document.location.href
redirectUri: 'http://localhost:4200/'
}
}
};
And my login controller looks like this -
facebook: function() {
var _this = this;
this.get('session').authenticate('simple-auth-authenticator:torii', 'facebook-oauth2').then(function(data){
console.log("status - ", _this.get('session'));
});
}
And login.hbs -
<li><button {{action "facebook" "facebook-oauth2"}}>Facebook OAuth2</button></li>
After the user clicks on the link, a facebook popup opens and ember app gets a token.
How do I get the user's email id along with this token ?
Has anybody faced a similar issue ?
So you're using oauth2, so all you're ever going to get is an authorization token. With this token, you can then go off and request other information. The token is basically just there to speed up the validation of users against your application.
If you want to get user information, you would need to create another method (probably on your server-side), which swaps the authorization code for an access token: like so (or alternatively you can request an access token directly, which would remove the need for a server-side solution.
Using the access Token you can then request the Facebook User ID, using the debug token endpoint, and after that you will be able get to any endpoint to get the information you need.

Validating the user of an access_token

In the Facebook dev article Manually Building a Login Flow, there is a section entitled "Confirming Identity". It mentions that you need to validate codes and tokens that you receive from them via your redirect_uri.
My question: Since you don't know anything about the user that just logged in, how do you validate that the user_id that you see in the response from the token inspection endpoint is correct?
The article says:
As a result, your app should confirm that the person using the app is the same person that you have response data for before generating an access token for them.
But, how can you actually do that? Are we expected to show publicly available info about that user_id back to the user with a UI that asks "Is this you?". I haven't seen any apps/sites that do that, so I'm assuming that this isn't practically done.
Am I missing something?
You can use FB.getLoginStatus to retrieve information about the logged in user. It returns a response object for the user. If the user has authenticated your application, the response object will look like this:
{
status: 'connected',
authResponse: {
accessToken: '...',
expiresIn:'...',
signedRequest:'...',
userID:'...'
}
}
You can use the UserId returned in this object to verify the user's identity.

How to authenticate Facebook User after receiving response.status === 'connected'?

Perhaps I am going about this the wrong way but I have a website that allows facebook login.
If the user has already registered on my website
and is logged into facebook but not logged into my site
when visiting the login page i check for their facebook login status and get response.status === 'connected' via-
FB.Event.subscribe('auth.authResponseChange', function (response)
{
if (response.status === 'connected')
{
var s = JSON.stringify(response.authResponse);
LogMeIn(s, function(response)
{
HandleAjaxError(response, function(msg)
{
window.location = '/_/';
});
});
}
}
I then want to pass their authResponse object to the server and confirm that this userid works with this token before I log them in as this user
I have read to simply grab the json contents of -
https://graph.facebook.com/{userID}?access_token={accessToken}
and if it does not return an error then it is good! But when testing this method I noticed that the same access_token worked for two different user ids (meaning it did not return an error for the userid that was not logged in on my computer). Instead it returned the facebook user object with name , location etc.
This really surprised me, as I expected the access_token to work only with a single user id.
In an effort to prevent someone from simply changing the user id before continuing the script I need to authenticate via server side. What is a way to accomplish this?
Proof, go to these links to see profile information
My profile-
https://graph.facebook.com/1233822590?access_token=CAACCBJJZBgjABAOGmvmsou8gMYGulLHTgAr5ZCHZAU7pKEp0cMAeX8r4qHLpiVuZCOT1v0ulMZAxX5YfLJkcZBr9l6qJQoPxWS5Fs5ndohDnH6ZAPPfZCZCTQtwWgAZAg6I1PAOIpdtCc0OUaMmBZAvGiMm9gQhmNXRbocZD
Another userid with same access_token-
https://graph.facebook.com/100000116781159?access_token=CAACCBJJZBgjABAOGmvmsou8gMYGulLHTgAr5ZCHZAU7pKEp0cMAeX8r4qHLpiVuZCOT1v0ulMZAxX5YfLJkcZBr9l6qJQoPxWS5Fs5ndohDnH6ZAPPfZCZCTQtwWgAZAg6I1PAOIpdtCc0OUaMmBZAvGiMm9gQhmNXRbocZD
Nothing to be surprised. You can fetch the basic details of any user of the facebook using the access token of any user of the facebook.. So this isnt really good way to validate the token. Moreover, that confirmation of token part isnt required.
If you want the authorization through server side go through.this link

How do I get a user's email address using accounts-facebook in Meteor?

I created a Meteor app that allows users to sign on using Facebook. To do this, I'm using the accounts-ui and accounts-facebook packages. This works fine.
How do I retrieve the user's email address once they've signed on? I understand that this requires special permission, and so I added email as a "User & Friend's Permission" in the app settings on the Facebook developers site. Following the Meteor documentation, I also set up Account.ui.config like this:
Accounts.ui.config({
requestPermissions: {
facebook: ['email'],
},
passwordSignupFields: 'USERNAME_AND_EMAIL'
});
As expected, when a user of my app signs on using Facebook, it correctly asks them to share their email address. But how do I retrieve it? The user document has only the _id and profile.name.
The Facebook user's email address is stored in [userDocument].services.facebook.email, which is not published to the client, but can be accessed from the server or from the client using Meteor.methods and Meteor.call.
this will add the Facebook profile info to the client side user object.
Accounts.onCreateUser (options, user) ->
if options.profile
user.profile = options.profile
# get profile data from Facebook
result = Meteor.http.get "https://graph.facebook.com/me", {
params: access_token: user.services.facebook.accessToken}
if !result.error && result.data
#if successfully obtained facebook profile, save it off
#the user can access the profile object on the client
user.profile.facebook = result.data;
return user
on the server side the facebook.accesstoken can be accessed... so use it to get the full FB info and save it to the client user object..
ping a Meteor.user() in the console now to get the FB info.
dont think this is exactly best practice in terms of having FB info on the client..