Mit Apple auf Android-Geräten authentifizieren

Sie können Ihren Nutzern die Authentifizierung mit Firebase über ihre Apple-ID ermöglichen, indem Sie das Firebase SDK verwenden, um den End-to-End-OAuth 2.0-Anmeldevorgang durchzuführen.

Hinweis

Wenn Sie Nutzer mit Apple anmelden möchten, müssen Sie zuerst „Mit Apple anmelden“ auf der Entwicklerwebsite von Apple konfigurieren und dann Apple als Anmeldeanbieter für Ihr Firebase-Projekt aktivieren.

Am Apple-Programm für Entwickler teilnehmen

„Über Apple anmelden“ kann nur von Mitgliedern des Apple-Programms für Entwickler konfiguriert werden.

Über Apple anmelden konfigurieren

Führen Sie auf der Apple Developer-Website die folgenden Schritte aus:

  1. Verknüpfen Sie Ihre Website mit Ihrer App, wie im ersten Abschnitt von Mit Apple im Web anmelden beschrieben. Registrieren Sie die folgende URL als Return-URL, wenn Sie dazu aufgefordert werden:

    https://YOUR_FIREBASE_PROJECT_ID.firebaseapp.com/__/auth/handler

    Sie finden Ihre Firebase-Projekt-ID in der Firebase Console auf der Seite „Einstellungen“.

    Notieren Sie sich nach Abschluss die neue Dienst-ID, die Sie im nächsten Abschnitt benötigen.

  2. Erstellen Sie einen privaten Schlüssel für „Mit Apple anmelden“. Sie benötigen Ihren neuen privaten Schlüssel und die Schlüssel-ID im nächsten Abschnitt.
  3. Wenn Sie Funktionen von Firebase Authentication verwenden, mit denen E‑Mails an Nutzer gesendet werden, z. B. die Anmeldung per E‑Mail-Link, die Bestätigung der E‑Mail-Adresse oder den Widerruf von Kontoänderungen, müssen Sie den privaten E‑Mail-Relay-Dienst von Apple konfigurieren und noreply@YOUR_FIREBASE_PROJECT_ID.firebaseapp.com (oder Ihre benutzerdefinierte E‑Mail-Vorlagendomain) registrieren, damit Apple E‑Mails, die von Firebase Authentication an anonymisierte Apple-E‑Mail-Adressen gesendet werden, weiterleiten kann.

Apple als Anmeldeanbieter aktivieren

  1. Fügen Sie Ihrem Android-Projekt Firebase hinzu. Registrieren Sie die SHA-1-Signatur Ihrer App, wenn Sie Ihre App in der Firebase-Konsole einrichten.
  2. Öffnen Sie in der Firebase-Konsole den Bereich Auth (Authentifizierung). Aktivieren Sie auf dem Tab Anmeldemethode den Anbieter Apple. Geben Sie die Dienst-ID an, die Sie im vorherigen Abschnitt erstellt haben. Geben Sie außerdem im Abschnitt „OAuth-Code-Ablauf konfigurieren“ Ihre Apple-Team-ID sowie den privaten Schlüssel und die Schlüssel-ID an, die Sie im vorherigen Abschnitt erstellt haben.

Anforderungen von Apple für anonymisierte Daten einhalten

Mit „Mit Apple anmelden“ haben Nutzer die Möglichkeit, ihre Daten, einschließlich ihrer E-Mail-Adresse, bei der Anmeldung zu anonymisieren. Nutzer, die diese Option auswählen, haben E-Mail-Adressen mit der Domain privaterelay.appleid.com. Wenn Sie „Mit Apple anmelden“ in Ihrer App verwenden, müssen Sie alle anwendbaren Entwicklerrichtlinien oder ‑bedingungen von Apple bezüglich dieser anonymisierten Apple-IDs einhalten.

