Uçtan uca OAuth 2.0 oturum açma akışını gerçekleştirmek için Firebase SDK'yı kullanarak kullanıcılarınızın Apple Kimliklerini kullanarak Firebase ile kimlik doğrulaması yapmasına izin verebilirsiniz.
Sen başlamadan önce
Apple kullanarak kullanıcıların oturum açmasını sağlamak için önce Apple'ın geliştirici sitesinde Apple ile Giriş Yap'ı yapılandırın, ardından Apple'ı Firebase projeniz için bir oturum açma sağlayıcısı olarak etkinleştirin.
Apple Geliştirici Programına Katılın
Apple ile Giriş Yap, yalnızca Apple Developer Program üyeleri tarafından yapılandırılabilir.
Apple ile Oturum Açmayı Yapılandırın
- Apple'ın geliştirici sitesindeki Sertifikalar, Tanımlayıcılar ve Profiller sayfasında uygulamanız için Apple ile Oturum Açmayı etkinleştirin.
- Web için Apple ile Oturum Açmayı Yapılandırma'nın ilk bölümünde açıklandığı gibi web sitenizi uygulamanızla ilişkilendirin. İstendiğinde, aşağıdaki URL'yi Dönüş URL'si olarak kaydedin:
https://YOUR_FIREBASE_PROJECT_ID.firebaseapp.com/__/auth/handler
Firebase proje kimliğinizi Firebase konsol ayarları sayfasından alabilirsiniz. İşiniz bittiğinde, bir sonraki bölümde ihtiyaç duyacağınız yeni Hizmet Kimliğinizi not edin. - Apple özel anahtarıyla Oturum Açma oluşturun . Bir sonraki bölümde yeni özel anahtarınıza ve anahtar kimliğinize ihtiyacınız olacak.
- E-posta bağlantısı oturum açma, e-posta adresi doğrulama, hesap değişikliği iptali ve diğerleri dahil olmak üzere Firebase Authentication'ın kullanıcılara e-posta gönderen özelliklerinden herhangi birini kullanıyorsanız, Apple özel e-posta geçiş hizmetini yapılandırın ve
noreply@ YOUR_FIREBASE_PROJECT_ID .firebaseapp.com
(veya özelleştirilmiş e-posta şablonu etki alanınız), böylece Apple, Firebase Authentication tarafından gönderilen e-postaları anonimleştirilmiş Apple e-posta adreslerine aktarabilir.
Oturum açma sağlayıcısı olarak Apple'ı etkinleştirin
- Firebase'i Apple projenize ekleyin . Uygulamanızı Firebase konsolunda ayarlarken uygulamanızın paket kimliğini kaydettiğinizden emin olun.
- Firebase konsolunda Kimlik Doğrulama bölümünü açın. Oturum açma yöntemi sekmesinde, Apple sağlayıcısını etkinleştirin. Önceki bölümde oluşturduğunuz Hizmet Kimliğini belirtin. Ayrıca, OAuth kod akışı yapılandırması bölümünde , Apple Ekip Kimliğinizi ve önceki bölümde oluşturduğunuz özel anahtarı ve anahtar kimliğini belirtin.
Apple anonimleştirilmiş veri gereksinimlerine uyun
Apple ile Giriş Yap, kullanıcılara oturum açarken e-posta adresleri dahil olmak üzere verilerini anonimleştirme seçeneği sunar. Bu seçeneği tercih eden kullanıcıların e-posta adresleri privaterelay.appleid.com
etki alanına sahiptir. Uygulamanızda Apple ile Giriş Yap'ı kullandığınızda, bu anonimleştirilmiş Apple Kimlikleri ile ilgili Apple'ın geçerli tüm geliştirici politikalarına veya koşullarına uymalısınız.
Bu, doğrudan tanımlayıcı herhangi bir kişisel bilgiyi anonimleştirilmiş bir Apple Kimliği ile ilişkilendirmeden önce gerekli tüm kullanıcı onayını almayı içerir. Firebase Authentication kullanılırken bu, aşağıdaki eylemleri içerebilir:
- Bir e-posta adresini anonimleştirilmiş bir Apple kimliğine bağlayın veya tam tersini yapın.
- Bir telefon numarasını anonimleştirilmiş bir Apple kimliğine bağlama veya tam tersi
- Anonim olmayan bir sosyal kimlik bilgisini (Facebook, Google vb.) anonimleştirilmiş bir Apple Kimliğine bağlayın veya tam tersini yapın.
Yukarıdaki liste ayrıntılı değildir. Uygulamanızın Apple gereksinimlerini karşıladığından emin olmak için geliştirici hesabınızın Üyelik bölümündeki Apple Geliştirici Programı Lisans Sözleşmesine bakın.
Apple ile oturum açın ve Firebase ile kimlik doğrulaması yapın
Bir Apple hesabıyla kimlik doğrulaması yapmak için önce Apple'ın AuthenticationServices
çerçevesini kullanarak kullanıcının Apple hesabında oturum açın ve ardından bir Firebase AuthCredential
nesnesi oluşturmak için Apple'ın yanıtındaki kimlik belirtecini kullanın:
Her oturum açma isteği için, aldığınız kimlik belirtecinin özellikle uygulamanızın kimlik doğrulama isteğine yanıt olarak verildiğinden emin olmak için kullanacağınız rastgele bir dize (bir "nonce") oluşturun. Bu adım, tekrar saldırılarını önlemek için önemlidir.
Aşağıdaki örnekte olduğu gibi
SecRandomCopyBytes(_:_:_)
ile kriptografik olarak güvenli bir nonce oluşturabilirsiniz:Süratli
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) }
Amaç-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]; }
Apple'ın yanıtta değiştirmeden ileteceği oturum açma isteğinizle nonce'nin SHA256 hash'ini göndereceksiniz. Firebase, orijinal nonce değerini hashleyerek ve bunu Apple tarafından iletilen değerle karşılaştırarak yanıtı doğrular.
Süratli
@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 }
Amaç-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; }
Apple'ın oturum açma akışını başlatın, isteğinizde nonce'nin SHA256 hash'i ve Apple'ın yanıtını işleyecek delege sınıfı dahil (sonraki adıma bakın):
Süratli
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() }
Amaç-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]; }
ASAuthorizationControllerDelegate
uygulamanızda Apple'ın yanıtını işleyin. Oturum açma başarılı olduysa, Firebase ile kimlik doğrulaması yapmak için Apple'ın yanıtındaki kimlik belirtecini karma yapılmamış nonce ile kullanın:Süratli
@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)") } }
Amaç-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); }
Firebase Auth tarafından desteklenen diğer sağlayıcıların aksine, Apple bir fotoğraf URL'si sağlamaz.
Ayrıca, kullanıcı e-postasını uygulamayla paylaşmamayı seçtiğinde, Apple söz konusu kullanıcı için uygulamanızla paylaştığı benzersiz bir e-posta adresi ( xyz@privaterelay.appleid.com
biçiminde) sağlar. Özel e-posta geçiş hizmetini yapılandırdıysanız Apple, anonimleştirilmiş adrese gönderilen e-postaları kullanıcının gerçek e-posta adresine iletir.
Yeniden kimlik doğrulama ve hesap bağlama
Aynı model, yakın zamanda oturum açmayı gerektiren hassas işlemler için yeni bir kimlik bilgisi almak için kullanabileceğiniz reauthenticateWithCredential()
ile kullanılabilir:
Süratli
// 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.
// ...
}
Amaç-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.
// ...
}];
Ayrıca, farklı kimlik sağlayıcıları mevcut hesaplara bağlamak için linkWithCredential()
kullanabilirsiniz.
Apple hesaplarını başka verilere bağlamadan önce Apple'ın kullanıcılardan açık onay almanızı gerektirdiğini unutmayın.
Apple ile oturum açın, mevcut bir hesaba bağlanmak için bir kimlik doğrulama bilgisini yeniden kullanmanıza izin vermez. Bir Apple ile Giriş Yap kimlik bilgisini başka bir hesaba bağlamak istiyorsanız, önce eski Apple ile Giriş Yap kimlik bilgilerini kullanan hesapları bağlamayı denemeli ve ardından yeni bir kimlik bilgisi bulmak için döndürülen hatayı incelemelisiniz. Yeni kimlik bilgisi, hatanın userInfo
sözlüğünde bulunur ve AuthErrorUserInfoUpdatedCredentialKey
anahtarı aracılığıyla erişilebilir.
Örneğin, bir Facebook hesabını mevcut Firebase hesabına bağlamak için, kullanıcıyı Facebook'ta oturum açarken elde ettiğiniz erişim jetonunu kullanın:
Süratli
// 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.
// ...
}
Amaç-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.
// ...
}];
Jeton iptali
Apple, hesap oluşturmayı destekleyen uygulamaların , App Store İnceleme Yönergelerinde açıklandığı gibi, kullanıcıların uygulama içinde hesaplarını silmeye başlamasına izin vermesini zorunlu kılar.
Bu gereksinimi karşılamak için aşağıdaki adımları uygulayın:
Apple ile Oturum Açma sağlayıcı yapılandırmasının Hizmet Kimliği ve OAuth kodu akışı yapılandırma bölümünü, Apple ile Oturum Açmayı Yapılandır bölümünde belirtildiği gibi doldurduğunuzdan emin olun.
Kullanıcılar Apple ile Giriş Yap ile oluşturulduğunda Firebase kullanıcı belirteçlerini saklamadığından, belirtecini iptal etmeden ve hesabı silmeden önce kullanıcıdan tekrar oturum açmasını istemeniz gerekir.
Süratli
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) } }
ASAuthorizationAppleIDCredential
yetkilendirme kodunu alın ve kullanıcının belirteçlerini iptal etmek içinAuth.auth().revokeToken(withAuthorizationCode:)
öğesini çağırmak için kullanın.Süratli
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) } } }
Son olarak, kullanıcı hesabını (ve ilişkili tüm verileri) silin
Sonraki adımlar
Bir kullanıcı ilk kez oturum açtıktan sonra, yeni bir kullanıcı hesabı oluşturulur ve kullanıcının oturum açtığı kimlik bilgilerine (yani, kullanıcı adı ve parolası, telefon numarası veya kimlik doğrulama sağlayıcı bilgileri) bağlanır. Bu yeni hesap, Firebase projenizin bir parçası olarak saklanır ve kullanıcının nasıl oturum açtığına bakılmaksızın projenizdeki her uygulamada bir kullanıcıyı tanımlamak için kullanılabilir.
Uygulamalarınızda, kullanıcının temel profil bilgilerini
User
nesnesinden alabilirsiniz. Bkz . Kullanıcıları Yönetin .Firebase Gerçek Zamanlı Veritabanı ve Bulut Depolama Güvenlik Kurallarınızda , oturum açmış kullanıcının benzersiz kullanıcı kimliğini
auth
değişkeninden alabilir ve bunu, bir kullanıcının hangi verilere erişebileceğini kontrol etmek için kullanabilirsiniz.
Bir kullanıcının oturumunu kapatmak için oturumu kapatın signOut:
.
Süratli
let firebaseAuth = Auth.auth() do { try firebaseAuth.signOut() } catch let signOutError as NSError { print("Error signing out: %@", signOutError) }
Amaç-C
NSError *signOutError; BOOL status = [[FIRAuth auth] signOut:&signOutError]; if (!status) { NSLog(@"Error signing out: %@", signOutError); return; }
Tüm kimlik doğrulama hataları için hata işleme kodu da eklemek isteyebilirsiniz. Bkz. İşleme Hataları .