با استفاده از اپل در iOS احراز هویت شوید

با استفاده از Firebase SDK می توانید به کاربران خود اجازه دهید با استفاده از Apple ID خود با Firebase احراز هویت کنند تا جریان ورود به سیستم OAuth 2.0 را به صورت کامل انجام دهند.

قبل از اینکه شروع کنی

برای ورود کاربران با استفاده از Apple ، ابتدا ورود به سیستم با Apple را در سایت توسعه دهندگان Apple پیکربندی کنید ، سپس Apple را به عنوان ارائه دهنده ورود به سیستم پروژه Firebase خود فعال کنید.

به برنامه توسعه دهندگان اپل بپیوندید

ورود به سیستم با اپل تنها می تواند توسط اعضای پیکربندی اپل توسعهدهنده برنامه .

پیکربندی ورود به سیستم با Apple

  1. فعال کردن ورود به سیستم با اپل برای برنامه خود را در گواهینامه، شناسه و پروفیل صفحه از سایت توسعه دهنده اپل.
  2. اگر شما استفاده از هر یک از ویژگی فایربیس احراز هویت که ارسال ایمیل به کاربران، از جمله لینک ایمیل ورود به سیستم، تأیید آدرس ایمیل، تغییر حساب ابطال، و دیگران، پیکربندی سرویس رله ایمیل خصوصی اپل و ثبت نام noreply@ YOUR_FIREBASE_PROJECT_ID .firebaseapp.com (یا دامنه قالب ایمیل سفارشی شما) تا اپل بتواند ایمیل های ارسال شده توسط تأیید هویت Firebase را به آدرس های ایمیل ناشناس اپل منتقل کند.

اپل را به عنوان ارائه دهنده ورود به سیستم فعال کنید

  1. اضافه کردن فایربیس به پروژه های iOS خود را . هنگام تنظیم برنامه در کنسول Firebase ، حتماً شناسه بسته نرم افزاری خود را ثبت کنید.
  2. در فایربیس کنسول ، باز کردن بخش تایید. بر روی ثبت نام در تب روش، فعال کردن ارائه دهنده اپل. اگر در برنامه iOS فقط از Sign in with Apple استفاده می کنید ، می توانید قسمت Service ID ، Apple Team ID ، کلید خصوصی و شناسه کلید را خالی بگذارید.

از الزامات داده ناشناس اپل پیروی کنید

ورود به سیستم با اپل به کاربران می دهد این گزینه از بی نام داده، از جمله آدرس ایمیل خود، هنگامی که ورود به سیستم. کاربرانی که این گزینه را انتخاب کنید آدرس ایمیل با دامنه privaterelay.appleid.com . هنگامی که از برنامه ورود به سیستم با Apple در برنامه خود استفاده می کنید ، باید از هرگونه خط مشی توسعه دهنده یا شرایط مربوط به Apple در مورد این شناسه های ناشناس Apple استفاده کنید.

این شامل اخذ رضایت مورد نیاز کاربر قبل از ارتباط مستقیم اطلاعات شخصی با یک Apple ID ناشناس است. هنگام استفاده از احراز هویت Firebase ، این ممکن است شامل اقدامات زیر باشد:

  • پیوند آدرس ایمیل به Apple ID ناشناس یا برعکس.
  • یک شماره تلفن را به Apple ID ناشناس یا بالعکس پیوند دهید
  • یک اعتبار اجتماعی ناشناس (فیس بوک ، گوگل و غیره) را به Apple ID ناشناس پیوند دهید یا برعکس.

لیست بالا جامع نیست. در قسمت عضویت در حساب توسعه دهنده خود به موافقت نامه مجوز برنامه توسعه دهندگان Apple مراجعه کنید تا مطمئن شوید برنامه شما با الزامات Apple مطابقت دارد.

با Apple وارد شوید و با Firebase احراز هویت کنید