Außerdem müssen Sie die erforderliche Einwilligung des Nutzers einholen, bevor Sie direkt identifizierbare personenbezogene Daten mit einer anonymisierten Apple-ID verknüpfen. Wenn Sie die Firebase-Authentifizierung verwenden, kann dies die folgenden Aktionen umfassen:

  • Eine E‑Mail-Adresse mit einer anonymisierten Apple‑ID verknüpfen und umgekehrt
  • Telefonnummer mit einer anonymisierten Apple‑ID verknüpfen und umgekehrt
  • Nicht-anonyme Anmeldedaten für soziale Medien (Facebook, Google usw.) mit einer anonymisierten Apple-ID verknüpfen und umgekehrt

Die obige Liste ist nicht vollständig. In der Lizenzvereinbarung des Apple-Entwicklerprogramms im Mitgliedschaftsbereich Ihres Entwicklerkontos finden Sie Informationen dazu, ob Ihre App die Anforderungen von Apple erfüllt.

Anmeldevorgang mit dem Firebase SDK abwickeln

Unter Android ist die einfachste Möglichkeit, Ihre Nutzer mit Firebase über ihre Apple-Konten zu authentifizieren, den gesamten Anmeldevorgang mit dem Firebase Android SDK zu verarbeiten.

So handhaben Sie den Anmeldevorgang mit dem Firebase Android SDK:

  1. Erstellen Sie eine Instanz von OAuthProvider mit dem Builder und der Anbieter-ID apple.com:

    Kotlin

    val provider = OAuthProvider.newBuilder("apple.com")
    

    Java

    OAuthProvider.Builder provider = OAuthProvider.newBuilder("apple.com");
    
  2. Optional:Geben Sie zusätzliche OAuth 2.0-Bereiche an, die Sie vom Authentifizierungsanbieter anfordern möchten.

    Kotlin

    provider.setScopes(arrayOf("email", "name"))
    

    Java

    List<String> scopes =
        new ArrayList<String>() {
          {
            add("email");
            add("name");
          }
        };
    provider.setScopes(scopes);
    

    Wenn Ein Konto pro E-Mail-Adresse aktiviert ist, fordert Firebase standardmäßig die Bereiche „E-Mail-Adresse“ und „Name“ an. Wenn Sie diese Einstellung in Mehrere Konten pro E-Mail-Adresse ändern, werden in Firebase keine Bereiche von Apple angefordert, sofern Sie sie nicht angeben.

  3. Optional:Wenn Sie den Anmeldebildschirm von Apple in einer anderen Sprache als Englisch anzeigen möchten, legen Sie den Parameter locale fest. Eine Liste der unterstützten Sprachen finden Sie in der Dokumentation zu „Mit Apple anmelden“.

    Kotlin

    // Localize the Apple authentication screen in French.
    provider.addCustomParameter("locale", "fr")
    

    Java

    // Localize the Apple authentication screen in French.
    provider.addCustomParameter("locale", "fr");
    
  4. Mit Firebase über das OAuth-Anbieterobjekt authentifizieren Im Gegensatz zu anderen FirebaseAuth-Vorgängen wird dabei die Kontrolle über Ihre Benutzeroberfläche übernommen, indem ein benutzerdefinierter Chrome-Tab geöffnet wird. Verweisen Sie daher nicht auf Ihre Aktivität in den Listenern OnSuccessListener und OnFailureListener, die Sie anhängen, da sie sofort getrennt werden, wenn der Vorgang die Benutzeroberfläche startet.

    Prüfen Sie zuerst, ob Sie bereits eine Antwort erhalten haben. Bei der Anmeldung mit dieser Methode wird Ihre Aktivität im Hintergrund ausgeführt, was bedeutet, dass das System sie während des Anmeldevorgangs zurückrufen kann. Damit der Nutzer es nicht noch einmal versuchen muss, sollten Sie prüfen, ob ein Ergebnis bereits vorhanden ist.

    Rufen Sie getPendingAuthResult() auf, um zu prüfen, ob ein Ergebnis aussteht:

    Kotlin

    val pending = auth.pendingAuthResult
    if (pending != null) {
        pending.addOnSuccessListener { authResult ->
            Log.d(TAG, "checkPending:onSuccess:$authResult")
            // Get the user profile with authResult.getUser() and
            // authResult.getAdditionalUserInfo(), and the ID
            // token from Apple with authResult.getCredential().
        }.addOnFailureListener { e ->
            Log.w(TAG, "checkPending:onFailure", e)
        }
    } else {
        Log.d(TAG, "pending: null")
    }
    

    Java

    mAuth = FirebaseAuth.getInstance();
    Task<AuthResult> pending = mAuth.getPendingAuthResult();
    if (pending != null) {
        pending.addOnSuccessListener(new OnSuccessListener<AuthResult>() {
            @Override
            public void onSuccess(AuthResult authResult) {
                Log.d(TAG, "checkPending:onSuccess:" + authResult);
                // Get the user profile with authResult.getUser() and
                // authResult.getAdditionalUserInfo(), and the ID
                // token from Apple with authResult.getCredential().
            }
        }).addOnFailureListener(new OnFailureListener() {
            @Override
            public void onFailure(@NonNull Exception e) {
                Log.w(TAG, "checkPending:onFailure", e);
            }
        });
    } else {
        Log.d(TAG, "pending: null");
    }
    

    Wenn kein Ergebnis vorhanden ist, starten Sie den Anmeldevorgang, indem Sie startActivityForSignInWithProvider() aufrufen:

    Kotlin

    auth.startActivityForSignInWithProvider(this, provider.build())
            .addOnSuccessListener { authResult ->
                // Sign-in successful!
                Log.d(TAG, "activitySignIn:onSuccess:${authResult.user}")
                val user = authResult.user
                // ...
            }
            .addOnFailureListener { e ->
                Log.w(TAG, "activitySignIn:onFailure", e)
            }
    

    Java

    mAuth.startActivityForSignInWithProvider(this, provider.build())
            .addOnSuccessListener(
                    new OnSuccessListener<AuthResult>() {
                        @Override
                        public void onSuccess(AuthResult authResult) {
                            // Sign-in successful!
                            Log.d(TAG, "activitySignIn:onSuccess:" + authResult.getUser());
                            FirebaseUser user = authResult.getUser();
                            // ...
                        }
                    })
            .addOnFailureListener(
                    new OnFailureListener() {
                        @Override
                        public void onFailure(@NonNull Exception e) {
                            Log.w(TAG, "activitySignIn:onFailure", e);
                        }
                    });
    

    Anders als andere von Firebase Auth unterstützte Anbieter stellt Apple keine Foto-URL bereit.

    Wenn der Nutzer seine E‑Mail-Adresse nicht mit der App teilen möchte, stellt Apple eine eindeutige E‑Mail-Adresse für diesen Nutzer bereit (im Format xyz@privaterelay.appleid.com), die an Ihre App weitergegeben wird. Wenn Sie den privaten E‑Mail-Relay-Dienst konfiguriert haben, leitet Apple alle an die anonymisierte Adresse gesendeten E‑Mails an die reale E‑Mail-Adresse des Nutzers weiter.

    Apple gibt Nutzerinformationen wie den Anzeigenamen nur dann an Apps weiter, wenn sich ein Nutzer zum ersten Mal anmeldet. Normalerweise speichert Firebase den Anzeigenamen, wenn sich ein Nutzer zum ersten Mal mit Apple anmeldet. Sie können ihn mit getCurrentUser().getDisplayName() abrufen. Wenn Sie Apple jedoch zuvor verwendet haben, um einen Nutzer ohne Firebase in der App anzumelden, stellt Apple Firebase den Anzeigenamen des Nutzers nicht zur Verfügung.

