2011-09-26 12 views
11

Ho seguito http://googlemac.blogspot.com/2011/05/ios-and-mac-sign-in-controllers.html per consentire agli utenti di utilizzare Google per accedere a un'app per iPhone. Dopo aver premuto il pulsante "Permetti l'accesso", ricevo una schermata aggiuntiva che dice: "Copia questo codice, passa alla tua applicazione e incollalo lì: (codice in una casella di testo)."Come impedire alla vista aggiuntiva di visualizzare un codice di accesso quando si utilizza Google OAuth 2.0

Questo è quello che ho:

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

si prega di vedere questo link è a buon https://developers.google.com/accounts/docs/OAuth2InstalledApp

+0

@kevlar ha la risposta corretta – 2cupsOfTech

risposta

0

Quando si utilizza GTM-OAuth2 per accedere ai servizi di Google, assicurati gli spettacoli di registrazione Google API Console progetto nella sezione Accesso API che viene emesso l'ID cliente per un'applicazione installata. Questo è descritto nel gtm-oauth2 documentation.

6

Ho trovato la risposta. Inizialmente stavo usando l'ID cliente per un'applicazione installata. Questo non ha dato la possibilità di configurare l'URI di Redirect. Ha fornito un URI di reindirizzamento predefinito di urn: ietf: wg: oauth: 2.0: oob http://localhost. Così, quando ho inviato una richiesta di autenticazione utilizzando questo codice:

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

Si ha restituito un codice di successo che viene poi utilizzato per autorizzare applicazioni native. Per ulteriori informazioni sui codici restituiti o sui token, reffer lo here.

Per risolvere il problema sono andato avanti e ho utilizzato un ID client per l'applicazione Web. Questo mi ha permesso di impostare in modo esplicito un reindirizzamento URI e anche mi ha permesso di impostare il response_type a gettone anziché il codice qui:

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

Così, quando io sono autenticati e redirect_uri è servita dal server è dotato di un " access_tocken" aggiunto come una stringa di query come questa:

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

Ora è possibile utilizzare un codice di espressione regolare:

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

per cogliere l'access_code e usarlo per y la nostra richiesta di autorizzazione qui:

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

allora si può solo inviare la richiesta e tornare in questo caso il profilo informazioni dell'utente in formato JSON. È possibile fare riferimento a questo question and answer per utilizzare l'API grafico di Facebook per accedere agli utenti. Quindi modifica il codice per utilizzare il nuovo Google OAuth 2.0 utilizzando i suggerimenti e gli URL di richiesta che ho incluso qui. Solo un suggerimento per velocizzare le cose per voi quando si converte il codice per Facebook, creare un nuovo metodo init in questo modo:

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

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

Così che si può facilmente lavorare con i metodi delegato della tua finestra di accesso di Google. Se segui attentamente l'esempio di Facebook, dovresti avere il login di Google con OAuth che funziona alla grande!

+0

Come usiamo questo mi mostra 400. Questo è un errore. Errore: invalid_request parametro richiesto mancante: response_type –

5

Si scopre che questo è piuttosto semplice. Nel callback di accesso, basta congedare e rimuovere viewController dal controller di visualizzazione genitore.

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

Questo non funziona per me-- lampeggio del "piacere copia questo codice," si verifica messaggio * prima * della chiamata a viewController: finishedWithAuth: errore: nel mio Astuccio. –

+0

Funziona per me su iPhone, iOS 9.2.1 (Swift). Non è perfetto però. L'utente può ancora visualizzare brevemente la schermata "Copia questo codice ...". Continuerò a cercare una soluzione ancora migliore. – marco

1

Ho fissato questo annidando controllore vista all'interno di un UINavigationController. Non ho idea del perché questo ha fatto il trucco, ma è successo.

Così, invece di

[self presentModalViewController:viewController animated:YES]; 

... usare

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

Questo non funziona per me. –

9

ho provato questo approccio, e funzionano bene, mettere questo nel vostro metodo di webViewDidFinishLoad:

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

Per chiarire: è necessario copiare e incollare le righe precedenti nel file GTMOAuth2ViewControllerTouch.m nella sezione OAuth2 della libreria client Objective C dell'API di Google. È un hack, ma ha funzionato per me. – Jono

+1

Grazie! Questa è l'unica soluzione che ha funzionato per me. – Jesse

+2

Ho fatto lo stesso, ma non riesco a nascondere la visualizzazione web. E 'ancora visto anche dopo averlo nascosto come da condizioni di cui sopra. Ho anche inserito il punto di interruzione per essere sicuro. – NSPratik

0

durante la creazione Client ID, Scegli l'applicazione web invece dell'applicazione installata, questo risolverà il tuo problema.

felice di codifica :)

0

Ho provato questo trucco e diventa lavoro ...

sostituire il WebView shouldStartLoadWithRequest con questo metodo seguito GTMOAuth2ViewControllerTouch.h. Non mostrerà la pagina di codice di autenticazione.

*- (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 questo Sto aggiungendo il mio visualizzazione personalizzata (redirectView) di questa pagina di autenticazione controllando questa approvazione url https://accounts.google.com/o/oauth2/approval?

e si dovrebbe anche aggiungere activityView nel XI ter del GTMOAuth2ViewControllerTouch per mostrare il caricatore durante il reindirizzamento indietro all'applicazione.

0

Dopo almeno 20 ore di configurazione, finalmente sono riuscito a farlo funzionare. Ho anche importato in precedenza il mio file swift nel mio file GTMOAuth2ViewControllerTouch.m. Non sono sicuro se che ha colpito, ma ho aggiunto:

#import "myBundleId-Swift.h" 

Poi, nel file viewController.swift avevo bisogno di aggiungere le ultime 2 righe:

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

, sbarazzandosi della copia questa schermata codice .