برای تأیید هویت با یک حساب کاربری اپل، برای اولین بار است که کاربر در به اپل خود را امضا حساب با استفاده از اپل AuthenticationServices چارچوب ، و سپس با استفاده از شناسه نشانه از پاسخ اپل برای ایجاد یک فایربیس AuthCredential شی:

  1. برای هر درخواست ورود به سیستم ، یک رشته تصادفی ایجاد کنید-یک "nonce"-که از آن استفاده خواهید کرد تا مطمئن شوید که شناسه ای که دریافت می کنید به طور خاص در پاسخ به درخواست احراز هویت برنامه شما اعطا شده است. این مرحله برای جلوگیری از حملات تکراری مهم است.

    شما می توانید یک فعلی رمز نویسی امن در iOS با تولید SecRandomCopyBytes(_:_:_) ، همانطور که در مثال زیر:

    سریع

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

    هدف-ج

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

    شما با درخواست ورود به سیستم ، هش SHA256 nonce را ارسال می کنید ، که اپل در پاسخ آن را بدون تغییر رد می کند. Firebase با هش کردن nonce اصلی و مقایسه آن با مقدار تصویب شده توسط Apple ، پاسخ را معتبر می کند.

  2. جریان ورود به سیستم اپل را شروع کنید ، از جمله در درخواست شما هش SHA256 از nonce و کلاس نماینده که پاسخ اپل را کنترل می کند (مرحله بعدی را ببینید):

    سریع

    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
    }
    

    هدف-ج

    @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;
    }
    
  3. دسته پاسخ اپل در اجرای خود از ASAuthorizationControllerDelegate . اگر ورود به سیستم موفقیت آمیز بود ، از شناسه ای که از پاسخ اپل به همراه uncehed بدون استفاده شده برای تأیید اعتبار با Firebase استفاده کنید:

    سریع

    @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)")
      }
    
    }
    

    هدف-ج

    - (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 ، اپل آدرس عکس ارائه نمی دهد.

همچنین، هنگامی که کاربر بخواهد به اشتراک گذاشتن ایمیل خود را با این برنامه، مفاد اپل یک آدرس ایمیل منحصر به فرد برای آن کاربر (از فرم نمی xyz@privaterelay.appleid.com )، آن سهام با برنامه شما. اگر سرویس رله ایمیل خصوصی را پیکربندی کرده اید ، اپل ایمیل های ارسال شده به آدرس ناشناس را به آدرس ایمیل واقعی کاربر ارسال می کند.

اپل این اطلاعات را تنها سهام کاربر مانند نام نمایش با برنامه های اولین بار که کاربر در. معمولا، فروشگاه های فایربیس نام صفحه نمایش اولین بار که کاربر با شرکت اپل، که شما می توانید با گرفتن Auth.auth().currentUser.displayName . با این حال ، اگر قبلاً از Apple برای ورود کاربر به برنامه بدون استفاده از Firebase استفاده کرده اید ، اپل نام نمایشی کاربر را به Firebase ارائه نمی دهد.

احراز هویت مجدد و پیوند دادن حساب

همین الگو را می توان با استفاده reauthenticateWithCredential() ، که شما می توانید برای بازیابی یک اعتبارنامه تازه برای عملیات حساس که نیاز به ورود به سیستم جدید استفاده کنید:

سریع

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

هدف-ج

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

و شما می توانید با استفاده از linkWithCredential() ، لینک ارائه دهندگان هویت های مختلف به حساب های موجود.

توجه داشته باشید که اپل از شما می خواهد قبل از پیوند دادن حساب های اپل آنها به سایر داده ها ، رضایت صریح آنها را از کاربران دریافت کنید.

ورود به سیستم با Apple به شما امکان نمی دهد از اعتبارنامه برای پیوند به حساب موجود استفاده مجدد کنید. اگر می خواهید ورود به سیستم را با اعتبار Apple به حساب دیگری پیوند دهید ، ابتدا باید حسابها را با استفاده از ورود به سیستم قدیمی با اعتبار Apple پیوند دهید و سپس خطای برگشتی را برای یافتن اعتبار جدید بررسی کنید. گواهی نامه جدید خواهد شد در خطا واقع userInfo فرهنگ لغت و می تواند از طریق دیده FIRAuthErrorUserInfoUpdatedCredentialKey کلیدی است.

به عنوان مثال ، برای پیوند دادن حساب فیس بوک به حساب فعلی Firebase ، از رمز دسترسی که از ورود کاربر به فیس بوک دریافت کرده اید استفاده کنید:

سریع

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

هدف-ج

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

مراحل بعدی

پس از ورود کاربر برای اولین بار ، یک حساب کاربری جدید ایجاد می شود و به اعتبارنامه - یعنی نام کاربری و گذرواژه ، شماره تلفن یا اطلاعات ارائه دهنده تأیید - که کاربر با آن وارد شده است پیوند داده می شود. این حساب جدید به عنوان بخشی از پروژه Firebase شما ذخیره می شود و می تواند بدون در نظر گرفتن نحوه ورود کاربر در هر برنامه ای در پروژه شما ، کاربر را شناسایی کند.

  • در برنامه های خود را، شما می توانید اطلاعات نمایه کاربر از دریافت FIRUser شی. مشاهده مدیریت کاربران .

  • در خود پایگاه فایربیس بیدرنگ و ابر ذخیره سازی قوانین امنیتی ، شما می توانید دریافت امضا در شناسه کاربری منحصر به فرد کاربر را از auth متغیر، و استفاده از آن برای کنترل آنچه داده دسترسی کاربر می تواند.

شما می توانید اجازه به کاربران برای ورود به سیستم برنامه خود را با استفاده از ارائه دهندگان تأیید هویت چندگانه توسط ارتباط تایید اعتبار ارائه دهنده به یک حساب کاربری موجود.

برای خروج از سیستم یک کاربر، پاسخ signOut: .

سریع

    let firebaseAuth = Auth.auth()
do {
  try firebaseAuth.signOut()
} catch let signOutError as NSError {
  print("Error signing out: %@", signOutError)
}
  

هدف-ج

    NSError *signOutError;
BOOL status = [[FIRAuth auth] signOut:&signOutError];
if (!status) {
  NSLog(@"Error signing out: %@", signOutError);
  return;
}

شما همچنین ممکن است بخواهید کد مدیریت خطا را برای طیف وسیعی از خطاهای احراز هویت اضافه کنید. مشاهده خطاها دسته .