Reauthentifizierung und Kontoverknüpfung

Dasselbe Muster kann mit startActivityForReauthenticateWithProvider() verwendet werden, um ein neues Anmeldedatenpaar für vertrauliche Vorgänge abzurufen, für die eine aktuelle Anmeldung erforderlich ist:

Kotlin

// The user is already signed-in.
val firebaseUser = auth.getCurrentUser()

firebaseUser
    .startActivityForReauthenticateWithProvider(/* activity= */ this, provider.build())
    .addOnSuccessListener( authResult -> {
        // User is re-authenticated with fresh tokens and
        // should be able to perform sensitive operations
        // like account deletion and email or password
        // update.
    })
    .addOnFailureListener( e -> {
        // Handle failure.
    })

Java

// The user is already signed-in.
FirebaseUser firebaseUser = mAuth.getCurrentUser();

firebaseUser
    .startActivityForReauthenticateWithProvider(/* activity= */ this, provider.build())
    .addOnSuccessListener(
        new OnSuccessListener<AuthResult>() {
          @Override
          public void onSuccess(AuthResult authResult) {
            // User is re-authenticated with fresh tokens and
            // should be able to perform sensitive operations
            // like account deletion and email or password
            // update.
          }
        })
    .addOnFailureListener(
        new OnFailureListener() {
          @Override
          public void onFailure(@NonNull Exception e) {
            // Handle failure.
          }
        });

