9

Ich habe Probleme, einen einmaligen Autorisierungscode von Google zu erhalten. Ich versuche, den Autorisierungscode von einem Android-Client abzurufen, damit ich ihn an mein Rails-Backend (Web-Client) senden kann.Einmaliger Autorisierungscode von Google

In meinem Google Cloud Developer Console Ich habe eine Anwendung mit zwei Client-IDs:

  1. Client-ID für Web-Anwendung (für meine Schienen-Backend)

  2. ID Client für Android-Anwendung (für meine Android-Client). Der SHA1 verwendet wird, aus ~/.android/debug.keystore

die Web Application Client-ID ist 12345.apps.googleusercontent.com

Angenommen Angenommen, die Android-Client-ID 67890.apps.googleusercontent.com ist

Diese einige meines Code sind :

private final static String WEB_CLIENT_ID = "12345.apps.googleusercontent.com"; 
private final static String GOOGLE_CALENDAR_API_SCOPE = "audience:server:client_id:" + WEB_CLIENT_ID; 

private void getAndUseAuthToken(final String email) { 
     AsyncTask task = new AsyncTask<String, Void, String>() { 
      @Override 
      protected String doInBackground(String... emails) { 
       try { 
        return GoogleAuthUtil.getToken(AddExternalCalendarsActivity.this, emails[0], GOOGLE_CALENDAR_API_SCOPE); 
       } catch (UserRecoverableAuthException e) { 
        startActivityForResult(e.getIntent(), IntentConstants.REQUEST_GOOGLE_AUTHORIZATION); 
       } catch (IOException e) { 
        e.printStackTrace(); 
       } catch (GoogleAuthException e) { 
        e.printStackTrace(); 
       } catch (Exception e) { 
        e.printStackTrace(); 
       } 

       return null; 
      } 

      @Override 
      protected void onPostExecute(String authToken) { 
       if (authToken != null) { 
        saveTokenAndGetCalendars(email, authToken); 
       } 
      } 
     }; 

     String[] emails = new String[1]; 
     emails[0] = email; 
     task.execute(emails); 
    } 

Einige zusätzliche Hinweise

  • Ich bin die GoogleAuthException schlagen und „Unbekannt“ als Nachricht Detail

  • Ich bin nicht in der Lage, um zusätzliche Mitglieder in den Berechtigungen des Google Cloud Console für dieses Projekt empfangen - wenn eine Zugabe neues Mitglied erscheint ein Popup mit "Server Error". Hoppla! . Unsere schlecht ". Ich habe zweimal Feedback an Google gesendet

  • Ich beziehe mich auf diese documentation unter das Zitat Bekanntmachung...‚Fixed‘, sagen sie, dass ich brauche, um Publikum nicht setzt: Server : in meiner GOOGLE_CALENDAR_API_SCOPE Variable cLIENT_ID ich sowohl mit als auch ohne und immer noch die gleiche GoogleAuthException immer versucht habe

in dieser Situation kann der Android App aufrufe, den GoogleAuthUtil.getToken() -Methode auf. Namen von Google Konten auf dem Gerät, a nd mit einem Bereichsargumentwert von Zielgruppe: Server: client_id: 9414861317621.apps.googleusercontent.com. Das Präfix audience: server: client_id: ist fest, und der Rest der Bereichszeichenfolge ist die Client-ID der Webkomponente.

  • Wenn ich diesen Bereich zu verwenden, ich mit Google von Gerät authentifizieren kann.Die Dokumentation, die ich gelesen habe, legt jedoch nahe, dass ich die Server-Webclient-ID (die sich im selben Google-Konsolenprojekt wie die Android-Client-ID befindet) im Bereich verwenden muss, damit der Server die Google API im Namen von Google trifft der Benutzer, der es auf dem android-Client autorisiert:

    private final static String GOOGLE_CALENDAR_API_SCOPE = "oauth2:https://www.googleapis.com/auth/calendar";

UPDATE 1

ich ursprünglich in Antwort hinzugefügt: der Grund für mein erstes Problem - ich bin schlagen der GoogleAuthException und "Unknown" als Nachrichtendetail zu erhalten - war ein Fehler, den ich beim Hinzufügen der Android-Client-ID in der Cloud-Konsole gemacht habe. Die SHA1 war korrekt, aber ich habe den Paketnamen nicht korrekt eingegeben. Ich habe com.company.app verwendet, wenn mein Android-Paket tatsächlich com.company.android.app ist. Der Code in der ursprünglichen Frage funktioniert gut. Stellen Sie nur sicher, dass Sie alle erforderlichen Clients in Ihrem Google Cloud Console-Projekt haben.

Aber ein anderes Problem existiert noch. Als ich die einmalige Berechtigungszeichen von GoogleAuthUtil.getToken() an die Rails-Backend zurück senden, und dann versuchen, es für einen access_token und refresh_token auszutauschen, erhalte ich die folgen:

