Você pode permitir que os usuários façam login no seu aplicativo usando vários provedores de autenticação vinculando as credenciais do provedor de autenticação a uma conta de usuário existente. Os usuários são identificáveis pelo mesmo ID de usuário do Firebase, independentemente do provedor de autenticação usado para fazer login. Por exemplo, um usuário que fez login com uma senha pode vincular uma conta do Google e fazer login com qualquer um dos métodos no futuro. Ou um usuário anônimo pode vincular uma conta do Facebook e, posteriormente, fazer login no Facebook para continuar usando seu aplicativo.
Antes de você começar
Adicione suporte para dois ou mais provedores de autenticação (possivelmente incluindo autenticação anônima) ao seu aplicativo.
Vincular credenciais do provedor de autenticação a uma conta de usuário
Para vincular credenciais do provedor de autenticação a uma conta de usuário existente:
- Faça login do usuário usando qualquer provedor ou método de autenticação.
- Conclua o fluxo de login para o novo provedor de autenticação até, mas não incluindo, chamar um dos métodos
FIRAuth.signInWith
. Por exemplo, obtenha o token de ID do Google, o token de acesso do Facebook ou o e-mail e a senha do usuário. Obtenha um
FIRAuthCredential
para o novo provedor de autenticação:Login do Google
guard
let authentication = user?.authentication,
let idToken = authentication.idToken
else {
return
}
let credential = GoogleAuthProvider.credential(withIDToken: idToken,
accessToken: authentication.accessToken)FIRAuthCredential *credential =
[FIRGoogleAuthProvider credentialWithIDToken:result.user.idToken.tokenString
accessToken:result.user.accessToken.tokenString];Entrar no Facebook
let credential = FacebookAuthProvider
.credential(withAccessToken: AccessToken.current!.tokenString)FIRAuthCredential *credential = [FIRFacebookAuthProvider
credentialWithAccessToken:[FBSDKAccessToken currentAccessToken].tokenString];Login com senha de e-mail
let credential = EmailAuthProvider.credential(withEmail: email, password: password)
FIRAuthCredential *credential =
[FIREmailAuthProvider credentialWithEmail:email
password:password];Passe o objeto
FIRAuthCredential
para o métodolinkWithCredential:completion:
do usuário conectado:user.link(with: credential) { authResult, error in
// ...
}
}[[FIRAuth auth].currentUser linkWithCredential:credential
completion:^(FIRAuthDataResult *result, NSError *_Nullable error) {
// ...
}];A chamada para
linkWithCredential:completion:
falhará se as credenciais já estiverem vinculadas a outra conta de usuário. Nessa situação, você deve mesclar as contas e os dados associados conforme apropriado para seu aplicativo:let prevUser = Auth.auth().currentUser
Auth.auth().signIn(with: credential) { authResult, error in
if let error = error {
let authError = error as NSError
if isMFAEnabled, authError.code == AuthErrorCode.secondFactorRequired.rawValue {
// The user is a multi-factor user. Second factor challenge is required.
let resolver = authError
.userInfo[AuthErrorUserInfoMultiFactorResolverKey] as! MultiFactorResolver
var displayNameString = ""
for tmpFactorInfo in resolver.hints {
displayNameString += tmpFactorInfo.displayName ?? ""
displayNameString += " "
}
self.showTextInputPrompt(
withMessage: "Select factor to sign in\n\(displayNameString)",
completionBlock: { userPressedOK, displayName in
var selectedHint: PhoneMultiFactorInfo?
for tmpFactorInfo in resolver.hints {
if displayName == tmpFactorInfo.displayName {
selectedHint = tmpFactorInfo as? PhoneMultiFactorInfo
}
}
PhoneAuthProvider.provider()
.verifyPhoneNumber(with: selectedHint!, uiDelegate: nil,
multiFactorSession: resolver
.session) { verificationID, error in
if error != nil {
print(
"Multi factor start sign in failed. Error: \(error.debugDescription)"
)
} else {
self.showTextInputPrompt(
withMessage: "Verification code for \(selectedHint?.displayName ?? "")",
completionBlock: { userPressedOK, verificationCode in
let credential: PhoneAuthCredential? = PhoneAuthProvider.provider()
.credential(withVerificationID: verificationID!,
verificationCode: verificationCode!)
let assertion: MultiFactorAssertion? = PhoneMultiFactorGenerator
.assertion(with: credential!)
resolver.resolveSignIn(with: assertion!) { authResult, error in
if error != nil {
print(
"Multi factor finanlize sign in failed. Error: \(error.debugDescription)"
)
} else {
self.navigationController?.popViewController(animated: true)
}
}
}
)
}
}
}
)
} else {
self.showMessagePrompt(error.localizedDescription)
return
}
// ...
return
}
// User is signed in
// ...
}
// Merge prevUser and currentUser accounts and data
// ...
}FIRUser *prevUser = [FIRAuth auth].currentUser;
[[FIRAuth auth] signInWithCredential:credential
completion:^(FIRAuthDataResult * _Nullable authResult,
NSError * _Nullable error) {
if (isMFAEnabled && error && error.code == FIRAuthErrorCodeSecondFactorRequired) {
FIRMultiFactorResolver *resolver = error.userInfo[FIRAuthErrorUserInfoMultiFactorResolverKey];
NSMutableString *displayNameString = [NSMutableString string];
for (FIRMultiFactorInfo *tmpFactorInfo in resolver.hints) {
[displayNameString appendString:tmpFactorInfo.displayName];
[displayNameString appendString:@" "];
}
[self showTextInputPromptWithMessage:[NSString stringWithFormat:@"Select factor to sign in\n%@", displayNameString]
completionBlock:^(BOOL userPressedOK, NSString *_Nullable displayName) {
FIRPhoneMultiFactorInfo* selectedHint;
for (FIRMultiFactorInfo *tmpFactorInfo in resolver.hints) {
if ([displayName isEqualToString:tmpFactorInfo.displayName]) {
selectedHint = (FIRPhoneMultiFactorInfo *)tmpFactorInfo;
}
}
[FIRPhoneAuthProvider.provider
verifyPhoneNumberWithMultiFactorInfo:selectedHint
UIDelegate:nil
multiFactorSession:resolver.session
completion:^(NSString * _Nullable verificationID, NSError * _Nullable error) {
if (error) {
[self showMessagePrompt:error.localizedDescription];
} else {
[self showTextInputPromptWithMessage:[NSString stringWithFormat:@"Verification code for %@", selectedHint.displayName]
completionBlock:^(BOOL userPressedOK, NSString *_Nullable verificationCode) {
FIRPhoneAuthCredential *credential =
[[FIRPhoneAuthProvider provider] credentialWithVerificationID:verificationID
verificationCode:verificationCode];
FIRMultiFactorAssertion *assertion = [FIRPhoneMultiFactorGenerator assertionWithCredential:credential];
[resolver resolveSignInWithAssertion:assertion completion:^(FIRAuthDataResult * _Nullable authResult, NSError * _Nullable error) {
if (error) {
[self showMessagePrompt:error.localizedDescription];
} else {
NSLog(@"Multi factor finanlize sign in succeeded.");
}
}];
}];
}
}];
}];
}
else if (error) {
// ...
return;
}
// User successfully signed in. Get user data from the FIRUser object
if (authResult == nil) { return; }
FIRUser *user = authResult.user;
// ...
}];
// Merge prevUser and currentUser accounts and data
// ...
}];
Se a chamada para linkWithCredential:completion:
for bem-sucedida, o usuário agora poderá fazer login usando qualquer provedor de autenticação vinculado e acessar os mesmos dados do Firebase.
Desvincular um provedor de autenticação de uma conta de usuário
Você pode desvincular um provedor de autenticação de uma conta para que o usuário não possa mais fazer login nesse provedor.
Para desvincular um provedor de autenticação de uma conta de usuário, passe o ID do provedor para o método unlink
. Você pode obter os IDs dos provedores de autenticação vinculados a um usuário na propriedade providerData
.
Auth.auth().currentUser?.unlink(fromProvider: providerID!) { user, error in
// ...
}
[[FIRAuth auth].currentUser unlinkFromProvider:providerID
completion:^(FIRUser *_Nullable user, NSError *_Nullable error) {
// ...
}];