GTM OAuth 2.0 on iOS - retrieving user's email - ios

GTMOAuth 2.0 seems like an excellent tool for OAuth 2.0 verification on iOS. I am trying to retrieve the full name and email of a Google user by implementing GTMOAuth-2 in Xcode but am having a bit of trouble. Based on this answer: Retrieve User email using GTM OAuth2 for iOS, it should be as easy as calling auth.userEmail. However, the problem is that calling auth.userEmail in the following code segment always return null:
- (void)viewController:(GTMOAuth2ViewControllerTouch * )viewController
finishedWithAuth:(GTMOAuth2Authentication * )auth
error:(NSError * )error
{
NSLog(#"finished");
NSLog(#"auth access token: %#", auth.accessToken);
[self.navigationController popToViewController:self animated:NO];
if (error != nil) {
UIAlertView * alert = [[UIAlertView alloc] initWithTitle:#"Error Authorizing with Google"
message:[error localizedDescription]
delegate:nil
cancelButtonTitle:#"OK"
otherButtonTitles:nil];
[alert show];
} else {
UIAlertView * alert = [[UIAlertView alloc] initWithTitle:#"Success Authorizing with Google"
message:[error localizedDescription]
delegate:nil
cancelButtonTitle:#"OK"
otherButtonTitles:nil];
[alert show];
}
NSLog(#"email: %#",auth.userEmail);
}
The code runs successfully and retrieves an access token, but auth.userEmail is always null. Do I need to make a request to the Google email endpoint using GTMOAuth 2.0's Fetcher object, or otherwise send an additional HTTP GET request to retrieve the user's email using auth.accessToken?

I recently worked on Google OAuth2 for logging user in with gmail
by following tutsplus's tutorial and It gave me the desired results.I
would recommend you to follow this link. This provides methods to
login and logout and also email address of logged in user. Google
OAuth2
. And to get email address of logged in user, add this in scopes
https://www.googleapis.com/auth/userinfo.email. and code will look
like this
[_googleOAuth authorizeUserWithClienID:#"YOUR CLIENT ID"
andClientSecret:#"SECRET"
andParentView:self.view
andScopes:[NSArray arrayWithObjects:#"https://www.googleapis.com/auth/userinfo.profile",#"https://www.googleapis.com/auth/userinfo.email", nil]];
And for GTM OAuth 2.0, add this
scopehttps://www.googleapis.com/auth/userinfo.email .Hope this helps
you.

Related

Parse - Sign Up and Login at the same time

Using Parse (iOS framework), I am able to sign up and login successfully using two API.
When user log in, it will cache the user and so accessing "currentUser" will return appropriate object. But sign up API is not caching.
Is there any way that sign up itself will cache the user and avoid separate log in functionality?
It should automatically log you in as well. For example, if in your completion block in signUpInBackground, you have a segue to your main screen and in your main screen, it is supposed to show information related to the user, then it will because [PFUser currentUser] is set to the user that registered.
here is an example
[user signUpInBackgroundWithBlock:^(BOOL succeeded, NSError *error) {
if (error) {
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:[[error userInfo] objectForKey:#"error"] message:nil delegate:self cancelButtonTitle:nil otherButtonTitles:#"Ok", nil];
[alertView show];
// Bring the keyboard back up, because they'll probably need to change something.
[_usernameField becomeFirstResponder];
}
else{
// Success!
[self performSegueWithIdentifier:#"goToMain" sender:self];
}
}];

cannot post to facebook using facebook ios sdk

i am unable to post to Facebook using Facebook ios sdk. i am receiving the following error.
"This app does not have permission to do this. to change permissions to do this. To change permissions, try logging into the app again."
- (void) performPublishAction:(void (^)(void)) action {
// we defer request for permission to post to the moment of post, then we check for the permission
if ([FBSession.activeSession.permissions indexOfObject:#"publish_actions"] == NSNotFound) {
// if we don't already have the permission, then we request it now
[FBSession.activeSession requestNewPublishPermissions:#[#"publish_actions"]
defaultAudience:FBSessionDefaultAudienceFriends
completionHandler:^(FBSession *session, NSError *error) {
if (!error) {
action();
} else if (error.fberrorCategory != FBErrorCategoryUserCancelled){
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:#"Permission denied"
message:#"Unable to get permission to post"
delegate:nil
cancelButtonTitle:#"OK"
otherButtonTitles:nil];
[alertView show];
}
}];
} else {
action();
}
}
i am using Facebook ios sample from git-hub for testing.i can successfully post to Facebook if i use some old app create on Facebook.i have created the app as described by the Facebook docs.
read the facebook document v2.0 carefully, i do have similar problem.
If your app asks for more than public_profile, email and user_friends, then it will have to be reviewed by Facebook before it can be made available to the general public. Please see our documentation on reviews for more information.
You have to register your app to Facebook at https://developers.facebook.com. Make sure to enter your app's bundle id exactly as it is in Xcode.

Access salesforce sandbox using zkSForce

I have used zkSForce in my iOS application to log in to SalesForce. Now I need to access the same data in sandbox environment for the same application.
But when I am trying to log in I am getting the following error.
Error Domain=APIError Code=0 "The operation couldn’t be completed. (APIError error 0.)" UserInfo=0xad3ef20
{faultstring=INVALID_LOGIN: Invalid username, password, security token; or user locked out., faultcode=INVALID_LOGIN}
But when I am trying to connect to production environment I am able to log in successfully. Is there any specific set of instructions to follow to connect to Sandbox using zkSForce? Thanks in advance.
--EDIT--
I am using the following method to log in.
[SFAccountManager setLoginHost:#"test.salesforce.com"];
[SFAccountManager setClientId:CLIENTID];
[SFAccountManager setRedirectUri:REDIRECTURI];
[SFAccountManager setCurrentAccountIdentifier:USERNAME];
[SFAccountManager sharedInstance].coordinator.credentials.instanceUrl=[NSURL URLWithString:#"https://test.salesfoce.com"];
[[FDCServerSwitchboard switchboard] loginWithUsername:username password:passwordToken target:self selector:#selector(loginResult:error:)];
and the result is handled by the following method
- (void)loginResult:(ZKLoginResult *)result error:(NSError *)error{
if (result && !error){
[[SFAccountManager sharedInstance].coordinator.credentials setAccessToken:nil];
[SFAccountManager sharedInstance].coordinator.credentials.accessToken = result.sessionId;
}
else if (error){
UIAlertView *myAlertView = [[UIAlertView alloc] initWithTitle:#"Login failed" message:#"Error" delegate:nil cancelButtonTitle:#"OK" otherButtonTitles: nil];
[myAlertView show];
}
}
Login requests for Sandbox need to goto a different endpoint than the default one for production, so you need to call setLoginProtocolAndHost: on the client object before calling login, e.g.
ZKSforceClient *c = [[ZKSforceClient alloc] init];
[c setLoginProtocolAndHost:#"https://test.salesforce.com"];
[c login:self.username password:self.password];
...
I am not sure if this is the perfect solution but adding the following line worked for me.
[[FDCServerSwitchboard switchboard] setApiUrlFromOAuthInstanceUrl:LOGINHOSTURL];
where LOGINHOSTURL is you host URL.
Thanks #superfell for giving me the hint

can't login with facebook on iOS

I am trying to login to a facebook account without the admin and test user I have been testing with. This is using the Parse.com framework facebook login utility. I get the error:
NSLocalizedDescription=User is not a test user owned by the application
My code to authenticate with facebook is hitting this condition:
[PFFacebookUtils logInWithPermissions:nil block:^(PFUser *user, NSError *error) {
if (!user) {
NSLog(#"User doesn't exist");
NSLog(#"%#", error);
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:#"Error"
message:error.localizedDescription
delegate:nil
cancelButtonTitle:#"OK"
otherButtonTitles:nil];
[alertView show];
}
I have set my app to: "Live and Available to All Users" in the facebook developer app dashboard.
Why am I receiving this error and how do I allow my app to be logged in by any user with a facebook account?
The problem was that I was already logged in in the simulator with a non valid account.

gtm-oauth2 access to own server configuration

SHORT STORY
Using gtm-oauth2 for iOS and FOSOAuthServerBundle in Symfony2 to implement my own Oauth2 server I am not getting the callBack finishedSelector to be invoked.
This is where the "special" ViewController is created:
GTMOAuth2ViewControllerTouch * viewController;
viewController = [[GTMOAuth2ViewControllerTouch alloc] initWithAuthentication:myAuth
authorizationURL:authURL
keychainItemName:nil
delegate:self
finishedSelector:#selector(viewController:finishedWithAuth:error:)];
What are the reasons that might make finishedSelector, (the implemented method viewController:finishedWithAuth:error) not to be invoked?
The behavior I get is that the login page is properly rendered, but it acts as the starting point of the whole web application, rendering the rest of the pages once it is logged-in instead of returning the control to the finishedSelector and, finally, to the view controller that has to manage the continuation of the APP workflow.
LONG STORY
Using gtm-oauth2 and FOSOAuthServerBundle in Symfony2, I am experiencing problems trying to make the arquitecture to catch the login and load the authenticated session from my iOS APP.
I am following the instructions described in the gtm-oauth2 documentation, particularly the Signing in to non-Google Services part.
Doing what it is described there, I have this method for creating the auth object:
- (GTMOAuth2Authentication * ) authForMyAPP
{
//This URL is defined by the individual 3rd party APIs, be sure to read their documentation
NSString * url_string = #"http://myHost/oauth/v2/token";
NSURL * tokenURL = [NSURL URLWithString:url_string];
// We'll make up an arbitrary redirectURI. The controller will watch for
// the server to redirect the web view to this URI, but this URI will not be
// loaded, so it need not be for any actual web page. This needs to match the URI set as the
// redirect URI when configuring the app.
NSString * redirectURI = #"http://myHost/oauth/v2/falseCallBack";
GTMOAuth2Authentication * myAuth;
myAuth = [GTMOAuth2Authentication authenticationWithServiceProvider:#"MyAPP"
tokenURL:tokenURL
redirectURI:redirectURI
clientID:kMyClientID
clientSecret:kMyClientSecret
];
//[myAuth setTokenType:#"Bearer"];
return myAuth;
}
And then, this method creates the "special" viewController that should handle the render of the login page and returning the control when the login is performed:
- (void)signInToMyAPP()
{
GTMOAuth2Authentication *myAuth = [self authForMyAPP];
NSString* auth_string = #"http://127.0.0.1/~pgbonino/Symfony/web/app.php/oauth/v2/auth";
NSURL * authURL = [NSURL URLWithString:auth_string];
// Display the authentication view
// Creates the "special" viewController passing the `auth` object, the authorization URL and the finishedSelector
GTMOAuth2ViewControllerTouch * viewController;
viewController = [[GTMOAuth2ViewControllerTouch alloc] initWithAuthentication:myAuth
authorizationURL:authURL
keychainItemName:nil
delegate:self
finishedSelector:#selector(viewController:finishedWithAuth:error:)];
[self.navigationController pushViewController:viewController animated:YES];
}
Finally, I have the method used for that finishedSelector. It should be called once the login is properly performed and the authentication has succeeded (or an error has come). THAT IS WHAT I AM NOT GET DONE:
- (void)viewController:(GTMOAuth2ViewControllerTouch *)viewController
finishedWithAuth:(GTMOAuth2Authentication *)myAuth
error:(NSError *)error
{
if (error != nil)
{
// Authentication failed
UIAlertView *alertView = [ [UIAlertView alloc] initWithTitle:#"Authorization Failed"
message:[error localizedDescription]
delegate:self
cancelButtonTitle:#"Dismiss"
otherButtonTitles:nil];
[alertView show];
}
else
{
// Authentication succeeded
// Assign the access token to the instance property for later use
//self.accessToken = myAuth.accessToken;
[myAuth setShouldAuthorizeAllRequests:YES];
[[Singleton sharedSingleton] setAuth:myAuth];
// Display the access token to the user
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:#"Authorization Succeeded"
message:[NSString stringWithFormat:#"Access Token: %#", myAuth.accessToken]
delegate:self
cancelButtonTitle:#"Dismiss"
otherButtonTitles:nil];
[alertView show];
}
}
This all is supposed to render my login page in a web view and catch the successful login to call the viewController:finishedWithAuth:error and save the session in some shared object.
Nevertheless, the behavior I am getting is that I get rendered the login in the web view, I correctly login and, instead oF the delegated selector gets invoked, it just normally logs in the application and the next page is loaded in the web view, as if it was in a normal browser. So the callback is not performed.
Why am I not getting the selector to be called? Any idea?
IMPORTANT NOTE: the Oauth2 server works perfectly: if I call the token URL and the callBack url from Safari, everything works well. Tokens and auths codes are correctly saved in database.
Forget it.
It was just me.
OAuth2 won't work with Symfony2 and FOSUserBundle while this parameter is set to true in config.yml:
always_use_default_target_path: false

Resources