I am using google+ sign in my app using the Google Plus SDK. When the user taps on the sign in button the user gets redirected to safari. (Standard Process).
However Apple seems to have changed some rules for this. My App was rejected due to this, stating the following
The app launches mobile Safari to complete signing into Google+ before returning to the app. However, the use should not have to exit the app to use it.
To resolve the issue, it would be appropriate to revise your app to allow the user to log through the app, to create another authentication method for your app, or to remove this requirement from using your app
Is someone else facing the same issue and has a solution? A work around could be using a UIWebView and use the OAuth Access Token. However this fails to provide me a Single Sign On feature. Also does anyone know how to share an image using the Access Token (Without SDK features). I have found the GTMOAuth2ViewControllerTouch file in the sdk but still no luck with it. Can anyone help me with this class?
As of version 48, Chrome for iOS uses WKWebView, which is the same view used in Safari.
UIWebView APIs are still supported in the upcoming iOS 13 release as well as macOS Catalina but are still going away in future releases. Sometime in the future, iOS apps may be blocked from release to the App Store when Apple decides to enforce blocking apps that use UIWebView.
WebView can be defined as an object which can display the interactive web content and load HTML strings within the iOS application for an in-app browser. It is an instance of the WKWebView class, which inherits the UIView class.
On your iPhone or iPad, open the Safari app. Go to www.google.com. Tap your profile image or Sign in. Follow the sign-in steps.
Google has released a new iOS SDK that does supports WebView Sign In, among several other updates and features. (Thanks to John Hjelmstad and Co for working on this)
I recommend strongly against using the outdated GTMAuth2Controller. If you really want this feature please add your voice to the official Google thread. The more voices we add there the higher the chance that Google will introduce this feature. Currently Apple are rejecting all Apps that force the user to flip flop from Safari to your App for Google+ Sign In. Even though Apple are aware that this is how Googles SDK does this (Nevermind the fact that Facebook does the same but won't get your app rejected).
Its petty and lame but unfortunately all we can do is appeal to Google to add support for this.
Here's what Google had to say about this issue (I also protested the use of their outdated controller)
Hi all -- at Google, we aim to make our services available to as many users and developers as possible. We have heard a very small number of reports of problems of this type, but those app developers appear to have eventually gotten approval to launch by working through Apple’s standard process.
Meantime, we're continuing to work on improved mechanisms for login. I do agree with Daniel that direct use of GTMOauth2ViewControllerTouch, or the equivalent UIWebView trickery, is not recommended. Oct 16, 2014
I tried merging sample apps for Gmail API and GooglePlus to use UIWebView login instead of Safari and it seems to work:
my viewcontroller .h file I added 2 buttons to login and retrieve data, textview to display retrieved data, connected them in the builder. ALSO added interface and property for GTMOAuth2Authentication:
#import <UIKit/UIKit.h>
#import <GoogleOpenSource/GoogleOpenSource.h>
#import <GooglePlus/GooglePlus.h>
@interface MyViewController : UIViewController{
IBOutlet UIButton *loginBttn;
IBOutlet UIButton *retriveBttn;
IBOutlet UITextView *profileTextView;
GTMOAuth2Authentication *mAuth;
}
@property (retain, nonatomic) IBOutlet UIButton *loginBttn;
@property (retain, nonatomic) IBOutlet UIButton *retriveBttn;
@property (nonatomic, retain) IBOutlet UITextView *profileTextView;
@property (nonatomic, retain) GTMOAuth2Authentication *auth;
-(IBAction)dologin;
-(IBAction)doretrive;
@end
my viewcontroller .m file:
#import "MyViewController.h"
#import "AppDelegate.h"
#import <GoogleOpenSource/GoogleOpenSource.h>
#import <GooglePlus/GooglePlus.h>
static NSString *const kKeychainItemName = @"Google OAuth2 For gglplustest";
static NSString *const kClientID = @"your client id";
static NSString *const kClientSecret = @"your client secret";
@interface MyViewController ()
@end
@implementation MyViewController
@synthesize loginBttn,retriveBttn;
@synthesize auth = mAuth;
@synthesize profileTextView;
-(IBAction)doretrive{
GTLServicePlus* plusService = [[[GTLServicePlus alloc] init] autorelease];
plusService.retryEnabled = YES;
[plusService setAuthorizer:self.auth];//!!!here use our authentication object!!!
GTLQueryPlus *query = [GTLQueryPlus queryForPeopleGetWithUserId:@"me"];
[plusService executeQuery:query
completionHandler:^(GTLServiceTicket *ticket,
GTLPlusPerson *person,
NSError *error) {
if (error) {
GTMLoggerError(@"Error: %@", error);
} else {
// Retrieve the display name and "about me" text
[person retain];
NSString *description = [NSString stringWithFormat:
@"%@\n%@\n%@", person.displayName,
person.aboutMe,person.emails];
[profileTextView setText:description];
}
}];
}
- (void)auth:(GTMOAuth2Authentication *)auth finishedRefreshWithFetcher:(GTMHTTPFetcher *)fetcher error:(NSError *)error {
[self viewController:nil finishedWithAuth:auth error:error];
if (error != nil) {
// Refresh failed
NSLog(@"Authentication Error %@", error.localizedDescription);
self.auth=nil;
return;
}
self.auth=auth;
}
- (void)viewController:(GTMOAuth2ViewControllerTouch *)viewController finishedWithAuth:(GTMOAuth2Authentication *)auth error:(NSError *)error
{
if (error != nil) {
// Authentication failed
NSLog(@"Authentication Error %@", error.localizedDescription);
self.auth=nil;
return;
}
self.auth=auth;
[viewController release];//no ARC
}
-(IBAction)dologin{
NSString *scope = kGTLAuthScopePlusLogin;//Google+ scope
GTMOAuth2Authentication * auth = [GTMOAuth2ViewControllerTouch
authForGoogleFromKeychainForName:kKeychainItemName
clientID:kClientID
clientSecret:kClientSecret];
if ([auth refreshToken] == nil) {
GTMOAuth2ViewControllerTouch *authController;
authController = [[GTMOAuth2ViewControllerTouch alloc]
initWithScope:scope
clientID:kClientID
clientSecret:kClientSecret
keychainItemName:kKeychainItemName
delegate:self
finishedSelector:@selector(viewController:finishedWithAuth:error:)];
[[self navigationController] pushViewController:authController animated:YES];
}else{
[auth beginTokenFetchWithDelegate:self didFinishSelector:@selector(auth:finishedRefreshWithFetcher:error:)];
}
}
- (void)viewDidLoad {
[super viewDidLoad];
}
So now, when view is loaded it does not try to login.
Then on a view when I touch loginBttn that will run dologin method (from GmailMail sample) where I setup the scope to GooglePlus: 1st it will check if there is saved info in keychain, if it is, it will proceed without asking you to login. If not, it will do it as for Gmail login in UIWebView directly inside my app.
here how it looks after login:
Then I can touch retriveBttn to run retrieve method (e.g. to get Name, About and emails) that uses GooglePlus sample HOWEVER I set Authorizer to the authenticator that I saved after successful login like that: [plusService setAuthorizer:self.auth];
here is the view before and after retrieve is complete:
Seems like it is doing what is is supposed to.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With