Google se compromete a impulsar la igualdad racial para las comunidades afrodescendientes. Obtén información al respecto.

Autenticar usando Apple

Organiza tus páginas con colecciones Guarda y categoriza el contenido según tus preferencias.

Puede permitir que sus usuarios se autentiquen con Firebase usando su ID de Apple mediante el SDK de Firebase para llevar a cabo el flujo de inicio de sesión de OAuth 2.0 de un extremo a otro.

Antes de que empieces

Para que los usuarios inicien sesión con Apple, primero configure Iniciar sesión con Apple en el sitio para desarrolladores de Apple y luego habilite Apple como proveedor de inicio de sesión para su proyecto de Firebase.

Únase al programa de desarrolladores de Apple

Solo los miembros del Programa para desarrolladores de Apple pueden configurar Iniciar sesión con Apple.

Configurar Iniciar sesión con Apple

  1. Habilite Iniciar sesión con Apple para su aplicación en la página Certificados, identificadores y perfiles del sitio para desarrolladores de Apple.
  2. Si usa alguna de las funciones de Firebase Authentication que envían correos electrónicos a los usuarios, incluido el inicio de sesión con enlace de correo electrónico, la verificación de dirección de correo electrónico, la revocación de cambio de cuenta y otras, configure el servicio de retransmisión de correo electrónico privado de Apple y registre noreply@ YOUR_FIREBASE_PROJECT_ID .firebaseapp.com (o su dominio de plantilla de correo electrónico personalizado) para que Apple pueda retransmitir los correos electrónicos enviados por Firebase Authentication a direcciones de correo electrónico anonimizadas de Apple.

Habilitar Apple como proveedor de inicio de sesión

  1. Agregue Firebase a su proyecto de Apple . Asegúrese de registrar el ID del paquete de su aplicación cuando configure su aplicación en Firebase console.
  2. En Firebase console , abra la sección Auth . En la pestaña Método de inicio de sesión , habilite el proveedor de Apple . Si solo está utilizando Iniciar sesión con Apple en una aplicación, puede dejar vacíos los campos ID de servicio, ID de equipo de Apple, clave privada e ID de clave.

Cumplir con los requisitos de datos anónimos de Apple

Iniciar sesión con Apple ofrece a los usuarios la opción de anonimizar sus datos, incluida su dirección de correo electrónico, al iniciar sesión. Los usuarios que eligen esta opción tienen direcciones de correo electrónico con el dominio privaterelay.appleid.com . Cuando usa Iniciar sesión con Apple en su aplicación, debe cumplir con las políticas de desarrollador aplicables o los términos de Apple con respecto a estas ID de Apple anonimizadas.

Esto incluye obtener cualquier consentimiento de usuario requerido antes de asociar cualquier información personal de identificación directa con una ID de Apple anonimizada. Al usar Firebase Authentication, esto puede incluir las siguientes acciones:

  • Vincule una dirección de correo electrónico a una ID de Apple anónima o viceversa.
  • Vincular un número de teléfono a una ID de Apple anonimizada o viceversa
  • Vincule una credencial social no anónima (Facebook, Google, etc.) a una ID de Apple anónima o viceversa.

La lista de arriba no es exhaustiva. Consulte el Acuerdo de licencia del Programa para desarrolladores de Apple en la sección Membresía de su cuenta de desarrollador para asegurarse de que su aplicación cumpla con los requisitos de Apple.

Inicie sesión con Apple y autentíquese con Firebase

