I followed http://googlemac.blogspot.com/2011/05/ios-and-mac-sign-in-controllers.html to allow users to use Google to login to an iPhone app. After I tap \"Allow access\" bu
It turns out this is pretty straightforward. In the login callback, simply dismiss and remove viewController
from the parent view controller.
- (void)viewController:(UIViewController *)viewController
finishedWithAuth:(GTMOAuth2Authentication *)auth
error:(NSError *)error
{
if (error == nil) {
// Get rid of the login view.
// self.parentViewController was saved somewhere else and is the parent
// view controller of the view controller that shows the google login view.
[self.parentViewController dismissViewControllerAnimated:NO completion:nil];
[viewController removeFromParentViewController];
// Tell the delegate that the user successfully logged in ...
} else {
// Error handling code ...
}
}
I tried this trick and it gets work...
replace the webview shouldStartLoadWithRequest with this below method in GTMOAuth2ViewControllerTouch.h. It will not show the authentication code page.
*- (BOOL)webView:(UIWebView *)webView
shouldStartLoadWithRequest:(NSURLRequest *)request
navigationType:(UIWebViewNavigationType)navigationType {
if (!hasDoneFinalRedirect_)
{
hasDoneFinalRedirect_ = [signIn_ requestRedirectedToRequest:request];
if ([request.URL.absoluteString rangeOfString:@"https://accounts.google.com/o/oauth2/approval?"].location != NSNotFound)
{
self.redirectView.frame=[UIScreen mainScreen].bounds;
//webView.frame=[UIScreen mainScreen].bounds;
[self.activityView startAnimating];
[webView addSubview:self.redirectView];
return YES;
}
else if(hasDoneFinalRedirect_) {
// signIn has told the view to close
return NO;
}
}
return YES;
}*
in this I am adding my own custom view (redirectView) to this authentication page by checking this approval url https://accounts.google.com/o/oauth2/approval?
and You should also add activityView in xib of GTMOAuth2ViewControllerTouch to show the loader while redirecting back to the application.
I tried this approach, and work fine, put this in your webViewDidFinishLoad method :
if ([webView.request.URL.absoluteString rangeOfString:@"https://accounts.google.com/o/oauth2/approval?"].location != NSNotFound) {
webView.hidden=YES;
}
while creating Client ID , Choose web Application instead of installed application , this will solve your problem .
happy coding :)
After at least 20 hours of configuring things, I finally got this running. I also previously imported my swift file into my GTMOAuth2ViewControllerTouch.m file. Not sure if that impacted it but I added:
#import "myBundleId-Swift.h"
Then, in the viewController.swift file I needed to add the final 2 lines:
// Handle completion of the authorization process, and updates the Drive service
// with the new credentials.
func viewController(viewController: GTMOAuth2ViewControllerTouch , finishedWithAuth authResult: GTMOAuth2Authentication, error:NSError? ) {
if let error = error
{
self.showAlert("Authentication Error", message:error.localizedDescription)
self.driveService.authorizer = nil
} else {
print("Authentication success")
self.driveService.authorizer = authResult
//This where we need to get rid of the copy the code screen:
self.parentViewController?.dismissViewControllerAnimated(false, completion:nil)
viewController.removeFromParentViewController()
}
}
That got rid of the copy this code screen.
I have found the answer. Initially I was using the Client ID for an installed application. This did not give the option to set up the Redirect URI. It gave a default Redirect URI of urn:ietf:wg:oauth:2.0:oob http://localhost. So when I sent a request for authentication using this code:
viewController = [GTMOAuth2ViewControllerTouch controllerWithScope:scope
clientID:clientID
clientSecret:clientSecret
keychainItemName:nil
delegate:self
finishedSelector:finishedSel];
It returned an success code that is then used to authorize native applications. Please reffer here for more on returned codes or tokens.
To fix my issue I went ahead and used a Client ID for web application. This allowed me to explicitly set a Redirect URI and also allowed me to set the response_type to token instead of code here:
https://accounts.google.com/o/oauth2/auth?
client_id=21302922996.apps.googleusercontent.com&
redirect_uri=https://www.example.com/back&
scope=https://www.google.com/m8/feeds/&
response_type=**token**
So when I am authenticated and the redirect_uri is served back from the server it comes with an "access_tocken" appended as a query string like this:
https://www.example.com/back?access_token=returned_access_tocken
Now you can use a regular expression code:
-(void)checkForAccessToken:(NSString *)urlString {
NSError *error;
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:@"access_token=(.*)&" options:0 error:&error];
if (regex != nil)
{
NSTextCheckingResult *firstMatch = [regex firstMatchInString:urlString options:0 range:NSMakeRange(0, [urlString length])];
if (firstMatch)
{
NSRange accessTokenRange = [firstMatch rangeAtIndex:1];
NSString *accessToken = [urlString substringWithRange:accessTokenRange];
accessToken = [accessToken stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
[_delegate accessTokenFoundGoogle:accessToken];
accessTokenFound = YES;
}
}
}
to pluck the access_code and use it for your authorization request here:
"https://www.googleapis.com/oauth2/v1/userinfo?oauth_token=put_your_accesstoken_here" to send a request for authorization
Then you can just send your request and get back in this case the user's profile info in JSON format. You can refer to this question and answer for using Facebook's graph api to login users. Then just modify the code to work with the new Google OAuth 2.0 using the suggestions and request urls I have included here. Just a suggestion to speed things for you when converting the code for Facebook, create a new init method like this:
- (id)initWithDelegate:(id<GoogleLoginDialogDelegate>)delegate;
- (id)initWithDelegate:(id<GoogleLoginDialogDelegate>)delegate
{
if ((self = [super initWithNibName:@"GoogleLoginDialog" bundle:[NSBundle mainBundle]])) {
self.delegate = delegate;
}
return self;
}
So that you can easly work with the delegate methods from your Google login dialog. If you follow the Facebook example carefully, you should have Google login with OAuth working great!