Facebook Graph API, how to get users email? - php

I'm using the Graph API, but I can't figure out how to get a logged-in users email address.
The intro to Graph states "The Graph API can provide access to all of the basic account registration data you would typically request in a sign-up form for your site, including name, email address, profile picture, and birthday"
All well and good, but how do I access that info?
This is what I have so far:
$json = $facebook->api('/me');
$first = $json['first_name']; // gets first name
$last = $json['last_name'];

The only way to get the users e-mail address is to request extended permissions on the email field. The user must allow you to see this and you cannot get the e-mail addresses of the user's friends.
http://developers.facebook.com/docs/authentication/permissions
You can do this if you are using Facebook connect by passing scope=email in the get string of your call to the Auth Dialog.
I'd recommend using an SDK instead of file_get_contents as it makes it far easier to perform the Oauth authentication.

// Facebook SDK v5 for PHP
// https://developers.facebook.com/docs/php/gettingstarted/5.0.0
$fb = new Facebook\Facebook([
'app_id' => '{app-id}',
'app_secret' => '{app-secret}',
'default_graph_version' => 'v2.4',
]);
$fb->setDefaultAccessToken($_SESSION['facebook_access_token']);
$response = $fb->get('/me?locale=en_US&fields=name,email');
$userNode = $response->getGraphUser();
var_dump(
$userNode->getField('email'), $userNode['email']
);

Open base_facebook.php
Add Access_token at function getLoginUrl()
array_merge(array(
'access_token' => $this->getAccessToken(),
'client_id' => $this->getAppId(),
'redirect_uri' => $currentUrl, // possibly overwritten
'state' => $this->state),
$params);
and Use scope for Email Permission
if ($user) {
echo $logoutUrl = $facebook->getLogoutUrl();
} else {
echo $loginUrl = $facebook->getLoginUrl(array('scope' => 'email,read_stream'));
}

Just add these code block on status return, and start passing a query string object {}. For JavaScript devs
After initializing your sdk.
step 1: // get login status
$(document).ready(function($) {
FB.getLoginStatus(function(response) {
statusChangeCallback(response);
console.log(response);
});
});
This will check on document load and get your login status check if users has been logged in.
Then the function checkLoginState is called, and response is pass to statusChangeCallback
function checkLoginState() {
FB.getLoginStatus(function(response) {
statusChangeCallback(response);
});
}
Step 2: Let you get the response data from the status
function statusChangeCallback(response) {
// body...
if(response.status === 'connected'){
// setElements(true);
let userId = response.authResponse.userID;
// console.log(userId);
console.log('login');
getUserInfo(userId);
}else{
// setElements(false);
console.log('not logged in !');
}
}
This also has the userid which is being set to variable, then a getUserInfo func is called to fetch user information using the Graph-api.
function getUserInfo(userId) {
// body...
FB.api(
'/'+userId+'/?fields=id,name,email',
'GET',
{},
function(response) {
// Insert your code here
// console.log(response);
let email = response.email;
loginViaEmail(email);
}
);
}
After passing the userid as an argument, the function then fetch all information relating to that userid. Note: in my case i was looking for the email, as to allowed me run a function that can logged user via email only.
// login via email
function loginViaEmail(email) {
// body...
let token = '{{ csrf_token() }}';
let data = {
_token:token,
email:email
}
$.ajax({
url: '/login/via/email',
type: 'POST',
dataType: 'json',
data: data,
success: function(data){
console.log(data);
if(data.status == 'success'){
window.location.href = '/dashboard';
}
if(data.status == 'info'){
window.location.href = '/create-account';
}
},
error: function(data){
console.log('Error logging in via email !');
// alert('Fail to send login request !');
}
});
}

To get the user email, you have to log in the user with his Facebook account using the email permission. Use for that the Facebook PHP SDK (see on github) as following.
First check if the user is already logged in :
require "facebook.php";
$facebook = new Facebook(array(
'appId' => YOUR_APP_ID,
'secret' => YOUR_APP_SECRET,
));
$user = $facebook->getUser();
if ($user) {
try {
$user_profile = $facebook->api('/me');
} catch (FacebookApiException $e) {
$user = null;
}
}
If he his not, you can display the login link asking for the email permission :
if (!$user) {
$args = array('scope' => 'email');
echo 'Login with Facebook';
} else {
echo 'Logout';
}
When he is logged in the email can be found in the $user_profile array.
Hope that helps !

