Nutzer mit Apple unter iOS anmelden.
In diesem Dokument erfahren Sie, wie Sie mit Identity Platform Über Apple anmelden zu Ihrer iOS-Anwendung hinzufügen.
Hinweis
Erstellen Sie eine iOS-Anwendung, die Identity Platform verwendet.
Nehmen Sie am Apple-Programm für Entwickler teil.
Anwendung mit Apple konfigurieren
Auf der Website für Apple-Entwickler:
Aktivieren Sie die Funktion „Über Apple anmelden“ für Ihre App.
Wenn Sie zum Senden von E-Mails an Ihre Nutzer Identity Platform verwenden, konfigurieren Sie Ihr Projekt mit dem privaten E-Mail-Relay-Dienst von Apple mithilfe der folgenden E-Mail-Adresse:
noreply@project-id.firebaseapp.com
Sie können auch eine benutzerdefinierte E-Mail-Vorlage nutzen, sofern eine solche für Ihre Anwendung vorhanden ist.
Anforderungen von Apple für anonymisierte Daten einhalten
Apple bietet Nutzern die Möglichkeit, ihre Daten, einschließlich ihrer E-Mail-Adresse, zu anonymisieren. Apple weist Nutzern, die diese Option auswählen, eine verschleierte E-Mail-Adresse mit der Domain privaterelay.appleid.com
zu.
Ihre Anwendung muss alle geltenden Entwicklerrichtlinien oder -bedingungen von Apple bezüglich anonymisierter Apple-IDs einhalten. Außerdem muss die Einwilligung des Nutzers eingeholt werden, bevor personenbezogene Daten mit einer anonymisierten Apple-ID verknüpft werden. Beispiele für Aktionen mit personenbezogenen Daten:
- 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 wie Facebook oder Google mit einer anonymisierten Apple-ID verknüpfen und umgekehrt
Weitere Informationen finden Sie in der Lizenzvereinbarung des Apple-Entwicklerprogramms für Ihr Apple-Entwicklerkonto.
Apple als Anbieter konfigurieren
So konfigurieren Sie Apple als Identitätsanbieter:
Rufen Sie in der Google Cloud Console die Seite Identitätsanbieter auf.
Klicken Sie auf Anbieter hinzufügen.
Wählen Sie in der Liste Apple aus.
Wählen Sie unter Plattform die Option iOS aus.
Geben Sie die Bundle-ID Ihrer App ein.
Klicken Sie unter Autorisierte Domains auf Domain hinzufügen, um die Domains Ihrer Anwendung zu registrieren. Für Entwicklungszwecke ist
localhost
bereits standardmäßig aktiviert.Klicken Sie unter Anwendung konfigurieren auf iOS. Kopieren Sie das Snippet in den Code Ihrer Anwendung, um das Identity Platform Client SDK zu initialisieren.
Klicken Sie auf Speichern.
Nutzer mit dem Client SDK anmelden
Melden Sie den Nutzer an und rufen Sie mit dem Authentifizierungsdienste-Framework von Apple ein ID-Token ab.
Erstellen Sie einen als Nonce bezeichneten zufälligen String, indem Sie
SecRandomCopyBytes(_:_:_:)
aufrufen.Die Nonce wird verwendet, um Wiederholungsversuche zu verhindern. Sie fügen den SHA-256-Hash Ihrer Nonce in die Authentifizierungsanfrage ein und Apple gibt ihn unverändert zurück. Identity Platform validiert dann die Antwort, indem der ursprüngliche Hash mit dem von Apple zurückgegebenen Wert verglichen wird.
Starten Sie den Anmeldevorgang von Apple, einschließlich des SHA-256-Hashs des Nonces, den Sie im vorherigen Schritt erstellt haben, und einer Delegate-Klasse zur Verarbeitung der Antwort von Apple:
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() } @available(iOS 13, *) private func sha256(_ input: String) -> String { let inputData = Data(input.utf8) let hashedData = SHA256.hash(data: inputData) let hashString = hashedData.compactMap { return String(format: "%02x", $0) }.joined() return hashString }
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]; } - (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; }
Verarbeiten Sie die Antwort von Apple in Ihrer Implementierung von
ASAuthorizationControllerDelegate
. Wenn die Anmeldung erfolgreich ist, verwenden Sie das ID-Token aus der Antwort von Apple mit dem nicht gehashten Nonce zur Authentifizierung bei Identity Platform: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. let credential = OAuthProvider.credential(withProviderID: "apple.com", IDToken: idTokenString, rawNonce: nonce) // 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. FIROAuthCredential *credential = [FIROAuthProvider credentialWithProviderID:@"apple.com" IDToken:idToken rawNonce:rawNonce]; // 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); }
Im Gegensatz zu vielen anderen Identitätsanbietern stellt Apple keine Foto-URL bereit.
Wenn ein Nutzer seine reale E-Mail-Adresse nicht mit Ihrer Anwendung teilen möchte, stellt Apple eine eindeutige E-Mail-Adresse für diesen Nutzer bereit. Diese E-Mail hat das Format xyz@privaterelay.appleid.com
. 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 Anzeigenamen nur dann an Anwendungen weiter, wenn sich ein Nutzer zum ersten Mal anmeldet. In den meisten Fällen werden diese Daten von Identity Platform gespeichert, damit Sie sie bei zukünftigen Sitzungen mithilfe von firebase.auth().currentUser.displayName
abrufen können. Wenn Sie Nutzern jedoch erlauben, sich mit Apple bei Ihrer Anwendung anzumelden, bevor Sie sie in Identity Platform eingebunden haben, sind keine Nutzerinformationen verfügbar.
Löschen von Nutzerkonten
Apple verlangt, dass iOS-Apps, die die Kontoerstellung unterstützen, Nutzern auch die Möglichkeit bieten, das Löschen ihres Kontos innerhalb der App zu veranlassen.
Wenn Sie ein Nutzerkonto löschen, müssen Sie das Token des Nutzers widerrufen, bevor Sie das Konto und alle Daten löschen, die Sie für ihn in Firestore, Cloud Storage und Firebase Realtime Database gespeichert haben. Weitere Informationen finden Sie in der Entwicklersupportdokumentation von Apple unter Kontolöschung in Ihrer App anbieten.
Da Identity Platform keine Nutzertokens speichert, wenn Nutzer mit der Apple-Anmeldung erstellt werden, müssen Sie den Nutzer bitten, sich anzumelden, bevor Sie sein Token widerrufen und das Konto löschen. Alternativ können Sie den Autorisierungscode speichern, um den Nutzer nicht noch einmal zur Anmeldung aufzufordern, wenn er mit der Apple-Anmeldung angemeldet ist. Dieser Code kann dann bei der Tokenentziehung wiederverwendet werden.
So widerrufen Sie das Token eines Nutzers und löschen sein Konto:
Swift
let user = Auth.auth().currentUser
// Check if the user has a token.
if let providerData = user?.providerData {
for provider in providerData {
guard let provider = provider as? FIRUserInfo else {
continue
}
if provider.providerID() == "apple.com" {
isAppleProviderLinked = true
}
}
}
// Re-authenticate the user and revoke their token
if isAppleProviderLinked {
let request = appleIDRequest(withState: "revokeAppleTokenAndDeleteUser")
let controller = ASAuthorizationController(authorizationRequests: [request])
controller.delegate = self
controller.presentationContextProvider = self
controller.performRequests()
} else {
// Usual user deletion
}
func authorizationController(
controller: ASAuthorizationController,
didCompleteWithAuthorization authorization: ASAuthorization
) {
if authorization.credential is ASAuthorizationAppleIDCredential {
let appleIDCredential = authorization.credential as? ASAuthorizationAppleIDCredential
if authorization.credential is ASAuthorizationAppleIDCredential {
if appleIDCredential.state == "signIn" {
// Sign in with Firebase.
// ...
} else if appleIDCredential.state == "revokeAppleTokenAndDeleteUser" {
// Revoke token with Firebase.
Auth.auth().revokeTokenWithAuthorizationCode(code) { error in
if error != nil {
// Token revocation failed.
} else {
// Token revocation succeeded then delete user again.
let user = Auth.auth().currentUser
user?.delete { error in
// ...
}
}
}
}
}
}
}
Objective-C
FIRUser *user = [FIRAuth auth].currentUser;
// Check if the user has a token.
BOOL isAppleProviderLinked = false;
for (id<FIRUserInfo> provider in user.providerData) {
if ([[provider providerID] isEqual:@"apple.com"]) {
isAppleProviderLinked = true;
}
}
// Re-authenticate the user and revoke their token
if (isAppleProviderLinked) {
if (@available(iOS 13, *)) {
ASAuthorizationAppleIDRequest *request =
[self appleIDRequestWithState:@"revokeAppleTokenAndDeleteUser"];
ASAuthorizationController *controller = [[ASAuthorizationController alloc]
initWithAuthorizationRequests:@[ request ]];
controller.delegate = self;
controller.presentationContextProvider = self;
[controller performRequests];
}
} else {
// Usual user deletion
}
- (void)authorizationController:(ASAuthorizationController *)controller
didCompleteWithAuthorization:(ASAuthorization *)authorization
API_AVAILABLE(ios(13.0)) {
if ([authorization.credential
isKindOfClass:[ASAuthorizationAppleIDCredential class]]) {
ASAuthorizationAppleIDCredential *appleIDCredential =
authorization.credential;
if ([appleIDCredential.state isEqualToString:@"signIn"]) {
// Sign in with Firebase.
// ...
} else if ([appleIDCredential.state
isEqualToString:@"revokeAppleTokenAndDeleteUser"]) {
// Revoke token with Firebase.
NSString *code =
[[NSString alloc] initWithData:appleIDCredential.authorizationCode
encoding:NSUTF8StringEncoding];
[[FIRAuth auth]
revokeTokenWithAuthorizationCode:code
completion:^(NSError *_Nullable error) {
if (error != nil) {
// Token revocation failed.
} else {
// Token revocation succeeded then delete
// user again.
FIRUser *user = [FIRAuth auth].currentUser;
[user deleteWithCompletion:^(
NSError *_Nullable error){
// ...
}];
}
}];
}
}
}
Nächste Schritte
- Weitere Informationen zu Identity Platform-Nutzern
- Nutzer mit anderen Identitätsanbietern anmelden