Mit linkWithCredential() können Sie verschiedene Identitätsanbieter mit bestehenden Konten verknüpfen.

Hinweis: Apple setzt voraus, dass Sie die ausdrückliche Einwilligung der Nutzer einholen, bevor Sie ihre Apple-Konten mit anderen Daten verknüpfen.

Wenn Sie beispielsweise ein Facebook-Konto mit dem aktuellen Firebase-Konto verknüpfen möchten, verwenden Sie das Zugriffstoken, das Sie beim Anmelden des Nutzers bei Facebook erhalten haben:

Kotlin

// Initialize a Facebook credential with a Facebook access token.
val credential = FacebookAuthProvider.getCredential(token.getToken())

// Assuming the current user is an Apple user linking a Facebook provider.
mAuth.getCurrentUser().linkWithCredential(credential)
    .addOnCompleteListener(this, task -> {
        if (task.isSuccessful()) {
          // Facebook credential is linked to the current Apple user.
          // The user can now sign in to the same account
          // with either Apple or Facebook.
        }
      });

Java

// Initialize a Facebook credential with a Facebook access token.
AuthCredential credential = FacebookAuthProvider.getCredential(token.getToken());

// Assuming the current user is an Apple user linking a Facebook provider.
mAuth.getCurrentUser().linkWithCredential(credential)
    .addOnCompleteListener(this, new OnCompleteListener<AuthResult>() {
      @Override
      public void onComplete(@NonNull Task<AuthResult> task) {
        if (task.isSuccessful()) {
          // Facebook credential is linked to the current Apple user.
          // The user can now sign in to the same account
          // with either Apple or Facebook.
        }
      }
    });

Fortgeschrittene Nutzer: Anmeldevorgang manuell verarbeiten

