Apple Kullanarak Kimlik Doğrula

Kullanıcılarınızın Apple Kimliklerini kullanarak Firebase ile kimlik doğrulamalarını aşağıdaki şekilde sağlayabilirsiniz: uçtan uca OAuth 2.0 oturum açma akışını gerçekleştirmek için Firebase SDK'sını kullanın.

Başlamadan önce

Apple kullanarak kullanıcıların oturumunu açmak için önce Apple ile oturum açma özelliğini yapılandırın Apple'ın geliştirici sitesinde Apple'ı oturum açma sağlayıcısı olarak etkinleştirin Firebase projesi.

Apple Developer Program'a katılın

Apple ile Oturum Açma özelliği, yalnızca Apple Developer'ın üyeleri tarafından yapılandırılabilir Program'ı tıklayın.

Apple ile oturum açma özelliğini yapılandırma

  1. Şuradaki uygulamanız için Apple ile Oturum Açma'yı etkinleştirin: Sertifikalar, Tanımlayıcılar ve Profiller sayfasındaki talimatları uygulayın.
  2. Web sitenizi, ilk bölümde açıklandığı şekilde uygulamanızla ilişkilendirin. Web için Apple ile Oturum Açma'yı yapılandırma başlıklı makaleye göz atın. İstendiğinde Dönüş URL'si olarak şu URL:
    https://YOUR_FIREBASE_PROJECT_ID.firebaseapp.com/__/auth/handler
    . Firebase proje kimliğinizi Firebase konsol ayarları sayfasında bulabilirsiniz. İşiniz bittiğinde yeni Hizmet Kimliğinizi not edin. Bu belgeyi ele alacağız.
  3. Oluştur: Apple özel anahtarıyla oturum açma başlıklı makaleyi inceleyin. Yeni özel anahtarınıza ve anahtarınıza ihtiyacınız olacak kimliğini girin.
  4. Firebase Authentication ürününün kullanıcılara e-posta gönderen özelliklerinden herhangi birini kullanıyorsanız e-posta bağlantısı oturum açma, e-posta adresi doğrulama, hesap değişikliği dahil iptal ve Apple özel e-posta geçiş hizmetini yapılandırın ve kaydolun noreply@YOUR_FIREBASE_PROJECT_ID.firebaseapp.com (veya özelleştirilmiş e-posta şablon alanınızı) kullanın. Böylece Apple, gönderilen e-postaları aktarabilir Firebase Authentication tarafından anonimleştirilmiş Apple e-posta adreslerine gönderildi.

Apple'ı oturum açma sağlayıcısı olarak etkinleştir

  1. Firebase'i Apple projenize ekleyin. Şunları yaptığınızdan emin olun: uygulamanızı Firebase konsolu.
  2. Firebase konsolunda Auth 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 kodu akışı yapılandırma bölümü, Apple Ekip Kimliğinizi ve Önceki bölümde oluşturduğunuz özel anahtar ve anahtar kimliği.

Apple'ın anonimleştirilmiş veri şartlarına uyma

Apple ile Oturum Açma, kullanıcılara verilerini anonimleştirme seçeneği sunar. oturum açarken kullandıkları e-posta adresleri de dahil. Bu seçeneği belirleyen kullanıcılar privaterelay.appleid.com alan adına sahip e-posta adresleri var. Zaman Uygulamanızda Apple ile Oturum Açma özelliğini kullanıyorsanız geçerli tüm bu anonimleştirilmiş Apple ile ilgili geliştirici politikaları veya Apple'ın şartları Kimlikler.

Buna, hesabınızı kullanmadan önce gerekli kullanıcı rızasının alınması da dahildir. doğrudan tanımlayıcı kişisel bilgileri anonimleştirilmiş bir Apple ile ilişkilendirme Kimlik. Firebase Authentication kullanılırken şunlar dahil olabilir: işlemler:

  • Bir e-posta adresini anonimleştirilmiş Apple kimliğine (veya tam tersi) bağlayın.
  • Telefon numarasını anonimleştirilmiş bir Apple kimliğine (veya tam tersi) bağlama
  • Anonim olmayan bir sosyal kimliği (ör. Facebook, Google) veya tam tersi de geçerlidir.

Yukarıdaki listede olası her duruma yer verilmemiştir. Apple Developer Program'ı inceleyin Geliştirici hesabınızın Üyelik bölümündeki Lisans Sözleşmesi'ni Uygulamanızın Apple'ın gereksinimlerini karşıladığından emin olun.

Apple ile oturum açma ve Firebase ile kimlik doğrulama

Bir Apple hesabıyla kimlik doğrulamak için önce kullanıcının Apple'da oturum açmasını sağlayın Apple'ın AuthenticationServices çerçevesini kullanan hesap ve ardından Firebase'i oluşturmak için Apple'ın yanıtındaki kimlik jetonunu kullanın. AuthCredential nesne:

  1. Her oturum açma isteği için rastgele bir dize oluşturun. "nonce": Aldığınız kimlik jetonunun şu olduğundan emin olmak için kullanırsınız: özel olarak uygulamanızın kimlik doğrulama isteğine yanıt olarak verilir. Bu adımı, tekrar saldırılarını önlemek için önemlidir.

    Tek başına güvenli tek seferlik rastgele sayı oluşturmak için SecRandomCopyBytes(_:_:_), aşağıdaki örnekte gösterildiği gibi:

    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];
    }
        

    Oturum açma isteğinizle birlikte tek seferlik rastgele sayının SHA256 karmasını gönderirsiniz. Apple, hiçbir değişiklik yapmadan yanıtta geçer. Firebase yanıtı doğrular karma oluşturma işlemini uygulayarak orijinal tek seferlik rastgele sayının karma hale getirilmesi ve Apple tarafından iletilen değerle karşılaştırılması gerekir.

    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;
    }
        
  2. İsteğinizde Apple'ın yanıtını işleyecek tek seferlik rastgele sayısı ve temsilci sınıfı (bkz. sıradaki adıma geçin):

    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];
    }
    
  3. ASAuthorizationControllerDelegate Oturum açma başarılı olduysa kimliği kullanın Apple'ın yanıtından gelen ve karma oluşturma işlemi uygulanmamış tek seferlik rastgele sayı içeren jetondan 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);
    }
    

