Wenn Sie Google-Dienste im Namen eines Nutzers verwenden möchten, während dieser offline ist, müssen Sie einen hybriden serverseitigen Ablauf verwenden, bei dem ein Nutzer Ihre App auf der Clientseite mithilfe des JavaScript API-Clients autorisiert und Sie einen speziellen Einmalautorisierungscode an Ihren Server senden. Ihr Server tauscht diesen Einmalcode aus, um eigene Zugriffs- und Aktualisierungstokens von Google zu erhalten, damit der Server eigene API-Aufrufe ausführen kann. Dies ist auch möglich, wenn der Nutzer offline ist. Dieser Ablauf mit Einmalcode bietet sowohl gegenüber einem reinen serverseitigen Ablauf als auch gegenüber dem Senden von Zugriffstokens an Ihren Server Sicherheitsvorteile.
Unten ist der Anmeldevorgang zum Abrufen eines Zugriffstokens für Ihre serverseitige Anwendung dargestellt.
Einmalcodes bieten mehrere Sicherheitsvorteile. Bei Codes stellt Google Tokens direkt an Ihren Server ohne Zwischenhändler bereit. Wir empfehlen zwar nicht, Codes preiszugeben, aber ohne Ihr Client-Secret sind sie nur schwer zu verwenden. Bewahren Sie Ihr Clientsecret geheim auf.
Einmalcode-Ablauf implementieren
Die Schaltfläche „Über Google anmelden“ stellt sowohl ein Zugriffstoken als auch einen Autorisierungscode bereit. Der Code ist ein Einmalcode, den Ihr Server gegen ein Zugriffstoken mit den Google-Servern austauschen kann.
Der folgende Beispielcode veranschaulicht den Ablauf für den Einmalcode.
Für die Authentifizierung der Google-Anmeldung mit dem Einmalcode-Vorgang müssen Sie Folgendes tun:
Schritt 1: Client-ID und Clientschlüssel erstellen
Wenn Sie eine Client-ID und ein Client-Secret erstellen möchten, erstellen Sie ein Google API Console-Projekt, richten Sie eine OAuth-Client-ID ein und registrieren Sie Ihre JavaScript-Quellen:
Gehen Sie zur Google API Console.
Wählen Sie im Drop-down-Menü „Projekt“ ein vorhandenes Projekt aus oder erstellen Sie ein neues, indem Sie Neues Projekt erstellen auswählen.
Wählen Sie in der Seitenleiste unter „APIs und Dienste“ die Option Anmeldedaten aus und klicken Sie dann auf Zustimmungsbildschirm konfigurieren.
Wählen Sie eine E-Mail-Adresse aus, geben Sie einen Produktnamen an und drücken Sie auf Speichern.
Wählen Sie auf dem Tab Anmeldedaten das Drop-down-Menü Anmeldedaten erstellen und dann OAuth-Client-ID aus.
Wählen Sie unter Anwendungstyp die Option Webanwendung aus.
Registrieren Sie die Ursprünge, von denen aus Ihre App auf die Google APIs zugreifen darf, wie unten beschrieben. Eine Quelle ist eine eindeutige Kombination aus Protokoll, Hostnamen und Port.
Geben Sie im Feld Autorisierte JavaScript-Quellen die Quelle für Ihre App ein. Sie können mehrere Quellen eingeben, damit Ihre App auf verschiedenen Protokollen, Domains oder Subdomains ausgeführt werden kann. Sie können keine Platzhalter verwenden. Im folgenden Beispiel könnte die zweite URL eine Produktions-URL sein.
http://localhost:8080 https://myproductionurl.example.com
Für das Feld Autorisierter Weiterleitungs-URI ist kein Wert erforderlich. Weiterleitungs-URIs werden nicht mit JavaScript APIs verwendet.
Klicken Sie auf die Schaltfläche Erstellen.
Kopieren Sie im angezeigten Dialogfeld OAuth-Client die Client-ID. Über die Client-ID kann Ihre App auf aktivierte Google APIs zugreifen.
Schritt 2: Google-Plattformbibliothek auf Ihrer Seite einfügen
Fügen Sie die folgenden Scripts ein, die eine anonyme Funktion zeigen, die ein Script in das DOM dieser index.html
-Webseite einfügt.
<!-- The top of file index.html -->
<html itemscope itemtype="http://schema.org/Article">
<head>
<!-- BEGIN Pre-requisites -->
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js">
</script>
<script src="https://apis.google.com/js/client:platform.js?onload=start" async defer>
</script>
<!-- END Pre-requisites -->
Schritt 3: GoogleAuth-Objekt initialisieren
Lade die auth2-Bibliothek und rufe gapi.auth2.init()
auf, um das GoogleAuth
-Objekt zu initialisieren. Geben Sie beim Aufruf von init()
Ihre Client-ID und die gewünschten Bereiche an.
<!-- Continuing the <head> section -->
<script>
function start() {
gapi.load('auth2', function() {
auth2 = gapi.auth2.init({
client_id: 'YOUR_CLIENT_ID.apps.googleusercontent.com',
// Scopes to request in addition to 'profile' and 'email'
//scope: 'additional_scope'
});
});
}
</script>
</head>
<body>
<!-- ... -->
</body>
</html>
Schritt 4: Anmeldeschaltfläche auf der Seite hinzufügen
Fügen Sie Ihrer Webseite die Anmeldeschaltfläche hinzu und fügen Sie einen Klick-Handler hinzu, um grantOfflineAccess()
aufzurufen und den Ablauf für den Einmalcode zu starten.
<!-- Add where you want your sign-in button to render -->
<!-- Use an image that follows the branding guidelines in a real app -->
<button id="signinButton">Sign in with Google</button>
<script>
$('#signinButton').click(function() {
// signInCallback defined in step 6.
auth2.grantOfflineAccess().then(signInCallback);
});
</script>
Schritt 5: Nutzer anmelden
Der Nutzer klickt auf die Anmeldeschaltfläche und gewährt Ihrer App Zugriff auf die von Ihnen angeforderten Berechtigungen. Anschließend wird der Rückruffunktion, die du in der Methode grantOfflineAccess().then()
angegeben hast, ein JSON-Objekt mit einem Autorisierungscode übergeben. Beispiel:
{"code":"4/yU4cQZTMnnMtetyFcIWNItG32eKxxxgXXX-Z4yyJJJo.4qHskT-UtugceFc0ZRONyF4z7U4UmAI"}
Schritt 6: Autorisierungscode an den Server senden
code
ist ein Einmalcode, den dein Server gegen ein eigenes Zugriffs- und Aktualisierungstoken eintauschen kann. Sie können ein Aktualisierungstoken erst abrufen, nachdem dem Nutzer ein Autorisierungsdialogfeld für den Offlinezugriff angezeigt wurde.
Wenn du in Schritt 4 select-account
prompt
in OfflineAccessOptions
angegeben hast, musst du das abgerufene Aktualisierungstoken für später speichern, da bei nachfolgenden Austauschen null
für das Aktualisierungstoken zurückgegeben wird. Dieser Ablauf bietet im Vergleich zum standardmäßigen OAuth 2.0-Vorgang mehr Sicherheit.
Zugriffstokens werden immer beim Austausch eines gültigen Autorisierungscodes zurückgegeben.
Im folgenden Script wird eine Callback-Funktion für die Anmeldeschaltfläche definiert. Wenn die Anmeldung erfolgreich war, speichert die Funktion das Zugriffstoken für die clientseitige Verwendung und sendet den Einmalcode an Ihren Server in derselben Domain.
<!-- Last part of BODY element in file index.html -->
<script>
function signInCallback(authResult) {
if (authResult['code']) {
// Hide the sign-in button now that the user is authorized, for example:
$('#signinButton').attr('style', 'display: none');
// Send the code to the server
$.ajax({
type: 'POST',
url: 'http://example.com/storeauthcode',
// Always include an `X-Requested-With` header in every AJAX request,
// to protect against CSRF attacks.
headers: {
'X-Requested-With': 'XMLHttpRequest'
},
contentType: 'application/octet-stream; charset=utf-8',
success: function(result) {
// Handle or verify the server response.
},
processData: false,
data: authResult['code']
});
} else {
// There was an error.
}
}
</script>
Schritt 7: Autorisierungscode gegen ein Zugriffstoken austauschen
Tausche den Autorisierungscode auf dem Server gegen Zugriffs- und Aktualisierungstokens aus. Verwenden Sie das Zugriffstoken, um im Namen des Nutzers Google APIs aufzurufen, und speichern Sie optional das Aktualisierungstoken, um ein neues Zugriffstoken abzurufen, wenn das aktuelle abläuft.
Wenn Sie den Profilzugriff angefordert haben, erhalten Sie außerdem ein ID-Token mit grundlegenden Profilinformationen für den Nutzer.
Beispiel:
Java
// (Receive authCode via HTTPS POST) if (request.getHeader("X-Requested-With") == null) { // Without the `X-Requested-With` header, this request could be forged. Aborts. } // Set path to the Web application client_secret_*.json file you downloaded from the // Google API Console: https://console.cloud.google.com/apis/credentials // You can also find your Web application client ID and client secret from the // console and specify them directly when you create the GoogleAuthorizationCodeTokenRequest // object. String CLIENT_SECRET_FILE = "/path/to/client_secret.json"; // Exchange auth code for access token GoogleClientSecrets clientSecrets = GoogleClientSecrets.load( JacksonFactory.getDefaultInstance(), new FileReader(CLIENT_SECRET_FILE)); GoogleTokenResponse tokenResponse = new GoogleAuthorizationCodeTokenRequest( new NetHttpTransport(), JacksonFactory.getDefaultInstance(), "https://oauth2.googleapis.com/token", clientSecrets.getDetails().getClientId(), clientSecrets.getDetails().getClientSecret(), authCode, REDIRECT_URI) // Specify the same redirect URI that you use with your web // app. If you don't have a web version of your app, you can // specify an empty string. .execute(); String accessToken = tokenResponse.getAccessToken(); // Use access token to call API GoogleCredential credential = new GoogleCredential().setAccessToken(accessToken); Drive drive = new Drive.Builder(new NetHttpTransport(), JacksonFactory.getDefaultInstance(), credential) .setApplicationName("Auth Code Exchange Demo") .build(); File file = drive.files().get("appfolder").execute(); // Get profile info from ID token GoogleIdToken idToken = tokenResponse.parseIdToken(); GoogleIdToken.Payload payload = idToken.getPayload(); String userId = payload.getSubject(); // Use this value as a key to identify a user. String email = payload.getEmail(); boolean emailVerified = Boolean.valueOf(payload.getEmailVerified()); String name = (String) payload.get("name"); String pictureUrl = (String) payload.get("picture"); String locale = (String) payload.get("locale"); String familyName = (String) payload.get("family_name"); String givenName = (String) payload.get("given_name");
Python
from apiclient import discovery import httplib2 from oauth2client import client # (Receive auth_code by HTTPS POST) # If this request does not have `X-Requested-With` header, this could be a CSRF if not request.headers.get('X-Requested-With'): abort(403) # Set path to the Web application client_secret_*.json file you downloaded from the # Google API Console: https://console.cloud.google.com/apis/credentials CLIENT_SECRET_FILE = '/path/to/client_secret.json' # Exchange auth code for access token, refresh token, and ID token credentials = client.credentials_from_clientsecrets_and_code( CLIENT_SECRET_FILE, ['https://www.googleapis.com/auth/drive.appdata', 'profile', 'email'], auth_code) # Call Google API http_auth = credentials.authorize(httplib2.Http()) drive_service = discovery.build('drive', 'v3', http=http_auth) appfolder = drive_service.files().get(fileId='appfolder').execute() # Get profile info from ID token userid = credentials.id_token['sub'] email = credentials.id_token['email']