Sie können sich auch mit einem Apple-Konto bei Firebase authentifizieren. Dazu müssen Sie den Anmeldevorgang entweder mit dem Apple Sign-In JS SDK, durch manuelles Erstellen des OAuth-Ablaufs oder mit einer OAuth-Bibliothek wie AppAuth verarbeiten.

  1. Generieren Sie für jede Anmeldeanfrage einen zufälligen String – "Nonce", mit dem Sie prüfen, ob das ID-Token, das Sie erhalten, speziell als Antwort auf die Authentifizierungsanfrage der Anwendung gewährt wurde. Dieser Schritt ist wichtig, um Wiederholungsversuche zu verhindern.

    Mit SecureRandom können Sie eine kryptografisch sichere Nonce auf Android generieren, wie im folgenden Beispiel gezeigt:

    Kotlin

    private fun generateNonce(length: Int): String {
        val generator = SecureRandom()
    
        val charsetDecoder = StandardCharsets.US_ASCII.newDecoder()
        charsetDecoder.onUnmappableCharacter(CodingErrorAction.IGNORE)
        charsetDecoder.onMalformedInput(CodingErrorAction.IGNORE)
    
        val bytes = ByteArray(length)
        val inBuffer = ByteBuffer.wrap(bytes)
        val outBuffer = CharBuffer.allocate(length)
        while (outBuffer.hasRemaining()) {
            generator.nextBytes(bytes)
            inBuffer.rewind()
            charsetDecoder.reset()
            charsetDecoder.decode(inBuffer, outBuffer, false)
        }
        outBuffer.flip()
        return outBuffer.toString()
    }
    

    Java

    private String generateNonce(int length) {
        SecureRandom generator = new SecureRandom();
    
        CharsetDecoder charsetDecoder = StandardCharsets.US_ASCII.newDecoder();
        charsetDecoder.onUnmappableCharacter(CodingErrorAction.IGNORE);
        charsetDecoder.onMalformedInput(CodingErrorAction.IGNORE);
    
        byte[] bytes = new byte[length];
        ByteBuffer inBuffer = ByteBuffer.wrap(bytes);
        CharBuffer outBuffer = CharBuffer.allocate(length);
        while (outBuffer.hasRemaining()) {
            generator.nextBytes(bytes);
            inBuffer.rewind();
            charsetDecoder.reset();
            charsetDecoder.decode(inBuffer, outBuffer, false);
        }
        outBuffer.flip();
        return outBuffer.toString();
    }
    

    Rufen Sie dann den SHA256-Hash der Nonce als Hexadezimalstring ab:

    Kotlin

    private fun sha256(s: String): String {
        val md = MessageDigest.getInstance("SHA-256")
        val digest = md.digest(s.toByteArray())
        val hash = StringBuilder()
        for (c in digest) {
            hash.append(String.format("%02x", c))
        }
        return hash.toString()
    }
    

    Java

    private String sha256(String s) throws NoSuchAlgorithmException {
        MessageDigest md = MessageDigest.getInstance("SHA-256");
        byte[] digest = md.digest(s.getBytes());
        StringBuilder hash = new StringBuilder();
        for (byte c: digest) {
            hash.append(String.format("%02x", c));
        }
        return hash.toString();
    }
    

    Sie senden den SHA256-Hash der Nonce mit Ihrer Anmeldeanfrage, die Apple in der Antwort unverändert übergibt. Firebase validiert die Antwort, indem die ursprüngliche Nonce gehasht und mit dem von Apple übergebenen Wert verglichen wird.

  2. Starten Sie den Anmeldevorgang von Apple mit Ihrer OAuth-Bibliothek oder einer anderen Methode. Achten Sie darauf, die gehashte Nonce als Parameter in Ihre Anfrage aufzunehmen.

  3. Nachdem Sie die Antwort von Apple erhalten haben, rufen Sie das ID-Token aus der Antwort ab und verwenden Sie es zusammen mit dem nicht gehashten Nonce, um ein AuthCredential zu erstellen:

    Kotlin

    val credential =  OAuthProvider.newCredentialBuilder("apple.com")
        .setIdTokenWithRawNonce(appleIdToken, rawUnhashedNonce)
        .build()
    

    Java

    AuthCredential credential =  OAuthProvider.newCredentialBuilder("apple.com")
        .setIdTokenWithRawNonce(appleIdToken, rawUnhashedNonce)
        .build();
    
  4. Mit dem Firebase-Anmeldedaten authentifizieren Sie sich bei Firebase:

    Kotlin

    auth.signInWithCredential(credential)
          .addOnCompleteListener(this) { task ->
              if (task.isSuccessful) {
                // User successfully signed in with Apple ID token.
                // ...
              }
          }
    

    Java

    mAuth.signInWithCredential(credential)
        .addOnCompleteListener(this, new OnCompleteListener<AuthResult>() {
          @Override
          public void onComplete(@NonNull Task<AuthResult> task) {
            if (task.isSuccessful()) {
              // User successfully signed in with Apple ID token.
              // ...
            }
          }
        });
    