Signet::AuthorizationError: 
    Authorization failed. Server message: 
    { 
     "error" : "invalid_grant" 
    } 

Diese google documentation und Mehrere SO-Posts legen nahe, dass ich access_type=offline setzen muss. Aber ich denke, das ist, wenn Sie den einmaligen Autorisierungscode und Offline-Zugriff von einem Web-Server anfordern. Ich versuche, den einmaligen Autorisierungscode von einem Android-Client anzufordern und an den Webserver zu senden.

Ist das möglich mit GoogleAuthUtil.getToken()?

UPDATE 2

Google Plus Login im Bereich sein muss, auch wenn Sie nur versuchen, den Kalender zuzugreifen:

private final static String GOOGLE_CALENDAR_API_SCOPE = "oauth2:server:client_id:" + WEB_CLIENT_ID + ":api_scope:https://www.googleapis.com/auth/plus.login https://www.googleapis.com/auth/calendar"; 

Diese SO post hilfreich war. Auch Google's Cross Client identity documentation tut Zustand:

[Hinweis: Diese Richtlinie wird allmählich ausgerollt. Für den Moment, wenn Zugriffstoken beteiligt sind, es gilt nur, wenn die angeforderten Bereiche https://www.googleapis.com/auth/plus.login.]

schließen Ich werde in einer Antwort zusammenfassen, wenn der Token-Austausch funktioniert on Rails-Backend.

+0

Wie erhalten Sie einen Offline-Autorisierungscode (access_type = offline) mit GoogleAuthUtil.getToken()? Hast du das geschafft? – grebulon

+0

@grebulon Ja, ich war in der Lage, einen einmaligen Autorisierungscode mit GoogleAuthUtil.getToken() zu bekommen, nachdem ich die Dinge in der akzeptierten Antwort abgeschlossen hatte. Ich habe diesen einmaligen Autorisierungscode an unseren Backend-Server geschickt, der damit einen Google API Token bekommen hat. – mikeorr85

+0

Ich bekomme es fast zur Arbeit ... In meinem Fluss bekomme ich immer UserRecoverableAuthException (NeedPermission) für die Offline-Erlaubnis. Startet die empfangene Absicht und ruft getToken auf, startet das Dialogfeld zum Hinzufügen von Berechtigungen für die Offline-Berechtigung usw. in einer Endlosschleife. – grebulon

Antwort

3

Zwei Dinge für mich gelöst:

  1. Achten Sie darauf, die Android- und Web-Client-IDs werden im selben Google Cloud Console-Projekt korrekt eingerichtet.

  2. Verwenden Sie den richtigen Bereich. Plus-Login erforderlich ist, auch wenn Sie nur den Zugriff auf den Kalender api:

    // die ID des Web-Servers, der den Auth-Code für den Zugriff austauscht und aktualisieren Token

    Private final static String WEB_CLIENT_ID = „12345 .apps.googleusercontent.com "; private final static Zeichenfolge GOOGLE_CALENDAR_API_SCOPE = "oauth2: Server: Client-ID:" + WEB_CLIENT_ID + ": api_scope: https://www.googleapis.com/auth/plus.loginhttps://www.googleapis.com/auth/calendar";

0

Hier ist, was ich getan habe:

final String authToken = GoogleAuthUtil.getTokenWithNotification (this.context, account.name, "oauth2:" + AuthUtils.profileScope, new Bundle(), 
       Contract.authority, new Bundle()); 

Aber man schlicht getToken sollte das gleiche für eine Vordergrund-Aktivität arbeiten.

Nehmen Sie dieses Token und senden Sie es an den Server, so dass Sie es wie einen HTTP-Header (über HTTPS) verwenden können. Solange der Serverbereich eine Teilmenge des zum Erfassen des Tokens verwendeten Bereichs ist, sollten Sie kein Problem haben. Der Server verwendet die Server-ID und der Android-Client verwendet die Android-Client-ID.

Sie Ihr Anwendungsbereich gesetzt sollte entweder:

oauth2:https://www.googleapis.com/auth/calendar 

oder

oauth2:https://www.googleapis.com/auth/calendar.readonly 

Siehe https://developers.google.com/google-apps/calendar/auth

Edit: OK, ich sehe, was Sie zu tun versuchen. Der Umfang Wert wird ein Leerzeichen getrennte Liste, so dass Sie wahrscheinlich Publikum anhängen brauchen würde: Server: client_id: zu Ihrem Umfang wie:

"oauth2:https://www.googleapis.com/auth/calendar audience:server:client_id:12345-your-web-component-client-id" 
+0

Danke für die Antwort. Der obige Bereich gibt eine GoogleAuthException - "INVALID_SCOPE" zurück. Ich denke, Google benötigt nur einmal die Autorisierung von Clients im selben Projekt. Ich denke *, sagen sie [hier] (https://developers.google.com/accounts/docs/CrossClientAuth) – mikeorr85