iOS Facebook SDK: FBSDKGraphRequest not getting email, despite permission - ios

I am using FB SDK v4.4 (latest) and think I have avoided the gotchas in the other questions.
I am establishing a logIn:
FBSDKLoginManager *login = [[FBSDKLoginManager alloc] init];
[login logInWithReadPermissions:#[#"email"]
handler:^(FBSDKLoginManagerLoginResult *result, NSError *error) {
if (error) {
// Process error
} else {
[self facebookGetUserProfileWithCompletion:completion];
}
}];
I've specifically asked for "email" (an extended permission that requires app review).
My app has passed review, and the user gives permission for email when prompted. Adding a [result.grantedPermissions containsObject:#"email"] check in the handler returns TRUE.
Once the user's has responded to the UI, the code then gets the user profile from Graph API:
[[[FBSDKGraphRequest alloc] initWithGraphPath:#"me" parameters:#{#"fields" : #"id,email,first_name,last_name,link,locale"}]
startWithCompletionHandler:^(FBSDKGraphRequestConnection *connection, id result, NSError *error) {
if (!error) {
NSString *email = [result objectForKey:#"email"] ;
NSString *first_name = [result objectForKey:#"first_name"] ;
//etc...
}
At this point, I have just five parameters; I am missing email. Using Graph API Explorer, I get the full six. The user does have an email address registered with FB.
Why no email???!!!

I've pretty much resolved my issues. Here they are:
1) #cbroe had the most helpful suggestion of getting the token and using Graph API Explorer to debug. Lots of help there.
2) FB are shifting their DOB field to age_range in most cases. It seems that my existing app will still return DOB, but the new version will not without permission. No doc on this I could find, but if I go with age_range, I'm good.
3) There was a strange problem with my email address in my FB test account. That's fixed, and I am getting email again no problem. Again, the Graph API test was most helpful in resolving this. Thanks again #cbroe!

Your parameters should be just one string
#"fields:id,email,first_name,last_name,link,locale"

Related

Facebook profile link of some facebook user is declined in response using FBSDKLoginManager in iOS app

I'm using FBSDKLoginKit to login with Facebook. I'm trying to get email, name, public profile and user profile link. According to latest policy to get profile link, developer need to ask permission during login and should provide how the information are being used to Facebook for review. I did all those process.
I was able to get all those required parameters when login with my developer Facebook account using FBSDKLoginManager. But when I tried login with another user account, profile link was declined in response. The link was empty.
I've created a method as below to login and get those parameters.
- (void)loginFaceBook
{
FBSDKLoginManager *login = [[FBSDKLoginManager alloc] init];
login.loginBehavior = FBSDKLoginBehaviorSystemAccount;
// need permission
[login logInWithReadPermissions:#[#"public_profile", #"email", #"user_link"]
fromViewController:self
handler:^(FBSDKLoginManagerLoginResult *result, NSError *error)
{
if (error)
{
NSLog(#"Process error");
}
else if (result.isCancelled)
{
NSLog(#"Cancelled");
}
else
{
NSLog(#"Logged in");
if ([result.grantedPermissions containsObject:#"email"])
{
NSDictionary *params = #{#"fields" : #"id,name,link,email"};
[[[FBSDKGraphRequest alloc] initWithGraphPath:#"me" parameters:params]
startWithCompletionHandler:^(FBSDKGraphRequestConnection *connection, id responseData, NSError *error)
{
NSLog(#"%#",responseData);
if (!error)
{
NSString *fbEmail = [AQCommon validateTextBeforePack:[responseData objectForKey:kEmail]];
NSString *fblink = [AQCommon validateTextBeforePack:[responseData objectForKey:#"link"]];
NSString *fbname = [AQCommon validateTextBeforePack:[responseData objectForKey:#"name"]];
}
else
{
NSLog(#"Facebook login failed. Please try later."); }
}
}];
}
else
{
NSLog(#"Facebook login failed. Please try later."); }
}
}];
}
I got all the required parameters login with my Facebook developer account (where I've created my app), but user_link was declined for some other accounts. What could be the problem? Is it related to Facebook privacy policy? Or, user needs to change some settings in their profile?
Apart from the above problem, the profile link that I got of my developer account was opening from any Facebook account except some accounts. The error says either the link is expired or permission is not granted. The problem is very specific to Facebook user accounts. What could be the reasons and solutions?
Facebook provides sandboxed test users which can use be used for testing purposes.
Here you can check all about Facebook test users.
https://developers.facebook.com/docs/apps/test-users
It seems that facebook allow to see the profile only if the user is friend or friend of friend.

Facebook Login after declined Permission

Since the release of the new FBSDK I'm facing this problem.
Scenario:
1.User logs into my app via FBLogin
2.User declines one of my permissions
My app sets him back to first screen (I don't allow creating an account without providing info)
He tries logging in again
He realizes FBSDK saved his settings he cannot change.
How do I provide the user with the possibility to change it?
My app runs to the point, I am noticing a declined permission and I give my user a notification to change the setting.
But I am clueless what to do at this point.
Firstly, you must not make all permissions as mandatory from Facebook.
Although if needed be, then you can check for the permission granted or not using the following code
if ([[FBSDKAccessToken currentAccessToken] hasGranted:#"publish_actions"]) {
// TODO: publish content.
} else {
FBSDKLoginManager *loginManager = [[FBSDKLoginManager alloc] init];
[loginManager logInWithPublishPermissions:#[#"publish_actions"]
fromViewController:self
handler:^(FBSDKLoginManagerLoginResult *result, NSError *error) {
//TODO: process error or result.
}];
}
To check for Declined Permissions
FBSDKLoginManager *loginManager = [[FBSDKLoginManager alloc] init];
[loginManager logInWithPublishPermissions:#[#"publish_actions"]
fromViewController:self
handler:^(FBSDKLoginManagerLoginResult *result, NSError *error) {
if ([result.declinedPermissions containsObject:#”publish_actions”]) {
// TODO: do not request permissions again immediately. Consider providing a NUX
// describing why the app want this permission.
} else {
// ...
}
}];
Note : If the user declines permissions, you should not immediately ask for them again. Instead your app should continue functioning. You may consider providing a guide or user interface explaining the benefits of granting that permission but should only ask for it again if the user performs an action that needs it.
Ref :
https://developers.facebook.com/docs/facebook-login/ios/permissions
https://developers.facebook.com/docs/ios/errors

Facebook iOS SDK "Access your basic profile info AND list of Friends" remove Friends

Using the Facebook SDK for iOS and have the following basic login code:
FBSDKLoginManager *login = [[FBSDKLoginManager alloc] init];
login.loginBehavior=FBSDKLoginBehaviorSystemAccount;
[login logInWithReadPermissions: #[#"public_profile"] fromViewController:self
handler:^(FBSDKLoginManagerLoginResult *result, NSError *error) {
NSMutableDictionary* parameters = [NSMutableDictionary dictionary];
[parameters setValue:#"id,name" forKey:#"fields"];
[[[FBSDKGraphRequest alloc] initWithGraphPath:#"me" parameters:parameters]
startWithCompletionHandler:^(FBSDKGraphRequestConnection *connection,
id result, NSError *error) {
NSLog(#"%#", result);
}];
}];
I ONLY want the basic profile information hence the call to public_profile
However, when I make the call, I get the following: "MyApp" would like to access your basic profile info and list of friends."
I don't want to access list of friends. When I go to the "MyApp" on facebook I can see it correctly only has access to the basic profile information.
How can I modify the prompt so my user doesn't think I need any of their friend info?
Try creating a new App, the friend list was included in older App versions without the need to add user_friends to your scope. Should not even be possible anymore because that was before v2.0, but you never know. Could be a bug. If it does not work in a new App and you are really not using the user_friends scope, you should file a bug: https://developers.facebook.com/bugs/

Getting basic facebook profile information ios

I have logged in on my iOS app that I am building using the easier method of FBSDKLoginButton.
Since all I want is the users name and a link to their facebook I know I can find this under [FBSDKProfile currentprofile].
My question really is how do I use this?
I am trying all sorts of combinations but something akin to the below is an example of what I'm doing.
[FBSDKProfile enableUpdatesOnAccessTokenChange:YES];
NSString *name = [[NSString alloc]init];
name = [[FBSDKProfile currentProfile]firstName];
I figure since my app now has access which I quickly tested through an if on the [FBSDKAccessToken currentAccessToken] so I believe I am primed. My app delegate is all setup also. So shouldn't my above code just work? I mean, I assume currentProfile is set if a user is logged in? Maybe? Arghhh!!!
Thanks guys
Try this code :
FBRequestHandler completionBlock = ^(FBRequestConnection *connection, NSDictionary<FBGraphUser> *user, NSError *error) {
NSLog(#"USER DICTIONARY : %#", user);
};
[[FBRequest requestForMe] startWithCompletionHandler:completionBlock];
you can then get the user details from the user dictionary.
I sorted it guys. Essentially the FBSDKLoginButton logs you in but offers no permissions. Simply ask for them as so;
loginButton.readPermissions = #[#"email", #"public_profile"];
Then the normal code I tried in my above comment will work. My mistake here is I assumed a simple login would at least give me the public profile. It doesn't, you have to ask.

How to “rerequest” email permission using Facebook iOS SDK 4.x?

I am integrating FacebookSDK 4.x integration with custom UI and using following method to log-in and also getting email permission from user.
FBSDKLoginManager *login = [[FBSDKLoginManager alloc] init];
[login logInWithReadPermissions:#[#"email"] handler:^(FBSDKLoginManagerLoginResult *result, NSError *error) {
if (error){
NSLog(#"%#",[error localizedDescription]);
}
else if (result.isCancelled){
NSLog(#"Cancled");
}
else
{
if ([result.grantedPermissions containsObject:#"email"])
{
NSLog(#"Granted all permission");
if ([FBSDKAccessToken currentAccessToken])
{
[[[FBSDKGraphRequest alloc] initWithGraphPath:#"me" parameters:nil] startWithCompletionHandler:^(FBSDKGraphRequestConnection *connection, id result, NSError *error)
{
if (!error)
{
NSLog(#"%#",result);
}
}];
}
}
else
{
NSLog(#"Not granted");
}
}
}];
This works great unless the user denies access to "email". I see in the FacebookSDK docs that I can re-request access to the user's email one time. According to the FB docs: as given in this link
If someone has declined a permission for your app, the login dialog won't let your app re-request the permission unless you pass auth_type=rerequest along with your request.
Enabling Re-authentication
During your chosen login flow we showed you how to use the Login
Dialog and OAuth to authenticate someone and request permissions from
them. To re-authenticate, you can use these same steps with additional
parameters to force it:
auth_type: this parameter specifies the requested authentication
features (as a comma-separated list). Valid options are:
https - checks for the presence of a secure Facebook session and asks for re-authentication if it is not present
reauthenticate - asks the person to re-authenticate unconditionally
auth_nonce: includes an app generated alphanumeric nonce which can be used to provide replay protection. See how to check an auth_nonce
for more.
Here is an example using the JavaScript SDK that triggers
re-authentication using an auth_type of reauthenticate:
FB.login(function(response) {
// Original FB.login code }, { auth_type: 'reauthenticate' })
Note that the body of the response contains the auth_type parameter
you specified, for example:
access_token=USER_ACCESS_TOKEN&expires=SECONDS_UNTIL_TOKEN_EXPIRES&auth_type=reauthenticate
How do I pass "auth_type=rerequest" to Facebook's servers via the iOS SDK? Is there a special method for that?
I resolved issue by recalling the method :
[login logInWithReadPermissions:#[#"email"] handler:^(FBSDKLoginManagerLoginResult *result, NSError *error)
I need to pass auth_type: 'rerequest' while requesting again and i get it in the documentation of this method i get the description :
Use this method when asking for read permissions. You should only ask
for permissions when they are needed and explain the value to the
user. You can inspect the result.declinedPermissions to also provide
more information to the user if they decline permissions.
If [FBSDKAccessToken currentAccessToken] is not nil, it will be
treated as a reauthorization for that user and will pass the
"rerequest" flag to the login dialog.
just the problem was i was calling logout Method of FbSDKLoginManager class. This will clear the token and it will takes it as the old permission not re-requested permission.
You actually don't need to pass or call auth_type:rerequest. This is already done by facebook. If you check FBSDKLoginManager, the code does it for you.
-(NSDictionary *)logInParametersWithPermissions:(NSSet *)permissions
{
if ([FBSDKAccessToken currentAccessToken])
{
loginParams[#"auth_type"] = #"rerequest";
}
}

Resources