Как предотвратить дополнительный просмотр, отображающий код доступа при использовании Google OAuth 2.0

Я следил за http://googlemac.blogspot.com/2011/05/ios-and-mac-sign-in-controllers.html, чтобы пользователи могли использовать Google для входа в приложение для iPhone. После того, как я нажму кнопку "Разрешить доступ", я получу дополнительный экран, который говорит: "Скопируйте этот код, переключитесь на приложение и вставьте его туда: (код в текстовом поле).

Это то, что у меня есть:

- (IBAction)googleLoginTapped:(UIButton *)sender
{
    [self loginToGoogle];
}

- (void)loginToGoogle 
{

    // For Google APIs, the scope strings are available
    // in the service constant header files.
    NSString *scope [email protected]"https://www.googleapis.com/auth/userinfo.profile";

    // Typically, applications will hardcode the client ID and client secret
    // strings into the source code; they should not be user-editable or visible.

    // But for this sample code, they are editable.
    NSString *clientID = @"my clientID";
    NSString *clientSecret = @"my clientSecret";


    // Display the autentication view.
    SEL finishedSel = @selector(viewController:finishedWithAuth:error:);

    GTMOAuth2ViewControllerTouch *viewController;

    viewController = [GTMOAuth2ViewControllerTouch controllerWithScope:scope
                                                              clientID:clientID
                                                          clientSecret:clientSecret
                                                      keychainItemName:nil
                                                              delegate:self
                                                      finishedSelector:finishedSel];

    // For this sample, we'll force English as the display language.
    NSDictionary *params = [NSDictionary dictionaryWithObject:@"en"
                                                       forKey:@"hl"];

    viewController.signIn.additionalAuthorizationParameters = params;

    // Optional: display some html briefly before the sign-in page loads
    NSString *html = @"<html><body bgcolor=silver><div align=center>Loading sign-in page...</div></body></html>";
    viewController.initialHTMLString = html;

    viewController.signIn.shouldFetchGoogleUserProfile = YES;

    [self presentModalViewController:viewController animated:YES];
}

- (void)viewController:(GTMOAuth2ViewControllerTouch *)viewController finishedWithAuth:(GTMOAuth2Authentication *)auth error:(NSError *)error
{
    if (error != nil) 
    {
        // Authentication failed (perhaps the user denied 

пожалуйста, см. эту ссылку. https://developers.google.com/accounts/docs/OAuth2InstalledApp

Ответ 1

Я пробовал этот подход и отлично работал, поместив его в свой метод webViewDidFinishLoad:

if ([webView.request.URL.absoluteString rangeOfString:@"https://accounts.google.com/o/oauth2/approval?"].location != NSNotFound) {
    webView.hidden=YES;
}

Ответ 2

Я нашел ответ. Первоначально я использовал идентификатор клиента для установленного приложения. Это не дало возможности настроить URI Redirect. Он дал URI по умолчанию для перенаправления urn: ietf: wg: oauth: 2.0: oob http://localhost. когда я отправил запрос на аутентификацию с помощью этого кода:

viewController = [GTMOAuth2ViewControllerTouch controllerWithScope:scope
                                                              clientID:clientID
                                                          clientSecret:clientSecret
                                                      keychainItemName:nil
                                                              delegate:self
                                                      finishedSelector:finishedSel];

Он вернул код успеха, который затем используется для авторизации собственных приложений. Пожалуйста, refere здесь для получения более подробной информации о возвращенных кодах или жетонах.

Чтобы исправить мою проблему, я пошел дальше и использовал идентификатор клиента для веб-приложения. Это позволило мне явно установить URI Redirect, а также разрешить мне вместо атрибута response_type вместо токена:

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**

Поэтому, когда я аутентифицирован и redirect_uri возвращается с сервера, он поставляется с "access_tocken", добавленным в виде строки запроса, как это:

https://www.example.com/back?access_token=returned_access_tocken

Теперь вы можете использовать код регулярного выражения:

-(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;
        }
    }
}

чтобы вырвать код доступа и использовать его для вашего запроса авторизации здесь:

"https://www.googleapis.com/oauth2/v1/userinfo?oauth_token=put_your_accesstoken_here" to send a request for authorization

Затем вы можете просто отправить свой запрос и вернуть в этом случае информацию профиля пользователя в формате JSON. Вы можете обратиться к этому вопросу и ответить для использования графического графика Facebook для входа в систему. Затем просто измените код для работы с новым Google OAuth 2.0 с помощью предложений и запросов, которые я включил здесь. Просто подскажите, как ускорить работу при преобразовании кода для Facebook, создайте новый метод init, например:

- (id)initWithDelegate:(id<GoogleLoginDialogDelegate>)delegate;

- (id)initWithDelegate:(id<GoogleLoginDialogDelegate>)delegate 
{
    if ((self = [super initWithNibName:@"GoogleLoginDialog" bundle:[NSBundle mainBundle]])) {
        self.delegate = delegate;
    }
    return self;    
}

Чтобы вы могли легко работать с методами делегата из своего диалогового окна входа в Google. Если вы внимательно следите за примером Facebook, у вас должен быть логин Google с OAuth, который отлично работает!

Ответ 3

Оказывается, это довольно просто. В обратном вызове login просто отпустите и удалите viewController из родительского контроллера представления.

- (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 ...
    }
}

Ответ 4

Я исправил это, вставив контроллер представления внутри UINavigationController. Не знаю, почему это сделал трюк, но так оно и было.

Итак, вместо

[self presentModalViewController:viewController animated:YES];

... использовать

UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:viewController];
[self presentModalViewController:navigationController animated:YES];

Ответ 5

При использовании gtm-oauth2 для входа в службы Google убедитесь, что Консоль API Google показывает в разделе API Access, что Идентификатор клиента выдается для приложения . Это описано в документации gtm-oauth2 .

Ответ 6

при создании идентификатора клиента, выберите веб-приложение вместо установленного приложения, это решит вашу проблему.

счастливое кодирование:)

Ответ 7

Я пробовал этот трюк, и он получает работу...

замените webview shouldStartLoadWithRequest следующим образом: GTMOAuth2ViewControllerTouch.h. Он не покажет страницу кода аутентификации.

*- (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;
}*

в этом я добавляю собственное собственное представление (redirectView) на эту страницу аутентификации, проверяя этот URL-адрес утверждения https://accounts.google.com/o/oauth2/approval?

и вы также должны добавить activityView в xib из GTMOAuth2ViewControllerTouch, чтобы показать загрузчика при перенаправлении обратно в приложение.

Ответ 8

После того, как по крайней мере 20 часов настройки, я, наконец, получил это. Я также импортировал мой быстрый файл в файл GTMOAuth2ViewControllerTouch.m. Не уверен, что это повлияло на это, но я добавил:

    #import "myBundleId-Swift.h"

Затем в файле viewController.swift мне нужно было добавить последние 2 строки:

 // 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()
    }
}

Это избавило от копирования этого экрана кода.