Para autenticarse con una cuenta de Apple, primero inicie sesión con el usuario en su cuenta de Apple usando el marco de servicios de AuthenticationServices de Apple y luego use el token de ID de la respuesta de Apple para crear un objeto Firebase AuthCredential :

  1. Para cada solicitud de inicio de sesión, genere una cadena aleatoria, un "nonce", que usará para asegurarse de que el token de ID que obtenga se haya otorgado específicamente en respuesta a la solicitud de autenticación de su aplicación. Este paso es importante para evitar ataques de repetición.

    Puede generar un nonce criptográficamente seguro con SecRandomCopyBytes(_:_:_) , como en el siguiente ejemplo:

    Rápido

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

    C objetivo

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

    Enviará el hash SHA256 del nonce con su solicitud de inicio de sesión, que Apple pasará sin cambios en la respuesta. Firebase valida la respuesta aplicando hash al nonce original y comparándolo con el valor pasado por Apple.

    Rápido

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

    C objetivo

    - (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. Inicie el flujo de inicio de sesión de Apple, incluyendo en su solicitud el hash SHA256 del nonce y la clase delegada que manejará la respuesta de Apple (vea el siguiente paso):

    Rápido

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

    C objetivo

    @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. Maneje la respuesta de Apple en su implementación de ASAuthorizationControllerDelegate . Si el inicio de sesión fue exitoso, use el token de ID de la respuesta de Apple con el nonce sin hash para autenticarse con Firebase:

    Rápido

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

    C objetivo

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

A diferencia de otros proveedores compatibles con Firebase Auth, Apple no proporciona una URL de foto.

Además, cuando el usuario elige no compartir su correo electrónico con la aplicación, Apple proporciona una dirección de correo electrónico única para ese usuario (de la forma xyz@privaterelay.appleid.com ), que comparte con su aplicación. Si configuró el servicio de retransmisión de correo electrónico privado, Apple reenvía los correos electrónicos enviados a la dirección anonimizada a la dirección de correo electrónico real del usuario.

Apple solo comparte información del usuario, como el nombre para mostrar, con las aplicaciones la primera vez que un usuario inicia sesión. Por lo general, Firebase almacena el nombre para mostrar la primera vez que un usuario inicia sesión con Apple, que puede obtener con Auth.auth().currentUser.displayName . Sin embargo, si anteriormente usó Apple para iniciar la sesión de un usuario en la aplicación sin usar Firebase, Apple no proporcionará a Firebase el nombre para mostrar del usuario.

Reautenticación y vinculación de cuentas

El mismo patrón se puede usar con reauthenticateWithCredential() , que puede usar para recuperar una credencial nueva para operaciones confidenciales que requieren un inicio de sesión reciente:

Rápido

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

C objetivo

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

Y puede usar linkWithCredential() para vincular diferentes proveedores de identidad a cuentas existentes.

Tenga en cuenta que Apple requiere que obtenga el consentimiento explícito de los usuarios antes de vincular sus cuentas de Apple a otros datos.

Iniciar sesión con Apple no le permitirá reutilizar una credencial de autenticación para vincularla a una cuenta existente. Si desea vincular una credencial de Iniciar sesión con Apple a otra cuenta, primero debe intentar vincular las cuentas utilizando la credencial anterior de Iniciar sesión con Apple y luego examinar el error que se devolvió para encontrar una nueva credencial. La nueva credencial se ubicará en el diccionario de información de userInfo del error y se puede acceder a ella a través de la clave FIRAuthErrorUserInfoUpdatedCredentialKey .

Por ejemplo, para vincular una cuenta de Facebook a la cuenta actual de Firebase, use el token de acceso que obtuvo al iniciar sesión el usuario en Facebook:

Rápido

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

C objetivo

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

Próximos pasos

Después de que un usuario inicia sesión por primera vez, se crea una nueva cuenta de usuario y se vincula a las credenciales (es decir, el nombre de usuario y la contraseña, el número de teléfono o la información del proveedor de autenticación) con las que el usuario inició sesión. Esta nueva cuenta se almacena como parte de su proyecto de Firebase y se puede usar para identificar a un usuario en cada aplicación de su proyecto, independientemente de cómo inicie sesión el usuario.

  • En sus aplicaciones, puede obtener la información básica del perfil del usuario del objeto FIRUser . Consulte Administrar usuarios .

  • En sus Reglas de seguridad de Firebase Realtime Database y Cloud Storage, puede obtener el ID de usuario único del usuario que inició sesión de la variable auth y usarlo para controlar a qué datos puede acceder un usuario.

Puede permitir que los usuarios inicien sesión en su aplicación utilizando varios proveedores de autenticación vinculando las credenciales del proveedor de autenticación a una cuenta de usuario existente.

Para cerrar la sesión de un usuario, llame signOut: .

Rápido

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

C objetivo

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

También es posible que desee agregar un código de manejo de errores para la gama completa de errores de autenticación. Consulte Manejo de errores .