Assuming you've requested email permissions when the user logged in from your app and you have a valid token,
With the fetch api you can just
const token = "some_valid_token";
const response = await fetch(
`https://graph.facebook.com/me?fields=email&access_token=${token}`
);
const result = await response.json();
result will be:
{
"id": "some_id",
"email": "name#example.org"
}
id will be returned anyway.
You can add to the fields query param more stuff, but you need permissions for them if they are not on the public profile (name is public).
?fields=name,email,user_birthday&token=
https://developers.facebook.com/docs/facebook-login/permissions

You can retrieve the email address from the logged in user's profile. Here is the code snippet
<?php
$facebook = new Facebook(array(
'appId' => $initMe["appId"],
'secret' => $initMe["appSecret"],
));
$facebook->setAccessToken($initMe["accessToken"]);
$user = $facebook->getUser();
if ($user) {
$user_profile = $facebook->api('/me');
print_r($user_profile["email"]);
}
?>

First, activate your application at the Facebook Developer center. Applications in development mode are not allowed to retrieve the e-mail field.
If the user is not logged in, you need to login and specify that your application/site will need the e-mail field.
FB.login(
function(response) {
console.log('Welcome!');
},
{scope: 'email'}
);
Then, after the login, or if the user is already logged, retrieve the e-mail using the Facebook API, specifying the field email:
FB.api('/me', {fields: 'name,email'}, (response) => {
console.log(response.name + ', ' + response.email);
console.log('full response: ', response);
});

https://graph.facebook.com/me
will give you info about the currently logged-in user, but you'll need to supply an oauth token. See:
http://developers.facebook.com/docs/reference/api/user

The email in the profile can be obtained using extended permission but I Guess it's not possible to get the email used to login fb. In my app i wanted to display mulitple fb accounts of a user in a list, i wanted to show the login emails of fb accounts as a unique identifier of the respective accounts but i couldn't get it off from fb, all i got was the primary email in the user profile but in my case my login email and my primary email are different.

Make sure your Facebook application is published. In order to receive data for email, public_profile and user_friends your app must be made available to public.
You can disable it later for development purposes and still get email field.

The following tools can be useful during development:
Access Token Debugger: Paste in an access token for details
https://developers.facebook.com/tools/debug/accesstoken/
Graph API Explorer: Test requests to the graph api after pasting in your access token
https://developers.facebook.com/tools/explorer

Make sure to fully specify the version number of the API as something like "v2.11" and not "2.11"
I'm not sure what it defaults to if this is incorrect, but I got some odd errors trying to just retrieve the email when I missed the v.

For me the problem with collecting user's email addres on PHP side (getGraphUser() method) was, that the default behavior of facebook-rendered button (on WEBSIDE side, created with xfbml=1) is to implicity calling FB.login() with the scope NOT including "email".
That means you MUST:
1) call
FB.login(....,{scope: email})
manifestly, creating your own button to start login process
OR
2) add scope="email" attribute to the xfbml button
<div class="fb-login-button" data-size="large" data-button-type="continue_with" data-
layout="rounded" data-auto-logout-link="false" data-use-continue-as="true" data-
width="1000px" scope="email"></div>
to be able to collect email address on PHP side.
Hope it helps.

Related

Can't Get Response.email from facebook API v2.5 even email is green in App Reviews

Can't Get Response.email from facebook API v2.5 even email is green in App Reviews. I used this basic FB.api(), even with SCOPE it doesn't return EMAIL
FB.api('/me', function(response) {
console.log(response);
});
The proper way to ask for additional fields (other than id and name) is this one:
FB.api('/me', {fields: 'email'}, function(response) {
console.log(response);
});
Of course, make sure you have added the email permission in the scope:
FB.login(function(response) {
if (response.authResponse) {
}
}, {scope: 'email'});
Additional information.
Btw, you can test API calls here.
First of all make sure that FB.login() is called with scope: email so that the token will have the permission to access the user's email.
Then, you should mention the field email explicitly while calling /me since by default it will return id and name only.
FB.api('/me?fields=email', function(response) {
console.log(response);
});
Make sure you define "email" scope while login, then you could get it when you ask graph.facebook.com:
$url = 'https://www.facebook.com/dialog/oauth';
$params = array(
'client_id' => $this->strategy['app_id'],
'redirect_uri' => $this->strategy['redirect_uri'],
'scope' => 'email',
);
mybad, nothing is wrong with the code, I just did a reset with the permissions on the app.