Firebase Auth tarafından desteklenen diğer sağlayıcıların aksine, Apple fotoğraf URL'si.

Ayrıca kullanıcı, e-postalarını uygulamayla paylaşmamayı seçtiğinde Apple, söz konusu kullanıcı için benzersiz bir e-posta adresi ( xyz@privaterelay.appleid.com) çıkar ve bunları uygulamanızla paylaşır. Şu durumda: özel e-posta geçiş hizmetini yapılandırdığında, Apple kullanıcının gerçek e-posta adresine anonimleştirilmiş adres.

Yeniden kimlik doğrulama ve hesap bağlama

Aynı deseni reauthenticateWithCredential() için de kullanabilirsiniz. gereken hassas işlemler için yeni kimlik bilgileri almak üzere son oturum açma işlemi:

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.
  // ...
}];

Dilerseniz linkWithCredential() kullanarak farklı kimlik sağlayıcıları da hesaplar.

Apple, bağlantı oluşturmadan önce kullanıcılardan açıkça izin almanızı zorunlu kılar. diğer verilere aktarmalarını sağlar.

Apple ile oturum açmak, bir mevcut hesabınızda oturum açın. Apple ile oturum açma kimlik bilgilerini başka bir kimlik bilgisine bağlamak istiyorsanız hesabınıza erişmek için öncelikle eski şununla oturum açma yöntemini kullanarak hesapları bağlamayı denemeniz gerekir: Apple kimlik bilgisi ve ardından yeni kimlik bilgisi bulmak için döndürülen hatayı inceleyin. Yeni kimlik bilgisi hatanın userInfo sözlüğünde bulunur ve AuthErrorUserInfoUpdatedCredentialKey tuşuyla erişilebilir.

Örneğin, bir Facebook hesabını mevcut Firebase hesabına bağlamak için kullanıcının Facebook'ta oturum açarak aldığınız erişim jetonu:

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.
  // ...
}];

Jeton iptali

Apple, hesap oluşturma özelliğini destekleyen uygulamaların, kullanıcıların işlemi başlatmasına izin vermesini zorunlu kılar App Store İncelemesi'nde açıklandığı gibi, uygulama içinde hesabının silinmesi Kurallar

Bu koşulu karşılamak için aşağıdaki adımları uygulayın:

  1. Hizmet Kimliği ve OAuth kodu akış yapılandırmasını doldurduğunuzdan emin olun. bölümünde belirtildiği şekilde, Apple sağlayıcı ile oturum açma özelliğinin Apple ile oturum açma özelliğini yapılandırın.

  2. Kullanıcılar şununla oluşturulmuşsa Firebase, kullanıcı jetonlarını depolamaz: Apple ile oturum açın. ve hesabı silmeniz gerekir.

    Swift

    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)
      }
    }
    
    
  3. ASAuthorizationAppleIDCredential sitesinden yetkilendirme kodunu alın ve bu kodu, Auth.auth().revokeToken(withAuthorizationCode:) işlevini çağırmak için kullanabilirsiniz. kullanıcının jetonları.

    Swift

    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)
        }
      }
    }
    
    
  4. Son olarak, kullanıcı hesabını (ve ilişkili tüm verileri) silin

Sonraki adımlar

Kullanıcı ilk kez oturum açtığında yeni bir kullanıcı hesabı oluşturulur ve bilgileri (kullanıcı adı ve şifre, telefon numarası) Numara veya kimlik doğrulama sağlayıcı bilgileri (oturum açan kullanıcı). Bu yeni Firebase projenizin bir parçası olarak saklanır ve aşağıdaki verileri tanımlamak için kullanılabilir: nasıl oturum açarsa açsın, projenizdeki tüm uygulamalarda kullanılır.

  • Uygulamalarınızda, kullanıcıların temel profil bilgilerini şuradan alabilirsiniz: User nesnesini tanımlayın. Kullanıcıları Yönetme başlıklı makaleye göz atın.

  • Firebase Realtime Database ve Cloud Storage içinde Güvenlik Kuralları'nı kullanarak şunları yapabilirsiniz: auth değişkeninden, oturum açmış kullanıcının benzersiz kullanıcı kimliğini alabilirsiniz. ve kullanıcının hangi verilere erişebileceğini kontrol etmek için kullanılır.

Kullanıcıların çoklu kimlik doğrulama kullanarak uygulamanızda oturum açmasına izin verebilirsiniz yetkilendirme sağlayıcısının kimlik bilgilerini hesaba katılmaz.

Bir kullanıcının oturumunu kapatmak için numaralı telefonu arayın signOut: değerleridir.

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;
}

Ayrıca tüm kimlik doğrulama aralığı için hata işleme kodu da ekleyebilirsiniz. hatalar. Hataları İşleme bölümüne bakın.