Permita que os usuários se autentiquem com o Firebase usando provedores OAuth, como o Yahoo. Basta integrar o login genérico do OAuth ao seu app usando o SDK do Firebase para realizar o fluxo de login completo.
Antes de começar
Para fazer login de usuários usando contas do Yahoo, primeiro ative o Yahoo como um provedor de login do seu projeto do Firebase:
- Adicione o Firebase ao projeto da Apple.
- No console do Firebase, abra a seção Autenticação.
- Na guia Método de login, ative o provedor Yahoo.
- Adicione o ID do cliente e a Chave secreta do cliente no console de desenvolvimento às
configurações do provedor:
-
Para registrar um cliente OAuth do Yahoo, siga a documentação do desenvolvedor dessa plataforma sobre como registrar um aplicativo da Web no Yahoo.
Selecione as duas permissões da API OpenID Connect:
profile
eemail
. - Ao registrar apps nesses provedores, registre o domínio
*.firebaseapp.com
do projeto como o domínio de redirecionamento do seu app.
-
- Clique em Salvar.
Processar o fluxo de login com o SDK do Firebase
Para processar o fluxo de login com o SDK do Firebase para plataformas Apple, siga estas etapas:
Adicione esquemas de URL personalizado ao seu projeto do Xcode:
- Abra a configuração do seu projeto clicando duas vezes no nome dele na visualização em árvore à esquerda. Selecione seu app na seção DESTINOS. Em seguida, selecione a guia Informações e expanda a seção Tipos de URL.
- Clique no botão + e adicione o ID do app codificado como um esquema de URL. Encontre o ID codificado do app na página Configurações gerais do Console do Firebase na seção do seu app iOS. Deixe os outros campos em branco.
Quando concluída, a configuração será semelhante à mostrada a seguir, mas com os valores específicos do seu app:
Crie uma instância de um OAuthProvider usando o ID de provedor yahoo.com.
var provider = OAuthProvider(providerID: "yahoo.com")
FIROAuthProvider *provider = [FIROAuthProvider providerWithProviderID:@"yahoo.com"];
Opcional: especifique os parâmetros OAuth personalizados que você quer enviar com a solicitação OAuth.
provider.customParameters = [ "prompt": "login", "language": "fr" ]
[provider setCustomParameters:@{@"prompt": @"login", @"language": @"fr"}];
Para saber quais parâmetros são aceitos pelo Yahoo, consulte a documentação do OAuth do Yahoo (em inglês). Não é possível transmitir os parâmetros exigidos pelo Firebase com
setCustomParameters
. Esses parâmetros são client_id, redirect_uri, response_type, scope e state.Opcional: especifique escopos adicionais do OAuth 2.0 além de
profile
eemail
que você quer solicitar ao provedor de autenticação. Se o aplicativo exigir acesso a dados particulares de usuários das APIs do Yahoo, será necessário solicitar permissões às APIs em Permissões de APIs no console de desenvolvimento do Yahoo. Os escopos do OAuth solicitados precisam corresponder exatamente àqueles pré-configurados nas permissões da API do app. Por exemplo, se o acesso de leitura/gravação for solicitado aos contatos do usuário e pré-configurado nas permissões da API do app, será necessário transmitirsdct-w
em vez do escopo somente leiturasdct-r
do OAuth. Caso contrário, o fluxo falhará e um erro será mostrado ao usuário final.// Request access to Yahoo Mail API. // Request read/write access to user contacts. // This must be preconfigured in the app's API permissions. provider.scopes = ["mail-r", "sdct-w"]
// Request access to Yahoo Mail API. // Request read/write access to user contacts. // This must be preconfigured in the app's API permissions. [provider setScopes:@[@"mail-r", @"sdct-w"]];
Para saber mais, consulte a documentação do escopo do Yahoo (em inglês).
Opcional: se quiser personalizar a forma como o app apresenta o
SFSafariViewController
ou oUIWebView
ao exibir o reCAPTCHA para o usuário, crie uma classe personalizada que esteja em conformidade com o protocoloAuthUIDelegate
e transmita-a paracredentialWithUIDelegate
.Use o objeto de provedor do OAuth para a autenticação no Firebase.
provider.getCredentialWith(nil) { credential, error in if error != nil { // Handle error. } if credential != nil { Auth().signIn(with: credential) { authResult, error in if error != nil { // Handle error. } // User is signed in. // IdP data available in authResult.additionalUserInfo.profile. // Yahoo OAuth access token can also be retrieved by: // (authResult.credential as? OAuthCredential)?.accessToken // Yahoo OAuth ID token can be retrieved by calling: // (authResult.credential as? OAuthCredential)?.idToken } } }
[provider getCredentialWithUIDelegate:nil completion:^(FIRAuthCredential *_Nullable credential, NSError *_Nullable error) { if (error) { // Handle error. } if (credential) { [[FIRAuth auth] signInWithCredential:credential completion:^(FIRAuthDataResult *_Nullable authResult, NSError *_Nullable error) { if (error) { // Handle error. } // User is signed in. // IdP data available in authResult.additionalUserInfo.profile. // Yahoo OAuth access token can also be retrieved by: // ((FIROAuthCredential *)authResult.credential).accessToken // Yahoo OAuth ID token can be retrieved by calling: // ((FIROAuthCredential *)authResult.credential).idToken }]; } }];
Com o token de acesso OAuth, é possível chamar a API do Yahoo.
Por exemplo, para receber informações básicas de perfil, chame a API REST transmitindo o token de acesso no cabeçalho
Authorization
:https://social.yahooapis.com/v1/user/YAHOO_USER_UID/profile?format=json
Em que
YAHOO_USER_UID
é o ID do usuário do Yahoo que pode ser recuperado com o campoAuth.auth.currentUser.providerData[0].uid
ou deauthResult.additionalUserInfo.profile
.Embora os exemplos acima se concentrem nos fluxos de login, você também pode vincular um provedor do Yahoo a um usuário existente usando
linkWithPopup
. Por exemplo, vincule vários provedores ao mesmo usuário permitindo o login com qualquer um deles.Auth().currentUser.link(withCredential: credential) { authResult, error in if error != nil { // Handle error. } // Yahoo credential is linked to the current user. // IdP data available in authResult.additionalUserInfo.profile. // Yahoo OAuth access token can also be retrieved by: // (authResult.credential as? OAuthCredential)?.accessToken // Yahoo OAuth ID token can be retrieved by calling: // (authResult.credential as? OAuthCredential)?.idToken }
[[FIRAuth auth].currentUser linkWithCredential:credential completion:^(FIRAuthDataResult * _Nullable authResult, NSError * _Nullable error) { if (error) { // Handle error. } // Yahoo credential is linked to the current user. // IdP data available in authResult.additionalUserInfo.profile. // Yahoo OAuth access token is can also be retrieved by: // ((FIROAuthCredential *)authResult.credential).accessToken // Yahoo OAuth ID token can be retrieved by calling: // ((FIROAuthCredential *)authResult.credential).idToken }];
É possível usar o mesmo padrão com
reauthenticateWithPopup
/reauthenticateWithRedirect
, que pode ser utilizado para recuperar credenciais novas de operações confidenciais que exigem um login recente.Auth().currentUser.reauthenticateWithCredential(withCredential: credential) { authResult, error in if error != nil { // Handle error. } // User is re-authenticated with fresh tokens minted and // should be able to perform sensitive operations like account // deletion and email or password update. // IdP data available in result.additionalUserInfo.profile. // Additional OAuth access token is can also be retrieved by: // (authResult.credential as? OAuthCredential)?.accessToken // Yahoo OAuth ID token can be retrieved by calling: // (authResult.credential as? OAuthCredential)?.idToken }
[[FIRAuth auth].currentUser reauthenticateWithCredential:credential completion:^(FIRAuthDataResult * _Nullable authResult, NSError * _Nullable error) { if (error) { // Handle error. } // User is re-authenticated with fresh tokens minted and // should be able to perform sensitive operations like account // deletion and email or password update. // IdP data available in result.additionalUserInfo.profile. // Additional OAuth access token is can also be retrieved by: // ((FIROAuthCredential *)authResult.credential).accessToken // Yahoo OAuth ID token can be retrieved by calling: // ((FIROAuthCredential *)authResult.credential).idToken }];
Tratamento de erros account-exists-with-different-credential
Se você ativou a configuração Uma conta por endereço de e-mail no Console do Firebase,
quando um usuário tentar se conectar a um provedor (como o Yahoo) com um e-mail que já
existe em outro provedor de usuário do Firebase (como o Google), o erro
FIRAuthErrorCodeAccountExistsWithDifferentCredential
será exibido com um
objeto FIRAuthCredential
(credencial do Yahoo). Para concluir o login no
provedor pretendido, o usuário primeiro precisa fazer login no provedor atual (Google) e, em seguida, vinculá-lo ao
FIRAuthCredential
anterior (credencial do Yahoo). O resultado desse processo seria semelhante ao mostrado abaixo:
// Sign-in with an OAuth credential. provider.getCredentialWith(nil) { credential, error in // An account with the same email already exists. if (error as NSError?)?.code == AuthErrorCode.accountExistsWithDifferentCredential.rawValue { // Get pending credential and email of existing account. let existingAcctEmail = (error! as NSError).userInfo[AuthErrorUserInfoEmailKey] as! String let pendingCred = (error! as NSError).userInfo[AuthErrorUserInfoUpdatedCredentialKey] as! AuthCredential // Lookup existing account identifier by the email. Auth.auth().fetchProviders(forEmail:existingAcctEmail) { providers, error in // Existing email/password account. if (providers?.contains(EmailAuthProviderID))! { // Existing password account for email. Ask user to provide the password of the // existing account. // Sign in with existing account. Auth.auth().signIn(withEmail:existingAcctEmail, password:password) { user, error in // Successfully signed in. if user != nil { // Link pending credential to account. Auth.auth().currentUser?.linkAndRetrieveData(with: pendingCred) { result, error in // ... } } } } } return } // Other errors. if error != nil { // handle the error. return } // Sign in with the credential. if credential != nil { Auth.auth().signInAndRetrieveData(with: credential!) { result, error in if error != nil { // handle the error. return } } } }
// Sign-in with an OAuth credential. [provider getCredentialWithUIDelegate:nil completion:^(FIRAuthCredential *_Nullable credential, NSError *_Nullable error) { // An account with the same email already exists. if (error.code == FIRAuthErrorCodeAccountExistsWithDifferentCredential) { // Get pending credential and email of existing account. NSString *existingAcctEmail = error.userInfo[FIRAuthErrorUserInfoEmailKey]; FIRAuthCredential *pendingCred = error.userInfo[FIRAuthErrorUserInfoUpdatedCredentialKey]; // Lookup existing account identifier by the email. [[FIRAuth auth] fetchProvidersForEmail:existingAcctEmail completion:^(NSArray<NSString *> *_Nullable providers, NSError *_Nullable error) { // Existing email/password account. if ( [providers containsObject:FIREmailAuthProviderID] ) { // Existing password account for email. Ask user to provide the password of the // existing account. // Sign in with existing account. [[FIRAuth auth] signInWithEmail:existingAcctEmail password:password completion:^(FIRUser *user, NSError *error) { // Successfully signed in. if (user) { // Link pending credential to account. [[FIRAuth auth].currentUser linkWithCredential:pendingCred completion:^(FIRUser *_Nullable user, NSError *_Nullable error) { // ... }]; } }]; } }]; return; } // Other errors. if (error) { // handle the error. return; } // Sign in with the credential. if (credential) { [[FIRAuth auth] signInAndRetrieveDataWithCredential:credential completion:^(FIRAuthDataResult *_Nullable authResult, NSError *_Nullable error) { if (error) { // handle the error. return; } }]; } }];
Avançado: processar o fluxo de login manualmente
Ao contrário de outros provedores OAuth aceitos pelo Firebase, como Google, Facebook e Twitter, em que é possível fazer login diretamente com credenciais baseadas em token de acesso OAuth, isso não é possível no Firebase Auth ao usar provedores como o Yahoo porque o servidor do Firebase Auth não consegue verificar o público dos tokens de acesso OAuth do Yahoo. Esse é um requisito de segurança fundamental e pode expor aplicativos e sites a ataques de repetição, em que um token de acesso OAuth do Yahoo recebido em um projeto (invasor) pode ser usado para acessar outro projeto (vítima). Em vez disso, o Firebase Auth permite gerenciar todo o fluxo do OAuth e trocar o código de autorização usando o ID do cliente e o secret do OAuth configurados no Console do Firebase. Um código de autorização recebido em um projeto não pode ser usado em outro, porque só pode ser utilizado em conjunto com um ID do cliente/secret específicos.
Se for preciso usar esses provedores em ambientes sem suporte, será necessário usar uma biblioteca OAuth de terceiros e uma autenticação personalizada do Firebase. O primeiro é necessário para autenticar com o provedor, e o segundo para trocar a credencial do provedor por um token personalizado.
Próximas etapas
Depois que um usuário faz login pela primeira vez, uma nova conta de usuário é criada e vinculada às credenciais, que podem ser o número do telefone, o nome de usuário e a senha ou as informações do provedor de autenticação. Essa nova conta é armazenada como parte do projeto do Firebase e pode ser usada para identificar um usuário em todos os apps do projeto, seja qual for o método de login utilizado.
-
É possível receber as informações básicas de perfil do usuário do objeto
User
nos seus apps. Consulte Gerenciar usuários. Nas Regras de segurança Firebase Realtime Database e Cloud Storage, você pode acessar o ID exclusivo do usuário conectado pela variável
auth
e usar essas informações para controlar quais dados um usuário pode acessar.
Os usuários podem fazer login no app usando vários provedores de autenticação. Basta vincular as credenciais desses provedores a uma conta de usuário.
Para desconectar um usuário, chame
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; }
Adicione também o código de tratamento de erros para todo o intervalo de erros de autenticação. Consulte Tratamento de erros.