facebook OAuthException: An active access token must be used to query information about the current user

Possible duplicate of facebook Uncaught OAuthException: An active access token must be used to query information about the current user
But I did not get a proper solution.
I am using facebook sdk with codeigniter it is working properly. but sometimes it throws exception OAuthException: An active access token must be used to query information about the current user.
Here is the code of Controller file
$config = array(
'appId' => 'XXXXXXX',
'secret' => 'XXXXXXXXXXXXXXXXXXXXXXXXXX',
'fileUpload' => true,
);
$this->load->library('facebook/Facebook', $config);
$fbme = null;
$user = $this->facebook->getUser();
if ($user) {
try {
$fbme = $this->facebook->api('/me');
} catch (FacebookApiException $e) {
error_log($e);
$user = null;
}
}
//if user is logged in and session is valid.
if ($fbme){
//do some stuff...
//redirecting to user home page (my site's)
}
In view file, I am using js sdk. Code for view file is
<div id="fb-root"></div>
<script type="text/javascript">
var button2;
window.fbAsyncInit = function() {
FB.init({ appId: 'XXXXXXXX',
status: true,
cookie: true,
xfbml: true,
oauth: true});
function updateButton(response) {
button1 = document.getElementById('fb-login'); //login button
button2 = document.getElementById('fb-logout'); //logout button
if (response.authResponse) {
//user is already logged in and connected
button2.onclick = function() {
FB.logout(function(response) {});
};
} else {
//user is not connected to your app or logged out
button1.onclick = function() {
FB.login(function(response) {
if (response.authResponse) {
} else {
//user cancelled login or did not grant authorization
}
}, {scope:'email,user_birthday,user_about_me,user_likes,user_interests,user_education_history,user_work_history'});
}
}
}
// run once with current status and whenever the status changes
FB.getLoginStatus(updateButton);
FB.Event.subscribe('auth.login', function(response) {
window.location.reload();
});
FB.Event.subscribe('auth.logout', function(response) {
window.location.reload();
});
};
(function() {
var e = document.createElement('script'); e.async = true;
e.src = document.location.protocol
+ '//connect.facebook.net/en_US/all.js';
document.getElementById('fb-root').appendChild(e);
}());
</script>
PROBLEM:
Sometimes the it throws "OAuthException: An active access token must be used to query information about the current user." to the error log file.
Case: user is logged in facebook and has already authenticated my app
If a user is logged in facebook and authenticated my app and tries to logged in to my site,
rather redirecting the user to my site (php sdk is not working in this case), it is loading the view file. In view file also I am checking whether the user is logged in in facebook or not. (in view) if the user is logged in it will reload the page, same controller script will run and it redirects the user to user's home page(php sdk is working in this case.).
But first time it is not working. Don't know where I am making the mistake.
Also that logout button (in view file) is also sometimes not working. Means on clicking it is not logging out the user from facebook. (It is only happening in one of my colleague's browser. She is using chrome in windows 7)
I was having a similar problem while using PHP-SDK + JS-SDK together. I temporarily solved it by removing the FB.init "cookie:true" option.
By some reason that I couldn't find, an invalid signedRequest cookie is being shared between PHP and JS, then, the valid access_token of the PHP Session was being override with an invalid access_token, thus, destroying the previously valid PHP token.
The difference between my problem and yours is that you're logging via JS and trying to access the same session on PHP (I was doing it backwards, logging on PHP and trying to use the JS-SDK).
This bug is apparently fixed on this pull request:
https://github.com/facebook/facebook-php-sdk/pull/48

Facebook Oauth 2.0 Login using PHP 3.1.1 and Javascript SDKs

I am trying to migrate to the new Facebook API for websites, and just can't get it to work smoothly. I would like to use the Javascript and PHP SDKs together, but am having problems. I can authenticate, but the page doesn't refresh automatically.
I have searched throughout SO and the Facebook documentation, but still can't get this to work correctly. I have read through http://developers.facebook.com/blog/post/534/, dowloaded the latest PHP SDK (3.1.1), and basically copied the example on the aforementioned post from facebook. I have made what I think are the correct settings in my app 'Migration' settings, but this could be where the problem lies. I can't post an image, so here are the setting:
Remove Deprecated API's: Enabled
Forces use of login secret: Enabled
Encrypted Access token: Enabled
Enhanced Auth Dialog: Enabled
(Everything else is disabled)
Here is the code:
<?php
require 'php-sdk/src/facebook.php';
$facebook = new Facebook(array(
'appId' => 'YOUR_APP_ID',
'secret' => 'YOUR_APP_SECRET',
));
// See if there is a user from a cookie
$user = $facebook->getUser();
if ($user) {
try {
// Proceed knowing you have a logged in user who's authenticated.
$user_profile = $facebook->api('/me');
} catch (FacebookApiException $e) {
echo '<pre>'.htmlspecialchars(print_r($e, true)).'</pre>';
$user = null;
}
}
?>
<!DOCTYPE html>
<html xmlns:fb="http://www.facebook.com/2008/fbml">
<body>
<?php if ($user_profile) { ?>
Your user profile is
<pre>
<?php print htmlspecialchars(print_r($user_profile, true)) ?>
</pre>
<?php } else { ?>
<fb:login-button></fb:login-button>
<?php } ?>
<div id="fb-root"></div>
<script>
window.fbAsyncInit = function() {
FB.init({
appId: '<?php echo $facebook->getAppID() ?>',
cookie: true,
xfbml: true,
oauth: true
});
FB.Event.subscribe('auth.login', function(response) {
window.location.reload();
});
FB.Event.subscribe('auth.logout', function(response) {
window.location.reload();
});
};
(function() {
var e = document.createElement('script'); e.async = true;
e.src = document.location.protocol +
'//connect.facebook.net/en_US/all.js';
document.getElementById('fb-root').appendChild(e);
}());
</script>
</body>
</html>
I was going to write this as a comment but it got a bit long... :)
A couple of pointers using the PHP SDK:
$facebook->getUser();
This will work regardless of authentication. getUser() pulls publicly available data that does not require an access token, HOWEVER if you do have an access token and the user has provided email permissions for example, this method will also contain their email address.
A better test for an authenticated user:
$code = $_REQUEST['code'] ? true : false;
if (!$code) {
echo ("<script>window.top.location=\"...\"</script>");
}
will check if a user has authorised your app.
$access = $facebook->getAccessToken();
Make sure that you always request the Access Token (priority!) You will only ever recieve a signed request when you have been redirected from a facebook dialogue to your app. (i.e.) oAUTH dialogue. This method of the SDK will also save your Access Token to a session variable. You can call the getAccessToken() method on any subsequent app page where a PHP session is active EVEN WHEN no signed request has been issued.
Now that you have your valid access token for the logged in user, you can proceed with:
$user = $facebook->api('/me');
or, simpler still:
$user = $facebook->getUser();
I tend to reserve API calls for more complex requests such as posting to a users feed / friends feed.
So to recap:
-> check for $code
-> get signed request on first page after oAuth dialogue.
-> If browser cookies are disabled (likely in ie) don't forget to pass your session to the next page with the SID constant. If you don't, you will loose your stored access token (not good!).

