Sie können Ihren Nutzern die Authentifizierung mit Firebase über ihre Apple-ID ermöglichen. Verwenden Sie dazu das Firebase SDK, um den OAuth 2.0-Anmeldevorgang von Anfang bis Ende auszuführen.
Hinweis
Wenn sich Nutzer über Apple anmelden sollen, konfigurieren Sie zuerst „Mit Apple anmelden“ auf der Apple-Entwicklerwebsite und aktivieren Sie dann Apple als Anmeldeanbieter für Ihr Firebase-Projekt.
Am Apple Developer Program teilnehmen
„Mit Apple anmelden“ kann nur von Mitgliedern des Apple Developer Program konfiguriert werden.
„Mit Apple anmelden“ konfigurieren
- Aktivieren Sie „Mit Apple anmelden“ für Ihre App auf der Certificates, Identifiers & Profiles Seite der Apple-Entwicklerwebsite.
- 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 Rückgabe-URL, wenn Sie dazu aufgefordert werden:
Ihre Firebase-Projekt-ID finden Sie auf der Firebase Console-Einstellungsseite. Notieren Sie sich die neue Dienst-ID. Sie benötigen sie im nächsten Abschnitt.https://YOUR_FIREBASE_PROJECT_ID.firebaseapp.com/__/auth/handler
- Erstellen Sie einen privaten Schlüssel für „Mit Apple anmelden“. Sie benötigen den neuen privaten Schlüssel und die Schlüssel-ID im nächsten Abschnitt.
- Wenn Sie Funktionen von Firebase Authentication, mit denen E‑Mails an Nutzer gesendet werden, verwenden,
z. B. die Anmeldung per E‑Mail-Link, die Bestätigung der E‑Mail-Adresse oder den Widerruf von Kontoänderungen, konfigurieren Sie den privaten E‑Mail-Relay-Dienst von Apple
und registrieren Sie
noreply@YOUR_FIREBASE_PROJECT_ID.firebaseapp.com(oder die Domain Ihrer benutzerdefinierten E‑Mail-Vorlage). So kann Apple E‑Mails, die von Firebase Authentication gesendet werden, an anonymisierte Apple-E‑Mail-Adressen weiterleiten.
Apple als Anmeldeanbieter aktivieren
- Fügen Sie Ihrem Apple-Projekt Firebase hinzu. Registrieren Sie die Bundle-ID Ihrer App, wenn Sie Ihre App in der Firebase Console einrichten.
- Öffnen Sie in der Firebase Konsole den Bereich Auth. Aktivieren Sie auf dem Tab Anmeldemethode den Anbieter Apple. Geben Sie die Dienst-ID an, die Sie im vorherigen Abschnitt erstellt haben. Geben Sie im Bereich OAuth-Codeablaufkonfiguration außerdem 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“ können Nutzer ihre Daten, einschließlich ihrer E‑Mail-Adresse, bei der Anmeldung 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 geltenden Entwicklerrichtlinien oder ‑bedingungen von Apple bezüglich dieser anonymisierten Apple-IDs einhalten.
Dazu gehört, dass Sie die erforderliche Einwilligung des Nutzers einholen müssen, bevor Sie direkt identifizierbare personenbezogene Daten mit einer anonymisierten Apple-ID verknüpfen. Bei der Verwendung von Firebase Authentication können folgende Aktionen erforderlich sein:
- Eine E‑Mail-Adresse mit einer anonymisierten Apple-ID verknüpfen und umgekehrt
- Eine Telefonnummer mit einer anonymisierten Apple-ID verknüpfen und umgekehrt
- Nicht anonyme Anmeldedaten für soziale Medien (z. B. Facebook oder Google) mit einer anonymisierten Apple-ID verknüpfen und umgekehrt
Die obige Liste ist nicht vollständig. In der Lizenzvereinbarung des Apple Developer Program im Bereich „Membership“ (Mitgliedschaft) Ihres Entwicklerkontos finden Sie weitere Informationen zu den Anforderungen von Apple an Ihre App.
Mit Apple anmelden und mit Firebase authentifizieren
Wenn Sie sich mit einem Apple-Konto authentifizieren möchten, melden Sie den Nutzer zuerst mit dem AuthenticationServices Framework von Apple in seinem Apple
Konto an. Verwenden Sie dann das ID-Token aus der Antwort von Apple, um ein Firebase
AuthCredential Objekt zu erstellen:
Generieren Sie für jede Anmeldeanfrage einen zufälligen String – eine „Nonce“. Damit prüfen Sie, 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
SecRandomCopyBytes(_:_:_)können Sie eine kryptografisch sichere Nonce generieren, wie im folgenden Beispiel gezeigt:Swift
private func randomNonceString(length: Int = 32) -> String { precondition(length > 0) var randomBytes = [UInt8](repeating: 0, count: length) let errorCode = SecRandomCopyBytes(kSecRandomDefault, randomBytes.count, &randomBytes) if errorCode != errSecSuccess { fatalError( "Unable to generate nonce. SecRandomCopyBytes failed with OSStatus \(errorCode)" ) } let charset: [Character] = Array("0123456789ABCDEFGHIJKLMNOPQRSTUVXYZabcdefghijklmnopqrstuvwxyz-._") let nonce = randomBytes.map { byte in // Pick a random character from the set, wrapping around if needed. charset[Int(byte) % charset.count] } return String(nonce) }
Objective-C
// Adapted from https://auth0.com/docs/api-auth/tutorials/nonce#generate-a-cryptographically-random-nonce - (NSString *)randomNonce:(NSInteger)length { NSAssert(length > 0, @"Expected nonce to have positive length"); NSString *characterSet = @"0123456789ABCDEFGHIJKLMNOPQRSTUVXYZabcdefghijklmnopqrstuvwxyz-._"; NSMutableString *result = [NSMutableString string]; NSInteger remainingLength = length; while (remainingLength > 0) { NSMutableArray *randoms = [NSMutableArray arrayWithCapacity:16]; for (NSInteger i = 0; i < 16; i++) { uint8_t random = 0; int errorCode = SecRandomCopyBytes(kSecRandomDefault, 1, &random); NSAssert(errorCode == errSecSuccess, @"Unable to generate nonce: OSStatus %i", errorCode); [randoms addObject:@(random)]; } for (NSNumber *random in randoms) { if (remainingLength == 0) { break; } if (random.unsignedIntValue < characterSet.length) { unichar character = [characterSet characterAtIndex:random.unsignedIntValue]; [result appendFormat:@"%C", character]; remainingLength--; } } } return [result copy]; }
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.
Swift
@available(iOS 13, *) private func sha256(_ input: String) -> String { let inputData = Data(input.utf8) let hashedData = SHA256.hash(data: inputData) let hashString = hashedData.compactMap { String(format: "%02x", $0) }.joined() return hashString }
Objective-C
- (NSString *)stringBySha256HashingString:(NSString *)input { const char *string = [input UTF8String]; unsigned char result[CC_SHA256_DIGEST_LENGTH]; CC_SHA256(string, (CC_LONG)strlen(string), result); NSMutableString *hashed = [NSMutableString stringWithCapacity:CC_SHA256_DIGEST_LENGTH * 2]; for (NSInteger i = 0; i < CC_SHA256_DIGEST_LENGTH; i++) { [hashed appendFormat:@"%02x", result[i]]; } return hashed; }
Starten Sie den Anmeldevorgang von Apple. Fügen Sie in Ihre Anfrage den SHA256-Hash der Nonce und die Delegate-Klasse ein, die die Antwort von Apple verarbeitet (siehe nächsten Schritt):
Swift
import CryptoKit // Unhashed nonce. fileprivate var currentNonce: String? @available(iOS 13, *) func startSignInWithAppleFlow() { let nonce = randomNonceString() currentNonce = nonce let appleIDProvider = ASAuthorizationAppleIDProvider() let request = appleIDProvider.createRequest() request.requestedScopes = [.fullName, .email] request.nonce = sha256(nonce) let authorizationController = ASAuthorizationController(authorizationRequests: [request]) authorizationController.delegate = self authorizationController.presentationContextProvider = self authorizationController.performRequests() }Objective-C
@import CommonCrypto; - (void)startSignInWithAppleFlow { NSString *nonce = [self randomNonce:32]; self.currentNonce = nonce; ASAuthorizationAppleIDProvider *appleIDProvider = [[ASAuthorizationAppleIDProvider alloc] init]; ASAuthorizationAppleIDRequest *request = [appleIDProvider createRequest]; request.requestedScopes = @[ASAuthorizationScopeFullName, ASAuthorizationScopeEmail]; request.nonce = [self stringBySha256HashingString:nonce]; ASAuthorizationController *authorizationController = [[ASAuthorizationController alloc] initWithAuthorizationRequests:@[request]]; authorizationController.delegate = self; authorizationController.presentationContextProvider = self; [authorizationController performRequests]; }Verarbeiten Sie die Antwort von Apple in Ihrer Implementierung von
ASAuthorizationControllerDelegate. Wenn die Anmeldung erfolgreich war, verwenden Sie das ID-Token aus der Antwort von Apple mit der nicht gehashten Nonce zur Authentifizierung bei Firebase:Swift
@available(iOS 13.0, *) extension MainViewController: ASAuthorizationControllerDelegate { func authorizationController(controller: ASAuthorizationController, didCompleteWithAuthorization authorization: ASAuthorization) { if let appleIDCredential = authorization.credential as? ASAuthorizationAppleIDCredential { guard let nonce = currentNonce else { fatalError("Invalid state: A login callback was received, but no login request was sent.") } guard let appleIDToken = appleIDCredential.identityToken else { print("Unable to fetch identity token") return } guard let idTokenString = String(data: appleIDToken, encoding: .utf8) else { print("Unable to serialize token string from data: \(appleIDToken.debugDescription)") return } // Initialize a Firebase credential, including the user's full name. let credential = OAuthProvider.appleCredential(withIDToken: idTokenString, rawNonce: nonce, fullName: appleIDCredential.fullName) // Sign in with Firebase. Auth.auth().signIn(with: credential) { (authResult, error) in if error { // Error. If error.code == .MissingOrInvalidNonce, make sure // you're sending the SHA256-hashed nonce as a hex string with // your request to Apple. print(error.localizedDescription) return } // User is signed in to Firebase with Apple. // ... } } } func authorizationController(controller: ASAuthorizationController, didCompleteWithError error: Error) { // Handle error. print("Sign in with Apple errored: \(error)") } }Objective-C
- (void)authorizationController:(ASAuthorizationController *)controller didCompleteWithAuthorization:(ASAuthorization *)authorization API_AVAILABLE(ios(13.0)) { if ([authorization.credential isKindOfClass:[ASAuthorizationAppleIDCredential class]]) { ASAuthorizationAppleIDCredential *appleIDCredential = authorization.credential; NSString *rawNonce = self.currentNonce; NSAssert(rawNonce != nil, @"Invalid state: A login callback was received, but no login request was sent."); if (appleIDCredential.identityToken == nil) { NSLog(@"Unable to fetch identity token."); return; } NSString *idToken = [[NSString alloc] initWithData:appleIDCredential.identityToken encoding:NSUTF8StringEncoding]; if (idToken == nil) { NSLog(@"Unable to serialize id token from data: %@", appleIDCredential.identityToken); } // Initialize a Firebase credential, including the user's full name. FIROAuthCredential *credential = [FIROAuthProvider appleCredentialWithIDToken:IDToken rawNonce:self.appleRawNonce fullName:appleIDCredential.fullName]; // Sign in with Firebase. [[FIRAuth auth] signInWithCredential:credential completion:^(FIRAuthDataResult * _Nullable authResult, NSError * _Nullable error) { if (error != nil) { // Error. If error.code == FIRAuthErrorCodeMissingOrInvalidNonce, // make sure you're sending the SHA256-hashed nonce as a hex string // with your request to Apple. return; } // Sign-in succeeded! }]; } } - (void)authorizationController:(ASAuthorizationController *)controller didCompleteWithError:(NSError *)error API_AVAILABLE(ios(13.0)) { NSLog(@"Sign in with Apple errored: %@", error); }
Anders als andere von Firebase Auth unterstützte Anbieter stellt Apple keine Foto-URL bereit.
Wenn der Nutzer außerdem nicht möchte, dass seine E‑Mail-Adresse für die App freigegeben wird, stellt Apple eine eindeutige E‑Mail-Adresse für diesen Nutzer bereit (im Format xyz@privaterelay.appleid.com), die für Ihre App freigegeben 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.
Neu authentifizieren und Konten verknüpfen
Dasselbe Muster kann mit reauthenticateWithCredential() verwendet werden. Damit können Sie neue Anmeldedaten für vertrauliche Vorgänge abrufen, für die eine aktuelle Anmeldung erforderlich ist:
Swift
// Initialize a fresh Apple credential with Firebase.
let credential = OAuthProvider.credential(
withProviderID: "apple.com",
IDToken: appleIdToken,
rawNonce: rawNonce
)
// Reauthenticate current Apple user with fresh Apple credential.
Auth.auth().currentUser.reauthenticate(with: credential) { (authResult, error) in
guard error != nil else { return }
// Apple user successfully re-authenticated.
// ...
}
Objective-C
FIRAuthCredential *credential = [FIROAuthProvider credentialWithProviderID:@"apple.com",
IDToken:appleIdToken,
rawNonce:rawNonce];
[[FIRAuth auth].currentUser
reauthenticateWithCredential:credential
completion:^(FIRAuthDataResult * _Nullable authResult,
NSError * _Nullable error) {
if (error) {
// Handle error.
}
// Apple user successfully re-authenticated.
// ...
}];
Mit linkWithCredential() können Sie verschiedene Identitätsanbieter mit bestehenden Konten verknüpfen.
Apple setzt voraus, dass Sie die ausdrückliche Einwilligung der Nutzer einholen, bevor Sie ihre Apple-Konten mit anderen Daten verknüpfen.
Mit „Mit Apple anmelden“ können Sie keine Anmeldedaten wiederverwenden, um eine Verknüpfung mit einem bestehenden Konto herzustellen. Wenn Sie Anmeldedaten von „Mit Apple anmelden“ mit einem anderen Konto verknüpfen möchten, müssen Sie zuerst versuchen, die Konten mit den alten Anmeldedaten von „Mit Apple anmelden“ zu verknüpfen. Untersuchen Sie dann den zurückgegebenen Fehler, um neue Anmeldedaten zu finden.
Die neuen Anmeldedaten befinden sich im userInfo-Wörterbuch des Fehlers und können über den Schlüssel AuthErrorUserInfoUpdatedCredentialKey aufgerufen werden.
Wenn Sie beispielsweise ein Facebook-Konto mit dem aktuellen Firebase-Konto verknüpfen möchten, verwenden Sie das Zugriffstoken, das Sie bei der Anmeldung des Nutzers bei Facebook erhalten haben:
Swift
// Initialize a Facebook credential with Firebase.
let credential = FacebookAuthProvider.credential(
withAccessToken: AccessToken.current!.tokenString
)
// Assuming the current user is an Apple user linking a Facebook provider.
Auth.auth().currentUser.link(with: credential) { (authResult, error) in
// Facebook credential is linked to the current Apple user.
// The user can now sign in with Facebook or Apple to the same Firebase
// account.
// ...
}
Objective-C
// Initialize a Facebook credential with Firebase.
FacebookAuthCredential *credential = [FIRFacebookAuthProvider credentialWithAccessToken:accessToken];
// Assuming the current user is an Apple user linking a Facebook provider.
[FIRAuth.auth linkWithCredential:credential completion:^(FIRAuthDataResult * _Nullable authResult, NSError * _Nullable error) {
// Facebook credential is linked to the current Apple user.
// The user can now sign in with Facebook or Apple to the same Firebase
// account.
// ...
}];
Token widerrufen
Apple setzt voraus, dass Apps, die die Kontoerstellung unterstützen, Nutzern die Möglichkeit bieten, das Löschen ihres Kontos innerhalb der App zu initiieren. Weitere Informationen finden Sie in den App Store-Überprüfungs richtlinien.
So erfüllen Sie diese Anforderung:
Achten Sie darauf, dass Sie die Bereiche Services ID und OAuth-Codeablaufkonfiguration der Konfiguration des Anbieters „Mit Apple anmelden“ ausgefüllt haben, wie im Abschnitt „Mit Apple anmelden“ konfigurieren beschrieben.
Da Firebase keine Nutzertokens speichert, wenn Nutzer mit „Mit Apple anmelden“ erstellt werden, müssen Sie den Nutzer bitten, sich noch einmal anzumelden, bevor Sie sein Token widerrufen und das Konto löschen.
Swift
private var currentNonce: String? private func deleteCurrentUser() { do { let nonce = try CryptoUtils.randomNonceString() currentNonce = nonce let appleIDProvider = ASAuthorizationAppleIDProvider() let request = appleIDProvider.createRequest() request.requestedScopes = [.fullName, .email] request.nonce = CryptoUtils.sha256(nonce) let authorizationController = ASAuthorizationController(authorizationRequests: [request]) authorizationController.delegate = self authorizationController.presentationContextProvider = self authorizationController.performRequests() } catch { // In the unlikely case that nonce generation fails, show error view. displayError(error) } }
Rufen Sie den Autorisierungscode aus
ASAuthorizationAppleIDCredentialab und verwenden Sie ihn, umAuth.auth().revokeToken(withAuthorizationCode:)aufzurufen und die Tokens des Nutzers zu widerrufen.Swift
private var user: User? func authorizationController(controller: ASAuthorizationController, didCompleteWithAuthorization authorization: ASAuthorization) { guard let appleIDCredential = authorization.credential as? ASAuthorizationAppleIDCredential else { print("Unable to retrieve AppleIDCredential") return } guard let _ = currentNonce else { fatalError("Invalid state: A login callback was received, but no login request was sent.") } guard let appleAuthCode = appleIDCredential.authorizationCode else { print("Unable to fetch authorization code") return } guard let authCodeString = String(data: appleAuthCode, encoding: .utf8) else { print("Unable to serialize auth code string from data: \(appleAuthCode.debugDescription)") return } Task { do { try await Auth.auth().revokeToken(withAuthorizationCode: authCodeString) try await user?.delete() self.updateUI() } catch { self.displayError(error) } } }
Löschen Sie schließlich 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, z. B. Nutzername und Passwort, Telefonnummer oder Informationen zum Anmeldeanbieter. 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
User-Objekt abrufen. Weitere Informationen finden Sie unter Nutzer verwalten. In den Firebase Realtime Database und Cloud Storage Sicherheitsregeln können Sie die eindeutige Nutzer-ID des angemeldeten Nutzers aus der Variablen
authabrufen und damit steuern, auf welche Daten ein Nutzer zugreifen kann.
Sie können Nutzern die Anmeldung in Ihrer App mit mehreren Authentifizierungs anbietern ermöglichen, indem Sie Anmeldedaten des Authentifizierungsanbieters mit einem bestehenden Nutzerkonto verknüpfen.
Rufen Sie
signOut: auf, um einen Nutzer abzumelden.
Swift
let firebaseAuth = Auth.auth() do { try firebaseAuth.signOut() } catch let signOutError as NSError { print("Error signing out: %@", signOutError) }
Objective-C
NSError *signOutError; BOOL status = [[FIRAuth auth] signOut:&signOutError]; if (!status) { NSLog(@"Error signing out: %@", signOutError); return; }
Sie können auch Code zur Fehlerbehandlung für alle Authentifizierungs fehler hinzufügen. Weitere Informationen finden Sie unter Fehler behandeln.