Wenn der Aufruf von signInWithCredential erfolgreich ist, können Sie mit der Methode getCurrentUser die Kontodaten des Nutzers abrufen.

Token-Widerruf

Apple verlangt, dass Nutzer in Apps, in denen Konten erstellt werden können, das Löschen ihres Kontos innerhalb der App initiieren können. Dies wird in den App Store Review Guidelines beschrieben.

Außerdem sollten Apps, die „Mit Apple anmelden“ unterstützen, die REST API „Mit Apple anmelden“ verwenden, um Nutzer-Tokens zu widerrufen.

Führen Sie dazu die folgenden Schritte aus:

  1. Verwenden Sie die Methode startActivityForSignInWithProvider(), um sich über Apple anzumelden und AuthResult abzurufen.

  2. Rufen Sie das Zugriffstoken für den Apple-Anbieter ab.

    Kotlin

    val oauthCredential: OAuthCredential =  authResult.credential
    val accessToken = oauthCredential.accessToken
    

    Java

    OAuthCredential oauthCredential = (OAuthCredential) authResult.getCredential();
    String accessToken = oauthCredential.getAccessToken();
    
  3. Widerrufen Sie das Token mit der revokeAccessToken API.

    Kotlin

    mAuth.revokeAccessToken(accessToken)
      .addOnCompleteListener(this) { task ->
        if (task.isSuccessful) {
          // Access token successfully revoked
          // for the user ...
        }
    }
    

    Java

    mAuth.revokeAccessToken(accessToken)
        .addOnCompleteListener(this, new OnCompleteListener<Void>() {
            @Override
            public void onComplete(@NonNull Task<Void> task) {
              if (task.isSuccessful()) {
                // Access token successfully revoked
                // for the user ...
              }
            }
      });
    
  1. Löschen Sie das Nutzerkonto (und alle zugehörigen Daten).

    Nächste Schritte

    Wenn sich ein Nutzer zum ersten Mal anmeldet, wird ein neues Nutzerkonto erstellt und mit den Anmeldedaten verknüpft, mit denen sich der Nutzer angemeldet hat, also mit dem Nutzernamen und Passwort, der Telefonnummer oder den Informationen des Authentifizierungsanbieters. Dieses neue Konto wird als Teil Ihres Firebase-Projekts gespeichert und kann verwendet werden, um einen Nutzer in allen Apps Ihres Projekts zu identifizieren, unabhängig davon, wie sich der Nutzer anmeldet.

    • In Ihren Apps können Sie die grundlegenden Profilinformationen des Nutzers aus dem FirebaseUser-Objekt abrufen. Weitere Informationen finden Sie unter Nutzer verwalten.

    • In Ihren Firebase Realtime Database- und Cloud Storage-Sicherheitsregeln können Sie die eindeutige Nutzer-ID des angemeldeten Nutzers aus der Variablen auth abrufen und damit steuern, auf welche Daten ein Nutzer zugreifen kann.

    Sie können Nutzern erlauben, sich mit mehreren Authentifizierungsanbietern in Ihrer App anzumelden, indem Sie Anmeldedaten des Authentifizierungsanbieters mit einem vorhandenen Nutzerkonto verknüpfen.

    Rufen Sie signOut auf, um einen Nutzer abzumelden:

    Kotlin

    Firebase.auth.signOut()

    Java

    FirebaseAuth.getInstance().signOut();