Attempting to Log user in with facebook api, and returning email address in a php site

This is my code thus far:
<div id='fb-root'></div>
<script src='http://connect.facebook.net/en_US/all.js'></script>
<script>
FB.init({
appId:'xxxxxxxxxxxx', cookie:true,
status:true, xfbml:true , oauth:true, channelUrl:'http://www.federationofhumanity.com/facebookconnect/channel.html'
});</script><fb:login-button show-faces='true' width='200' max-rows='1' perms='user_birthday,user_online_presence,user_website,email'>Login using Facebook</fb:login-button><script>
FB.getLoginStatus(function(response) {
if (response.authResponse) {
document.getElementById('fb-root').innerHTML = '';
} else {
document.getElementById('fb-root').innerHTML = '';
}
});
if ($user)
</script>
(FYI, this code is included in php script via a readfile command.) As it is, I can show someone as "logged in", but I have nothing to differentiate them from a normal user on the website. My website is php based. I need to get their primary email address so the site can use it and provide the personalized experience they're coming to the site for. I need to somehow get their email address and turn it into a variable for the php to use. Help please?
After the user authenticates your application, Facebook can return them to a URL you set [add the paramater onlogin='window.location="https://graph.facebook.com/oauth/authorize?client_id=XXXXX&redirect_uri=http://www.yoursite.com/facebookscript; ?>&r="+window.location.href;']
This script can then pull their email address from Facebook using the PHP SDK now that you have authorization to use it.
// call up the php SDK
require './facebook/facebook.php';
// now connect to facebook with our secret information
$facebook = new Facebook(array(
'appId' => XXXXXXX,
'secret' => XXXXXXX,
'cookie' => true
));
// get the facebook user id
$fb_user = $facebook->getUser();
// try to get their email address
try {
$user_info = $facebook->api('/me'); // this is their profile basics
} catch (FacebookApiException $e) {
echo "something went wrong: ". $e; die;
}
// print email address
echo "your email address is: ". $user_info['email']
You can also grab the email out with the JavaScript SDK using the response.authResponse function you currently have left blank. But you still need a script to kick in to process it and register them [likely via ajax] -- I'd suggest letting the user confirm their email address as some people will want to switch accounts.

