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ına izin verebilirsiniz.
Sen başlamadan önce
Apple kullanarak kullanıcılarda oturum açmak için önce Apple'ın geliştirici sitesinde Apple ile Giriş Yap özelliğini yapılandırın, ardından Apple'ı Firebase projeniz için 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 Geliştirici Programı üyeleri tarafından yapılandırılabilir.
Apple ile Giriş Yapmayı Yapılandırma
- Apple'ın geliştirici sitesinin Sertifikalar, Tanımlayıcılar ve Profiller sayfasında uygulamanız için Apple ile Giriş Yap özelliğini etkinleştirin.
- Firebase Authentication'ın e-posta bağlantısı girişi, e-posta adresi doğrulama, hesap değişikliği iptali ve diğerleri dahil olmak üzere kullanıcılara e-posta gönderen özelliklerinden herhangi birini kullanıyorsanız , Apple özel e-posta aktarma hizmetini yapılandırın ve
noreply@ YOUR_FIREBASE_PROJECT_ID .firebaseapp.com
(veya Apple'ın Firebase Authentication tarafından gönderilen e-postaları anonimleştirilmiş Apple e-posta adreslerine aktarabilmesi için özelleştirilmiş e-posta şablonu etki alanınız).
Apple'ı oturum açma sağlayıcı olarak etkinleştirin
- Firebase'i iOS projenize ekleyin . Firebase konsolunda uygulamanızı kurarken uygulamanızın paket kimliğini kaydettiğinizden emin olun.
- In Firebase konsoluna , Auth bölümünü açın. Giriş yöntemi sekmesinde, Apple sağlayıcısını etkinleştirin. Bir iOS uygulamasında yalnızca Apple ile Giriş Yap özelliğini kullanıyorsanız Servis Kimliği, Apple Ekip Kimliği, özel anahtar ve anahtar kimliği alanlarını boş bırakabilirsiniz.
Apple'ın anonimleştirilmiş veri gereksinimlerine uyun
Apple ile Giriş Yap, kullanıcılara oturum açarken e-posta adresleri de dahil olmak üzere verilerini anonimleştirme seçeneği sunar. Bu seçeneği seçen kullanıcılar privaterelay.appleid.com
etki alanı ile e-posta adreslerine sahiptir. Uygulamanızda Apple ile Giriş Yap özelliğini kullandığınızda, bu anonimleştirilmiş Apple Kimlikleriyle ilgili olarak Apple'ın geçerli geliştirici politikalarına veya hükümlerine uymanız gerekir.
Bu, kişisel bilgileri doğrudan anonimleştirilmiş bir Apple Kimliği ile ilişkilendirmeden önce gerekli tüm kullanıcı onayını almayı içerir. Firebase Kimlik Doğrulaması kullanılırken bu, aşağıdaki eylemleri içerebilir:
- Bir e-posta adresini anonimleştirilmiş bir Apple Kimliğine bağlayın veya tersini yapın.
- Bir telefon numarasını anonimleştirilmiş bir Apple Kimliğine bağlayın veya tam tersi
- Anonim olmayan bir sosyal kimlik bilgisini (Facebook, Google, vb.) Anonimleştirilmiş bir Apple Kimliğine bağlayın veya tam tersi.
Yukarıdaki liste kapsamlı 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 giriş yapın ve Firebase ile kimlik doğrulayın
Bir Apple hesabıyla kimlik doğrulaması yapmak için önce Apple'ın AuthenticationServices
çerçevesini kullanarak kullanıcının Apple hesabına giriş yapın ve ardından bir AuthCredential
nesnesi oluşturmak için Apple'ın yanıtındaki kimlik jetonunu kullanın:
Her oturum açma isteği için, aldığınız kimlik jetonunun özellikle uygulamanızın kimlik doğrulama isteğine yanıt olarak verildiğinden emin olmak için kullanacağınız rastgele bir dize ("nonce") oluşturun. Bu adım, tekrar saldırılarını önlemek için önemlidir.
Aşağıdaki örnekte olduğu gibi,
SecRandomCopyBytes(_:_:_)
ile iOS'ta kriptografik olarak güvenli bir nonce oluşturabilirsiniz:Swift
// Adapted from https://auth0.com/docs/api-auth/tutorials/nonce#generate-a-cryptographically-random-nonce private func randomNonceString(length: Int = 32) -> String { precondition(length > 0) let charset: Array<Character> = Array("0123456789ABCDEFGHIJKLMNOPQRSTUVXYZabcdefghijklmnopqrstuvwxyz-._") var result = "" var remainingLength = length while remainingLength > 0 { let randoms: [UInt8] = (0 ..< 16).map { _ in var random: UInt8 = 0 let errorCode = SecRandomCopyBytes(kSecRandomDefault, 1, &random) if errorCode != errSecSuccess { fatalError("Unable to generate nonce. SecRandomCopyBytes failed with OSStatus \(errorCode)") } return random } randoms.forEach { random in if remainingLength == 0 { return } if random < charset.count { result.append(charset[Int(random)]) remainingLength -= 1 } } } return result }
Amaç-C
- (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; }
Nonce'nin SHA256 hash'ini oturum açma talebinizle birlikte göndereceksiniz ve Apple, yanıtta değişmeden iletecektir. Firebase, orijinal nonce'ye hashing uygulayarak ve Apple tarafından iletilen değerle karşılaştırarak yanıtı doğrular.
Apple'ın oturum açma akışını, isteğinizde nonce'nin SHA256 karması ve Apple'ın yanıtını işleyecek temsilci sınıfı dahil olmak üzere başlatın (sonraki adıma bakın):
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 }
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]; } - (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; }
ASAuthorizationControllerDelegate
uygulamanızda Apple'ın yanıtınıASAuthorizationControllerDelegate
. Oturum açma başarılı olduysa, Firebase ile kimlik doğrulaması yapmak için Apple'ın yanıtından gelen kimlik jetonunu karma olmayan nonce ile kullanın: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)") } }
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. 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); }
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 bu kullanıcı için uygulamanızla paylaştığı benzersiz bir e-posta adresi ( xyz@privaterelay.appleid.com
biçiminde) sağlar. Özel e-posta aktarma hizmetini yapılandırdıysanız Apple, anonimleştirilmiş adrese gönderilen e-postaları kullanıcının gerçek e-posta adresine iletir.
Apple, görünen ad gibi kullanıcı bilgilerini yalnızca bir kullanıcı ilk kez oturum Auth.auth().currentUser.displayName
, görünen adı Auth.auth().currentUser.displayName
ile Auth.auth().currentUser.displayName
bir kullanıcı Apple ile ilk kez oturum Auth.auth().currentUser.displayName
. Ancak, Apple'ı daha önce bir kullanıcıyı Firebase kullanmadan uygulamada oturum açmak için kullandıysanız, Apple Firebase'e kullanıcının görünen adını sağlamaz.
Yeniden kimlik doğrulama ve hesap bağlama
Aynı desen, 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:
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.
// ...
}
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'ın, Apple hesaplarını diğer verilere bağlamadan önce kullanıcılardan açık izin almanızı gerektirdiğini unutmayın.
Apple ile giriş yapmak, mevcut bir hesaba bağlanmak için bir kimlik doğrulama bilgilerini yeniden kullanmanıza izin vermez. Apple ile Giriş Yap kimlik bilgilerini başka bir hesaba bağlamak istiyorsanız, önce eski Apple ile Giriş Yap kimlik bilgilerini kullanarak 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 içinde yer alacak userInfo
Sözlük ve erişilebilir FIRAuthErrorUserInfoUpdatedCredentialKey
tuşu.
Örneğin, bir Facebook hesabını mevcut Firebase hesabına bağlamak için, kullanıcıyı Facebook'ta oturum açarak elde ettiğiniz erişim jetonunu kullanın:
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.
// ...
}
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.
// ...
}];
Sonraki adımlar
Bir kullanıcı ilk kez oturum açtıktan sonra, yeni bir kullanıcı hesabı oluşturulur ve oturum açan kullanıcı 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 depolanı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,
FIRUser
nesnesinden kullanıcının temel profil bilgileriniFIRUser
. Kullanıcıları Yönetme konusuna bakın.Firebase Realtime Database ve Cloud Storage Güvenlik Kurallarınızda , oturum
auth
kullanıcının benzersiz kullanıcı kimliğiniauth
değişkeninden alabilir ve bir kullanıcının hangi verilere erişebileceğini kontrol etmek için kullanabilirsiniz.
Yetkilendirme sağlayıcı kimlik bilgilerini mevcut bir kullanıcı hesabına bağlayarak , kullanıcıların birden çok kimlik doğrulama sağlayıcısı kullanarak uygulamanızda oturum açmasına izin verebilirsiniz .
Bir kullanıcının oturumunu kapatmak için signOut:
arayın.
Swift
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. Hataları İşleme .