I use Facebook login with my app. (Facebook iOS SDK version 3.11.1)
I ask for "email" permission:
NSArray *permissions = [NSArray arrayWithObjects: #"basic_info", #"email", nil];
Most of the time, I do get the user's email like that:
NSString *email = [user objectForKey:#"email"];
//user is (NSDictionary<FBGraphUser> *)
Sometimes I just don't. (I can see that the NSDictionary is not including email).
I am using this fix so the app won't terminate when i use email later and its nil:
NSString *email = [user objectForKey:#"email"] ? [user objectForKey:#"email"] : #"NO_EMAIL";
But i need the real mail, so i have to come up with a new solution.
I haven't noticed something special with the problematic users.
Any ideas what can be the problem?
It appears that its a well known problem... For many reasons, not everyone on Facebook have Email address registered.
But as i said, my problem is that i need a real mail.
So the simplest solution is to use the user's Facebook Email : user_name#facebook.com
NSString *email = [user objectForKey:#"email"] ? [user objectForKey:#"email"] : [NSString stringWithFormat:#"%##facebook.com", user.username];
some links ref to that you can't sent HTML emails to the Facebook mail, only plain text!
Here is how i have done it and it always works great for me in every situation:
(I suppose that you have added email permission in your code)
Step 1
Open Facebook Framework folder in Xcode and find the FBGraphUser.h class
As you see, you have there all the properties that you use from Facebook Framework, to take the user details, so add an other property there (copy and paste the code below):
Step 2
#property (retain, nonatomic) id<FBGraphUser> email;
And you are good to go!
You could check for a couple of things:
Make sure you are requesting email scope permission in the login request dialog:
https://www.facebook.com/dialog/oauth?client_id=APP&redirect_uri=REDIRECT&state=UNIQUE&scope=email
Check if the access token you got actually has email permission granted with the Access Token Debugger.
All facebook accounts which are verified through Phone Number instead of email will get NULL for [user objectForKey:#"email"]
Facebook won't return the email address if it's not verified.
https://developers.facebook.com/docs/graph-api/reference/v2.2/user
This person's primary email address listed on their profile. This field will not be returned if no valid email address is available.
Related
I'm using the the PFLogInViewController of the ParseUI framework. I have two questions related to emails with regards to Facebook Login within the framework:
1) When signing up via Facebook, I see that the email field of my new user is 'undefined.' How can I obtain the user's email address?
2) If I am able to obtain the email address, does parse's application setting of 'emailVerified' still send a verification email to the user upon Facebook signup? If not, how can this be done?
Thanks.
In order to read the user's email address you'll need to add email to your array of Facebook permissions you're requesting. Look at the Parse tutorial on this https://www.parse.com/tutorials/login-and-signup-views#properties
In your case, you'll want to add #"email" like this:
[logInViewController setFacebookPermissions:[NSArray arrayWithObjects:#"friends_about_me", #"email", nil]];
Then when you are requesting the user information from Facebook, you will be able to access the user's email address:
FBRequest *request = [FBRequest requestForMe];
[request startWithCompletionHandler:^(FBRequestConnection *connection, id result, NSError *error) {
if (!error) {
// Now you can access user's email
NSString *email = result[#"email"];
if (email) {
// Save it to your email field in Parse
}
}
}];
Regarding part 2 of your question, I'm not as familiar with the email validation functionality that Parse supports, but looking at this (admittedly old) response https://www.parse.com/questions/email-verification-emails-going-out-to-facebook-users it appears that Parse will validate email addresses even when the user logs in with Facebook.
I'm new to Apigee and can't seem to wrap my head around it. I am familiar with implementing an iOS app that talks to a database via a webservice call. The call would involve passing back and forth JSON or variables though POST, GET, etc.
The user flow I envision is a lot like Facebook long term token storage. Here are the steps:
Type username and password to login.
The app will remember the access_token in the keychain.
The access_token will be used with any future requests such as updating profile. This way the user doesn't have re-login every time he/she is using the app.
Log out will clear all the token.
If the token is invalid or expired, the app will take the user back to login.
I've taken multiple routes and ended up getting stuck on all of them when it comes to Apigee.
ROUTE 1
I made a call to logInUser and receive access_token in return.
[self.apigeeDataClient logInUser:username password:password];
All this is good until I want to update user's email address using the code below.
NSMutableDictionary *requestDict = [NSMutableDictionary dictionary];
[requestDict setObject:email forKey:kDataEmail];
NSString *url = [NSString stringWithFormat:#"%#/%#/%#/users/%#?access_token=%#", BASE_URL, UG_ORG_NAME, APP_NAME, [userData objectForKey:kDataUUID], self.accessToken];
NSString *op = #"PUT";
NSError *error;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:[NSDictionary dictionaryWithDictionary:requestDict]
options:0
error:&error];
[self.apigeeDataClient apiRequest:url operation:op data:[NSString stringWithUTF8String:[jsonData bytes]]];
It seems that every other time it's giving me "No content to map to Object due to end of input" error. I checked out this thread but have no luck. I made sure the JSON object is not null. I tried changing the operation from PUT to POST and GET. None of which update the email address in the database.
ROUTE 2
Instead of using apiRequest, I switched to updateEntity.
NSMutableDictionary *requestDict = [NSMutableDictionary dictionary];
[requestDict setObject:email forKey:kDataEmail];
[requestDict setObject:kDataUsers forKey:kDataType];
[requestDict setObject:self.accessToken forKey:kDataAccessToken];
NSString *entityID = [userData objectForKey:kDataUUID];
[self.apigeeDataClient updateEntity:entityID entity:requestDict];
It looks promising except I started getting "Subject does not have permission" like the issue described in this thread. I tried calling assignPermissions like mentioned in Apigee document but that didn't solve the problem. I even provide access_token with the call, even though I shouldn't have to.
In the attempt to avoid calling login also tried calling storeOAuth2TokensInKeychain and retrieveStoredOAuth2TokensFromKeychain mentioned here. That didn't work either.
The only thing way to resolve this error is by calling logInUser before making a call to updateEntity. This means the user will have to login every time he/she wants to use the app. I know I can store username/password in the keychain. But before I do that I'm wondering if there's better solution out there.
I know it's a long post. So thank you for reading this far. Any pointers are greatly appreciated.
Is there a way to get the details/credentials (email, password, name, etc.) of the logged in user using salesforce SDK or even third party libraries?. After allot of googling and searching, i found this link but doesn't work on me:
Query for username in Salesforce iOS SDK
Finally Fetched the email/username and the user iD. I didn't notice the comment below. And yes password cannot be fetched thank you #john. You certainly cannot fetch the user's password nor should you be able to -- that's the entire point of OAuth.
#import "SFIdentityData.h"
#import "SFAuthenticationManager.h"
userName = [SFAuthenticationManager sharedManager].idCoordinator.idData.username;
NSString *userID = [SFAuthenticationManager sharedManager].idCoordinator.idData.userId;
NSLog(#"User name: %# and User ID: %#", userName, userID);
> Is there a way to get the (..) password
No.
SWIFT
YourTextLabel.text = SFAuthenticationManager.sharedManager().idCoordinator.idData.displayName
YourSecondTextLabel.text = SFAuthenticationManager.sharedManager().idCoordinator.idData.email
When I access to the Facebook Account using ACAccountStore to get an ACAccount object I noticed that for some profiles the ACAccount.username give me the Facebook email but for other profiles give me the nickname... How is possible that the same property contains different value ?
This drive me crazy...
Yes, it's weird for me too.
But I can get the email from properties field like below:
NSString *email = [[account valueForKey:#"properties"] objectForKey:#"ACUIDisplayUsername"];
I've spent hours on this and can't get it to work. Basically I just want a button in my app that will 'Like' itself on Facebook.
I've created the app on dev Facebook and have an associated App Page.
In my code I request these permissions:
_permissions = [NSArray arrayWithObjects:#"publish_stream", #"publish_actions", #"user_birthday", nil];
I can retrieve a profile picture fine, but when I try to 'Like' using this code:
NSMutableDictionary* params = [NSMutableDictionary dictionaryWithObjectsAndKeys:
_facebook.accessToken, #"access_token",
nil];
[_facebook requestWithGraphPath:#"329756493773381/og.likes" andParams:params andHttpMethod:#"POST" andDelegate:self];
I get this error response:
(facebookErrDomain error 10000.)" UserInfo=0x20090590 {error={
code = 200;
message = "(#200) Requires extended permission: publish_actions";
type = OAuthException;
}}
When logging in on the app, Facebook asks me for permission to see my birthday, and tell's me it will Post on my behalf but it seems to not get the publish_actions permission.
Is there something i'm missing that I need to do?
I see Temple Run has a Facebook Like button and offers bonus coins for pressing it. This is what I wish to achieve.
EDIT -------
I've changed my permissions to just #"publish_actions", #"user_birthday" and now the auth dialogue says
"This app may post on your behalf, including objects you liked and
more"
which seems to be the publish_actions permission, however I was still getting the error
message = "(#200) Requires extended permission: publish_actions";
I've changed this line:
[_facebook requestWithGraphPath:#"329756493773381/og.likes" andParams:params andHttpMethod:#"POST" andDelegate:selrf];
to this:
[_facebook requestWithGraphPath:#"329756493773381/og.likes" andDelegate:self];
and I do now get a response back, although it doesn't post a 'like'
This is the result response:
{
data = (
);
paging = {
next = "https://graph.facebook.com/329756493773381/og.likes?sdk=ios&sdk_version=2&access_token=BAAGeAp3ZBGwoBAPICjlgB5zK0YECyP8yElf8hJoMrx8Qs4vjeZAK5PlXFAVbGM1JyXHE0wZBvU0aBeCzCUTZBejQgoJ44CAIQsrG64TfrHdxjMqWD&format=json&offset=25&limit=25";
};
}
Any idea what to try next?
EDIT 2 ---------------
I'm making progress with this.
I've added the users id to the graph request like this
NSString *graphPath = [NSString stringWithFormat:#"%#/og.likes",facebookID];
and used these parameters
NSMutableDictionary* params = [NSMutableDictionary dictionaryWithObjectsAndKeys:
#"AAAGeAp3ZBGwoBABvKjsPZAoQQNG9cDPJI2v2TI8acyyPSNtm9ZBkfydHqVZAjSKWSbLuvFwxyxSrCts7kFZCnh7Y6f5PFNlWb6smF8XF33wlRZBgfLyhT1", #"access_token",
#"http://samples.ogp.me/329756493773381", #"object",
nil];
and now I get a like showing up on my timeline :-)
I was using the access-token supplied by the Facebook login, but it seems the one supplied by the graph object is different.
Now, the like that i'm seeing has this pattern:
Darren likes object on MyAPP
Is it even possible to have it as
Darren likes MyAPP
with it linking to the app Facebook page?
Thanks
Check if you have done the steps below:
https://developers.facebook.com/docs/opengraph/tutorial/
"Note: The user-prompt for this permission will be displayed in the first screen of the Enhanced Auth Dialog and cannot be revoked as part of the authentication flow." - link
Try this if you havent already:
Auth Dialog -> Configure how Facebook refers users to your app - > Add publish_actions permissions.
https://developers.facebook.com/docs/opengraph/authentication/
"To enable the new Auth Dialog, go to the App Dashboard, and enable the Enhanced Auth Dialog setting in the Advanced section of your app." -link
Hope this helps!
This seems to be the same problem I was having on this SO question:
Facebook iOS SDK 3.0, implement like action on a url?
But if you want to like you facebook page in the app, there is no way to do that in Objective C. Only with the javascript Like button which you can generate here:
https://developers.facebook.com/docs/reference/plugins/like/
The way Temple Run does it is to display the Like button in a web-view, so their like button is actually on their server, this is perhaps an ugly-hack but will work for liking a page.