FB.login with PHP API

I've set up a Canvas Page which doe's a FB.login on click of a form submit button. During the following request it tries to access the users data via $facebook->api('/me') (last API version from Github). It works in Firefox and Chrome, but not in Safari and IE, where the API fails with "auth token required". Has anybody already had this problem or got an idea what could cause it?
BR Philipp
edit:
I call FB.login inside the click event of a form submit button:
$('.form-submit', this).click(function() {
FB.getLoginStatus(function(response) {
if (response.session) {
form.submit();
} else {
FB.login(function(response) {
if(response.session && (permissions == '' || response.perms)) {
form.submit();
}
else {
}
},{perms:permissions});
}
});
return false;
});
On server side in simply construct the php-api object and try to get user data:
$facebook = new Facebook(array(
'appId' => $appid,
'secret' => $appsecret,
'cookie' => TRUE,
));
if ($facebook) {
try {
$me = $api->api('/me');
}
catch (Exception $exc) {
// Failure in Safari and IE due to invalid auth token
}
}
The signed_request is passed inside a hidden form element.
I had the same problem and I've included a solution below.
I believe the reason this happens is because on a Javascript login attempt your server never receives any access tokens. The Javascript is only passing data between your browser and Facebook.com so your server has no idea what the authentication status is. Your server will only receive the new access tokens when the page is refreshed; this is where facebook hands over the access tokens.
Heres my solution.
Upon a successful login via FB.login you will receive the response object and inside it is an access_token. All you need to do is pass this access token to your script in some way. Here is an example:
// Hold the access token
var js_access_token = "";
// Connect to facebook
FB.login(function(response) {
if (response.session) {
if (response.perms) {
// user is logged in and granted some permissions.
// Save the access token
js_access_token = response.session.access_token;
// Do stuff on login
}
}
});
You then include the access token along with any requests. I've chosen an ajax example.
// Communication back to server.
$.ajax({
url: 'myurl.php',
data: {
js_access_token: js_access_token // Including the js_access_token
},
success: function(data) {
console.log(data);
}
});
Within your PHP you then need to have something which looks like this:
$facebook = new Facebook(array(
'appId' => $appid,
'secret' => $appsecret,
'cookie' => TRUE,
));
if ($facebook) {
// If we get the access token from javascript use it instead
if (isset($_REQUEST['js_access_token']) && $_REQUEST['js_access_token']) {
$facebook->setAccessToken($_REQUEST['js_access_token']);
}
try {
$me = $api->api('/me');
}
catch (Exception $exc) {
// Failure in Safari and IE due to invalid auth token
}
}
Hope this helps
I had a lot of troubles with the JS FB login stuff. I recommend using the simpler redirect login using oauth and the getLoginUrl function from php fb api.
So basically you do it from PHP, you check if you have your session, if not you use getLoginUrl and redirect to that page, your use will be then redirected to your app/site with a valid session (if he accepts).
Does this help ? I really lost HOURS trying to make the FB JS login work on any browser and I couldn't, I've switched since then to the simple redirect login method in all of my apps with complete success.
I liked Conor's answer as I had to pass my access token from the client side to server side as it was not working in Safari (cookie issues I presume). But this is an old question so a few things had to change. The vars are different now and as oliland pointed out we shouldn't be sending access tokens as GET params.
Anyway, here's what I ended up with in case it helps anyone
<a id="start-button" href="#">Start</a>
<form id="entry-form" action="nextpageurl" method="post">
<input type="hidden" name="access_token" />
</form>
<script>
$(document).ready(function() {
$('#start-button').click(function(e) {
e.preventDefault();
FB.login(function (response) {
if (response.authResponse) {
$('#entry-form input').val(response.authResponse.accessToken);
$('#entry-form').submit();
} else {
alert('Permissions required');
}
}, {});
});
});
</script>
and then in the PHP, pretty much same as Conor's answer, but getting the token from the $_POST var.

Categories