Bei der Authentifizierung wird festgestellt, wer eine Person ist. Sie wird häufig als Nutzerregistrierung oder ‑anmeldung bezeichnet. Die Autorisierung ist der Prozess, bei dem der Zugriff auf Daten oder Ressourcen gewährt oder abgelehnt wird. Beispiel: Ihre App fordert die Zustimmung eines Nutzers an, auf Google Drive zuzugreifen.
Authentifizierungs- und Autorisierungsaufrufe müssen zwei separate und unterschiedliche Abläufe sein, die auf den Anforderungen der App basieren.
Wenn Ihre App Funktionen enthält, die Google API-Daten verwenden können, aber nicht zu den Kernfunktionen Ihrer App gehören, muss Ihre App Fälle, in denen API-Daten nicht zugänglich sind, problemlos verarbeiten können. Sie können beispielsweise eine Liste der zuletzt gespeicherten Dateien ausblenden, wenn der Nutzer keinen Zugriff auf Drive gewährt hat.
Sie sollten nur dann Zugriff auf Bereiche anfordern, die Sie für den Zugriff auf Google APIs benötigen, wenn der Nutzer eine Aktion ausführt, die Zugriff auf eine bestimmte API erfordert. Sie sollten beispielsweise immer dann eine Berechtigung für den Zugriff auf das Drive des Nutzers anfordern, wenn der Nutzer auf die Schaltfläche In Drive speichern tippt.
Wenn Sie die Autorisierung von der Authentifizierung trennen, können Sie vermeiden, dass neue Nutzer überfordert werden oder dass Nutzer verwirrt sind, warum sie um bestimmte Berechtigungen gebeten werden.
Für die Authentifizierung empfehlen wir die Verwendung der Credential Manager API. Für die Autorisierung von Aktionen, die Zugriff auf von Google gespeicherte Nutzerdaten erfordern, empfehlen wir die Verwendung von AuthorizationClient.
Google Cloud Console-Projekt einrichten
- Öffnen Sie Ihr Projekt in der Cloud Console, oder erstellen Sie ein Projekt, falls Sie noch keines haben.
- Prüfen Sie auf der Seite „Branding“,
ob alle Informationen vollständig und korrekt sind.
- Achten Sie darauf, dass Ihrer App ein korrekter App-Name, ein korrektes App-Logo und eine korrekte App-Homepage zugewiesen sind. Diese Werte werden Nutzern bei der Registrierung auf dem Zustimmungsbildschirm „Über Google anmelden“ und auf dem Bildschirm „Drittanbieter-Apps und ‑Dienste“ angezeigt.
- Achten Sie darauf, dass Sie die URLs der Datenschutzerklärung und der Nutzungsbedingungen Ihrer App angegeben haben.
- Erstellen Sie auf der Seite „Clients“ eine Android-Client-ID für Ihre App, falls Sie noch keine haben. Sie müssen den Paketnamen und die SHA-1-Signatur Ihrer App angeben.
- Rufen Sie die Seite „Clients“ auf.
- Klicken Sie auf Client erstellen.
- Wählen Sie den Anwendungstyp Android aus.
- Geben Sie einen Namen für den OAuth-Client ein. Dieser Name wird auf der Seite „ Clients“ Ihres Projekts angezeigt, um den Client zu identifizieren.
- Geben Sie den Paketnamen Ihrer Android-App ein. Dieser Wert ist im
packageAttribut des<manifest>Elements in IhrerAndroidManifest.xmlDatei definiert. - Geben Sie den SHA-1-Signaturzertifikat-Fingerabdruck der App-Verteilung ein.
- Wenn Ihre App die App-Signatur von Google Play verwendet, kopieren Sie den SHA-1-Fingerabdruck von der Seite für die App-Signatur in der Play Console.
- Wenn Sie Ihren eigenen Keystore und Ihre eigenen Signaturschlüssel verwalten, verwenden Sie das keytool
Dienstprogramm, das in Java enthalten ist, um Zertifikatsinformationen in einem
für Menschen lesbaren Format auszugeben. Kopieren Sie den
SHA-1Wert imCertificate fingerprintsAbschnitt der keytool Ausgabe. Weitere Informationen finden Sie unter Authentifizieren Ihres Clients in der Dokumentation zu den Google APIs für Android. - Optional: Bestätigen Sie die Inhaberschaft Ihrer Android Anwendung.
- Erstellen Sie auf der Seite „Clients“
eine neue Client-ID für die Webanwendung, falls Sie noch keine haben. Sie können die Felder „Autorisierte JavaScript-Quellen“ und „Autorisierte Weiterleitungs-URIs“ vorerst ignorieren. Diese Client-ID wird verwendet, um Ihren Back-End-Server zu identifizieren, wenn er mit den Authentifizierungsdiensten von Google kommuniziert.
- Rufen Sie die Seite „Clients“ auf.
- Klicken Sie auf Client erstellen.
- Wählen Sie den Typ Webanwendung aus.
App-Inhaberschaft bestätigen
Sie können die Inhaberschaft Ihrer Anwendung bestätigen, um das Risiko von App-Imitationen zu verringern.
Wenn Sie ein Google Play-Entwicklerkonto haben und Ihre App in der Google Play Console registriert ist, können Sie dieses Konto verwenden, um die Bestätigung abzuschließen. Für eine erfolgreiche Bestätigung müssen die folgenden Voraussetzungen erfüllt sein:
- Sie müssen in der Google Play Console eine registrierte Anwendung mit demselben Paketnamen und SHA-1-Zertifikat-Fingerabdruck wie der Android-OAuth-Client haben, für den Sie die Bestätigung durchführen.
- Sie müssen die Berechtigung Administrator für die App in der Google Play Console haben. Weitere Informationen zur Zugriffsverwaltung in der Google Play Console
Klicken Sie im Abschnitt App-Inhaberschaft bestätigen des Android-Clients auf die Schaltfläche Inhaberschaft bestätigen, um die Bestätigung abzuschließen.
Wenn die Bestätigung erfolgreich ist, wird eine Benachrichtigung angezeigt, um den Erfolg der Bestätigung zu bestätigen. Andernfalls wird eine Fehlermeldung angezeigt.
So beheben Sie eine fehlgeschlagene Bestätigung:
- Achten Sie darauf, dass die App, die Sie bestätigen, in der Google Play Console registriert ist.
- Achten Sie darauf, dass Sie die Berechtigung Administrator für die App in der Google Play Console haben.
Abhängigkeiten deklarieren
Deklarieren Sie in der Datei build.gradle Ihres Moduls Abhängigkeiten mit der neuesten Version der Google Identity Services-Bibliothek.
dependencies {
// ... other dependencies
implementation "com.google.android.gms:play-services-auth:21.5.1"
}
Berechtigungen anfordern, die für Nutzeraktionen erforderlich sind
Wenn ein Nutzer eine Aktion ausführt, die einen zusätzlichen Bereich erfordert, rufen Sie AuthorizationClient.authorize() auf. Wenn ein Nutzer beispielsweise eine Aktion ausführt, die Zugriff auf den Speicher seiner Drive-App erfordert, gehen Sie so vor:
Kotlin
val requestedScopes: List<Scope> = listOf(DriveScopes.DRIVE_FILE)
val authorizationRequest = AuthorizationRequest.builder()
.setRequestedScopes(requestedScopes)
.build()
Identity.getAuthorizationClient(activity)
.authorize(authorizationRequestBuilder.build())
.addOnSuccessListener { authorizationResult ->
if (authorizationResult.hasResolution()) {
val pendingIntent = authorizationResult.pendingIntent
// Access needs to be granted by the user
startAuthorizationIntent.launch(IntentSenderRequest.Builder(pendingIntent!!.intentSender).build())
} else {
// Access was previously granted, continue with user action
saveToDriveAppFolder(authorizationResult);
}
}
.addOnFailureListener { e -> Log.e(TAG, "Failed to authorize", e) }
Java
List<Scopes> requestedScopes = Arrays.asList(DriveScopes.DRIVE_FILE);
AuthorizationRequest authorizationRequest = AuthorizationRequest.builder()
.setRequestedScopes(requestedScopes)
.build();
Identity.getAuthorizationClient(activity)
.authorize(authorizationRequest)
.addOnSuccessListener(authorizationResult -> {
if (authorizationResult.hasResolution()) {
// Access needs to be granted by the user
startAuthorizationIntent.launch(
new IntentSenderRequest.Builder(
authorizationResult.getPendingIntent().getIntentSender()
).build()
);
} else {
// Access was previously granted, continue with user action
saveToDriveAppFolder(authorizationResult);
}
})
.addOnFailureListener(e -> Log.e(TAG, "Failed to authorize", e));
Wenn Sie ActivityResultLauncher definieren, verarbeiten Sie die Antwort wie im folgenden Snippet gezeigt. Hier wird davon ausgegangen, dass dies in einem Fragment erfolgt. Der Code prüft, ob die erforderlichen Berechtigungen erfolgreich erteilt wurden, und führt dann die Nutzeraktion aus.
Kotlin
private lateinit var startAuthorizationIntent: ActivityResultLauncher<IntentSenderRequest>
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?,
): View? {
// ...
startAuthorizationIntent =
registerForActivityResult(ActivityResultContracts.StartIntentSenderForResult()) { activityResult ->
try {
// extract the result
val authorizationResult = Identity.getAuthorizationClient(requireContext())
.getAuthorizationResultFromIntent(activityResult.data)
// continue with user action
saveToDriveAppFolder(authorizationResult);
} catch (e: ApiException) {
// log exception
}
}
}
Java
private ActivityResultLauncher<IntentSenderRequest> startAuthorizationIntent;
@Override
public View onCreateView(
@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
// ...
startAuthorizationIntent =
registerForActivityResult(
new ActivityResultContracts.StartIntentSenderForResult(),
activityResult -> {
try {
// extract the result
AuthorizationResult authorizationResult =
Identity.getAuthorizationClient(requireActivity())
.getAuthorizationResultFromIntent(activityResult.getData());
// continue with user action
saveToDriveAppFolder(authorizationResult);
} catch (ApiException e) {
// log exception
}
});
}
Wenn Sie serverseitig auf Google APIs zugreifen, rufen Sie die
getServerAuthCode() Methode aus AuthorizationResult auf, um einen
Autorisierungscode zu erhalten, den Sie an Ihr Back-End senden, um ihn gegen ein Zugriffs- und
Aktualisierungstoken einzutauschen. Weitere Informationen finden Sie unter
Dauerhaften Zugriff auf die Daten des Nutzers aufrechterhalten.
Berechtigungen für Nutzerdaten oder ‑ressourcen widerrufen
Wenn Sie zuvor gewährten Zugriff widerrufen möchten, rufen Sie
AuthorizationClient.revokeAccess() auf. Wenn der Nutzer beispielsweise sein Konto aus Ihrer App entfernt und Ihrer App zuvor Zugriff auf DriveScopes.DRIVE_FILE gewährt wurde, verwenden Sie den folgenden Code, um den Zugriff zu widerrufen:
Kotlin
val requestedScopes: MutableList<Scope> = mutableListOf(DriveScopes.DRIVE_FILE)
RevokeAccessRequest revokeAccessRequest = RevokeAccessRequest.builder()
.setAccount(account)
.setScopes(requestedScopes)
.build()
Identity.getAuthorizationClient(activity)
.revokeAccess(revokeAccessRequest)
.addOnSuccessListener { Log.i(TAG, "Successfully revoked access") }
.addOnFailureListener { e -> Log.e(TAG, "Failed to revoke access", e) }
Java
List<Scopes> requestedScopes = Arrays.asList(DriveScopes.DRIVE_FILE);
RevokeAccessRequest revokeAccessRequest = RevokeAccessRequest.builder()
.setAccount(account)
.setScopes(requestedScopes)
.build();
Identity.getAuthorizationClient(activity)
.revokeAccess(revokeAccessRequest)
.addOnSuccessListener(unused -> Log.i(TAG, "Successfully revoked access"))
.addOnFailureListener(e -> Log.e(TAG, "Failed to revoke access", e));
Token-Cache leeren
OAuth-Zugriffstokens werden nach dem Empfang vom Server lokal im Cache gespeichert, wodurch der Zugriff beschleunigt und die Anzahl der Netzwerkaufrufe reduziert wird. Diese Tokens werden automatisch aus dem Cache gelöscht, wenn sie ablaufen. Sie können aber auch aus anderen Gründen ungültig werden.
Wenn Sie beim Verwenden eines Tokens eine IllegalStateException erhalten, leeren Sie den lokalen Cache, damit die nächste Autorisierungsanfrage für ein Zugriffstoken an den OAuth-Server gesendet wird. Mit dem folgenden Snippet wird invalidAccessToken aus dem lokalen Cache entfernt:
Kotlin
Identity.getAuthorizationClient(activity)
.clearToken(ClearTokenRequest.builder().setToken(invalidAccessToken).build())
.addOnSuccessListener { Log.i(TAG, "Successfully removed the token from the cache") }
.addOnFailureListener{ e -> Log.e(TAG, "Failed to clear token", e) }
Java
Identity.getAuthorizationClient(activity)
.clearToken(ClearTokenRequest.builder().setToken(invalidAccessToken).build())
.addOnSuccessListener(unused -> Log.i(TAG, "Successfully removed the token from the cache"))
.addOnFailureListener(e -> Log.e(TAG, "Failed to clear the token cache", e));
Nutzerinformationen während der Autorisierung abrufen
Die Autorisierungsantwort enthält keine Informationen zum verwendeten Nutzerkonto. Sie enthält nur ein Token für die angeforderten Bereiche. Beispiel: Die Antwort auf das Abrufen eines Zugriffstokens für den Zugriff auf Google Drive eines Nutzers enthält nicht die Identität des vom Nutzer ausgewählten Kontos, obwohl damit auf Dateien auf dem Drive des Nutzers zugegriffen werden kann. So erhalten Sie Informationen wie den Namen oder die E‑Mail-Adresse des Nutzers:
Melden Sie den Nutzer mit seinem Google-Konto über die Credential Manager APIs an, bevor Sie die Autorisierung anfordern. Die Authentifizierungsantwort von Credential Manager enthält Nutzerinformationen wie die E‑Mail-Adresse und legt außerdem das Standardkonto der App auf das ausgewählte Konto fest. Bei Bedarf können Sie dieses Konto in Ihrer App verfolgen. Bei einer nachfolgenden Autorisierungsanfrage wird das Konto als Standard verwendet und der Schritt zur Kontoauswahl im Autorisierungsablauf wird übersprungen. Informationen zur Verwendung eines anderen Kontos für die Autorisierung finden Sie unter Autorisierung über ein anderes als das Standardkonto.
Fordern Sie in Ihrer Autorisierungsanfrage zusätzlich zu den gewünschten Bereichen (z. B. dem
Drive scope) die Bereicheuserinfo,profile, undopenidan. Nachdem ein Zugriffstoken zurückgegeben wurde, rufen Sie die Nutzerinformationen ab, indem Sie eineGET-HTTP-Anfrage an den OAuth-Nutzerinfo-Endpunkt (https://www.googleapis.com/oauth2/v3/userinfo) senden. Verwenden Sie dazu Ihre bevorzugte HTTP-Bibliothek und fügen Sie das erhaltene Zugriffstoken im Header ein. Das entspricht dem folgendencurl-Befehl:curl -X GET \ "https://www.googleapis.com/oauth2/v1/userinfo?alt=json" \ -H "Authorization: Bearer $TOKEN"Die Antwort ist das
UserInfo-Objekt, das auf die angeforderten Bereiche beschränkt ist und im JSON-Format vorliegt.
Autorisierung über ein anderes als das Standardkonto
Wenn Sie Credential Manager zur Authentifizierung verwenden und
AuthorizationClient.authorize() ausführen, wird das Standardkonto Ihrer App auf
das vom Nutzer ausgewählte Konto festgelegt. Das bedeutet, dass bei allen nachfolgenden Autorisierungsaufrufen dieses Standardkonto verwendet wird. Wenn Sie erzwingen möchten, dass die Kontoauswahl angezeigt wird,
melden Sie den Nutzer mit der clearCredentialState() API von
Credential Manager von der App ab.
Dauerhaften Zugriff auf die Daten des Nutzers aufrechterhalten
Wenn Sie über Ihre App auf die Daten des Nutzers zugreifen müssen, rufen Sie
AuthorizationClient.authorize() einmal auf. In nachfolgenden Sitzungen und solange die gewährten Berechtigungen nicht vom Nutzer entfernt werden, rufen Sie dieselbe
Methode auf, um ein Zugriffstoken zu erhalten, ohne dass eine Nutzerinteraktion erforderlich ist. Wenn Sie hingegen im Offlinemodus von Ihrem Back-End-Server aus auf die Daten des Nutzers zugreifen müssen, müssen Sie eine andere Art von Token anfordern, das als Aktualisierungstoken bezeichnet wird.
Zugriffstokens sind bewusst kurzlebig und haben eine Lebensdauer von einer Stunde. Wenn ein Zugriffstoken abgefangen oder kompromittiert wird, minimiert die begrenzte Gültigkeitsdauer potenziellen Missbrauch. Nach Ablauf der Gültigkeitsdauer ist das Token ungültig und alle Versuche, es zu verwenden, werden vom Ressourcenserver abgelehnt. Da Zugriffstokens kurzlebig sind, verwenden Server Aktualisierungstokens, um den kontinuierlichen Zugriff auf die Daten eines Nutzers aufrechtzuerhalten. Aktualisierungstokens sind Tokens mit langer Lebensdauer, die von einem Client verwendet werden, um ein kurzlebiges Zugriffstoken vom Autorisierungsserver anzufordern, wenn das alte Zugriffstoken abgelaufen ist, ohne dass eine Nutzerinteraktion erforderlich ist.
Um ein Aktualisierungstoken zu erhalten, müssen Sie zuerst einen Autorisierungscode während des Autorisierungsschritts in Ihrer App abrufen, indem Sie „Offlinezugriff“ anfordern. Anschließend tauschen Sie den Autorisierungscode auf Ihrem Server gegen ein Aktualisierungstoken ein. Es ist wichtig, langlebige Aktualisierungstokens sicher auf Ihrem Server zu speichern, da sie wiederholt verwendet werden können, um neue Zugriffstokens zu erhalten. Aus Sicherheitsgründen wird daher dringend davon abgeraten, Aktualisierungstokens auf dem Gerät zu speichern. Stattdessen sollten sie auf den Back-End-Servern der App gespeichert werden, wo der Austausch gegen ein Zugriffstoken erfolgt.
Nachdem der Autorisierungscode an den Back-End-Server Ihrer App gesendet wurde, können Sie ihn auf dem Server gegen ein kurzlebiges Zugriffstoken und ein langlebiges Aktualisierungstoken eintauschen. Folgen Sie dazu der Anleitung zur Kontoautorisierung. Dieser Austausch sollte nur im Back-End Ihrer App erfolgen.
Kotlin
// Ask for offline access during the first authorization request
val authorizationRequest = AuthorizationRequest.builder()
.setRequestedScopes(requestedScopes)
.requestOfflineAccess(serverClientId)
.build()
Identity.getAuthorizationClient(activity)
.authorize(authorizationRequest)
.addOnSuccessListener { authorizationResult ->
startAuthorizationIntent.launch(IntentSenderRequest.Builder(
pendingIntent!!.intentSender
).build())
}
.addOnFailureListener { e -> Log.e(TAG, "Failed to authorize", e) }
Java
// Ask for offline access during the first authorization request
AuthorizationRequest authorizationRequest = AuthorizationRequest.builder()
.setRequestedScopes(requestedScopes)
.requestOfflineAccess(serverClientId)
.build();
Identity.getAuthorizationClient(getContext())
.authorize(authorizationRequest)
.addOnSuccessListener(authorizationResult -> {
startAuthorizationIntent.launch(
new IntentSenderRequest.Builder(
authorizationResult.getPendingIntent().getIntentSender()
).build()
);
})
.addOnFailureListener(e -> Log.e(TAG, "Failed to authorize"));
Im folgenden Snippet wird davon ausgegangen, dass die Autorisierung über ein Fragment gestartet wird.
Kotlin
private lateinit var startAuthorizationIntent: ActivityResultLauncher<IntentSenderRequest>
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?,
): View? {
// ...
startAuthorizationIntent =
registerForActivityResult(ActivityResultContracts.StartIntentSenderForResult()) { activityResult ->
try {
val authorizationResult = Identity.getAuthorizationClient(requireContext())
.getAuthorizationResultFromIntent(activityResult.data)
// short-lived access token
accessToken = authorizationResult.accessToken
// store the authorization code used for getting a refresh token safely to your app's backend server
val authCode: String = authorizationResult.serverAuthCode
storeAuthCodeSafely(authCode)
} catch (e: ApiException) {
// log exception
}
}
}
Java
private ActivityResultLauncher<IntentSenderRequest> startAuthorizationIntent;
@Override
public View onCreateView(
@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
// ...
startAuthorizationIntent =
registerForActivityResult(
new ActivityResultContracts.StartIntentSenderForResult(),
activityResult -> {
try {
AuthorizationResult authorizationResult =
Identity.getAuthorizationClient(requireActivity())
.getAuthorizationResultFromIntent(activityResult.getData());
// short-lived access token
accessToken = authorizationResult.getAccessToken();
// store the authorization code used for getting a refresh token safely to your app's backend server
String authCode = authorizationResult.getServerAuthCode()
storeAuthCodeSafely(authCode);
} catch (ApiException e) {
// log exception
}
});
}