Você pode permitir que seus usuários se autentiquem com o Firebase usando provedores OAuth, como o Microsoft Azure Active Directory, integrando o login OAuth genérico baseado na Web ao seu aplicativo usando o SDK do Firebase para realizar o fluxo de login de ponta a ponta.
Antes de você começar
Para conectar usuários usando contas da Microsoft (Azure Active Directory e contas pessoais da Microsoft), primeiro você deve habilitar a Microsoft como provedor de login para seu projeto do Firebase:
- Adicione o Firebase ao seu projeto Apple .
- No console do Firebase , abra a seção Auth .
- Na guia Método de login , habilite o provedor Microsoft .
- Adicione o ID do cliente e o segredo do cliente do console do desenvolvedor desse provedor à configuração do provedor:
- Para registrar um cliente Microsoft OAuth, siga as instruções em Início rápido: registrar um aplicativo com o ponto de extremidade do Azure Active Directory v2.0 . Observe que esse ponto de extremidade dá suporte à entrada usando contas pessoais da Microsoft, bem como contas do Azure Active Directory. Saiba mais sobre o Azure Active Directory v2.0.
- Ao registrar aplicativos com esses provedores, registre o domínio
*.firebaseapp.com
do seu projeto como o domínio de redirecionamento do seu aplicativo.
- Clique em Salvar .
Lidar com o fluxo de login com o SDK do Firebase
Para lidar com o fluxo de login com o SDK das plataformas Apple do Firebase, siga estas etapas:
Adicione esquemas de URL personalizados ao seu projeto Xcode:
- Abra a configuração do seu projeto: clique duas vezes no nome do projeto na visualização em árvore à esquerda. Selecione seu aplicativo na seção TARGETS , selecione a guia Informações e expanda a seção Tipos de URL .
- Clique no botão + e adicione seu ID de aplicativo codificado como um esquema de URL. Você pode encontrar o ID do aplicativo codificado na página Configurações gerais do console do Firebase, na seção do seu aplicativo iOS. Deixe os outros campos em branco.
Quando concluída, sua configuração deverá ser semelhante à seguinte (mas com os valores específicos do seu aplicativo):
Crie uma instância de um OAuthProvider usando o ID do provedor microsoft.com .
var provider = OAuthProvider(providerID: "microsoft.com")
FIROAuthProvider *provider = [FIROAuthProvider providerWithProviderID:@"microsoft.com"];
Opcional : Especifique parâmetros OAuth customizados adicionais que você deseja enviar com a solicitação OAuth.
provider.customParameters = [
"prompt": "consent",
"login_hint": "user@firstadd.onmicrosoft.com"
]
[provider setCustomParameters:@{@"prompt": @"consent", @"login_hint": @"user@firstadd.onmicrosoft.com"}];
Para os parâmetros suportados pela Microsoft, consulte a documentação do Microsoft OAuth . Observe que você não pode transmitir parâmetros exigidos pelo Firebase com
setCustomParameters
. Esses parâmetros são client_id , Response_Type , Redirect_uri , State , Scope e Response_mode .Para permitir que apenas os utilizadores de um determinado inquilino do Azure AD iniciem sessão na aplicação, pode ser utilizado o nome de domínio amigável do inquilino do Azure AD ou o identificador GUID do inquilino. Isso pode ser feito especificando o campo "locatário" no objeto de parâmetros personalizados.
provider.customParameters = [
// Optional "tenant" parameter in case you are using an Azure AD
// tenant. eg. '8eaef023-2b34-4da1-9baa-8bc8c9d6a490' or
// 'contoso.onmicrosoft.com' or "common" for tenant-independent
// tokens. The default value is "common".
"tenant": "TENANT_ID"
]
// Optional "tenant" parameter in case you are using an Azure AD tenant.
// eg. '8eaef023-2b34-4da1-9baa-8bc8c9d6a490' or
// 'contoso.onmicrosoft.com' or "common" for tenant-independent tokens.
// The default value is "common".
provider.customParameters = @{@"tenant": @"TENANT_ID"};
Opcional : Especifique escopos adicionais do OAuth 2.0 além do perfil básico que você deseja solicitar do provedor de autenticação.
provider.scopes = ["mail.read", "calendars.read"]
[provider setScopes:@[@"mail.read", @"calendars.read"]];
Para saber mais, consulte a documentação de permissões e consentimento da Microsoft .
Opcional : se você quiser personalizar a forma como seu aplicativo apresenta o
SFSafariViewController
ouUIWebView
ao exibir o reCAPTCHA para o usuário, crie uma classe personalizada que esteja em conformidade com o protocoloAuthUIDelegate
e passe-a paracredentialWithUIDelegate
.Autentique-se com o Firebase usando o objeto do provedor OAuth.
// Replace nil with the custom class that conforms to AuthUIDelegate
// you created in last step to use a customized web view.
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.
// OAuth access token can also be retrieved:
// (authResult.credential as? OAuthCredential)?.accessToken
// OAuth ID token can also be retrieved:
// (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.
// OAuth access token can also be retrieved:
// ((FIROAuthCredential *)authResult.credential).accessToken
// OAuth ID token can also be retrieved:
// ((FIROAuthCredential *)authResult.credential).idToken
}];
}
}];
Usando o token de acesso OAuth, você pode chamar a API do Microsoft Graph .
Por exemplo, para obter informações básicas de perfil, você pode chamar a API REST, passando o token de acesso no cabeçalho
Authorization
:https://graph.microsoft.com/v1.0/me
Ao contrário de outros provedores suportados pelo Firebase Auth, a Microsoft não fornece um URL de foto e, em vez disso, os dados binários de uma foto de perfil devem ser solicitados por meio da API Microsoft Graph .
Além do token de acesso OAuth, o token de ID OAuth do usuário também pode ser recuperado do objeto
OAuthCredential
. Asub
no token de ID é específica do aplicativo e não corresponderá ao identificador de usuário federado usado pelo Firebase Auth e acessível por meio deuser.providerData[0].uid
. O campo de declaraçãooid
deve ser usado em seu lugar. Ao utilizar um inquilino AZure AD para iniciar sessão, a reivindicaçãooid
será uma correspondência exata. No entanto, para o caso de não locatário, o campooid
é preenchido. Para um ID federado4b2eabcdefghijkl
, ooid
terá o formato00000000-0000-0000-4b2e-abcdefghijkl
.Embora os exemplos acima se concentrem em fluxos de entrada, você também tem a capacidade de vincular um provedor Microsoft a um usuário existente usando
linkWithCredential
. Por exemplo, você pode vincular vários provedores ao mesmo usuário, permitindo que eles façam login com qualquer um deles.Auth().currentUser.link(withCredential: credential) { authResult, error in
if error != nil {
// Handle error.
}
// Microsoft credential is linked to the current user.
// IdP data available in authResult.additionalUserInfo.profile.
// OAuth access token can also be retrieved:
// (authResult.credential as? OAuthCredential)?.accessToken
// OAuth ID token can also be retrieved:
// (authResult.credential as? OAuthCredential)?.idToken
}
[[FIRAuth auth].currentUser
linkWithCredential:credential
completion:^(FIRAuthDataResult * _Nullable authResult, NSError * _Nullable error) {
if (error) {
// Handle error.
}
// Microsoft credential is linked to the current user.
// IdP data available in authResult.additionalUserInfo.profile.
// OAuth access token can also be retrieved:
// ((FIROAuthCredential *)authResult.credential).accessToken
// OAuth ID token can also be retrieved:
// ((FIROAuthCredential *)authResult.credential).idToken
}];
O mesmo padrão pode ser usado com
reauthenticateWithCredential
, que pode ser usado para recuperar credenciais novas para operações confidenciais que exigem 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 can also be retrieved:
// (authResult.credential as? OAuthCredential)?.accessToken
// OAuth ID token can also be retrieved:
// (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 can also be retrieved:
// ((FIROAuthCredential *)authResult.credential).accessToken
// OAuth ID token can also be retrieved:
// ((FIROAuthCredential *)authResult.credential).idToken
}];
Tratamento de erros de conta existente com credenciais diferentes
Se você ativou a configuração Uma conta por endereço de e-mail no console do Firebase , quando um usuário tenta fazer login em um provedor (como a Microsoft) com um e-mail que já existe para o provedor de outro usuário do Firebase (como o Google), o erro FIRAuthErrorCodeAccountExistsWithDifferentCredential
é lançado junto com um objeto FIRAuthCredential
temporário (credencial da Microsoft). Para concluir o login no provedor pretendido, o usuário deve primeiro fazer login no provedor existente (Google) e depois vincular-se ao antigo FIRAuthCredential
(credencial da Microsoft). Isso ficaria conforme ilustrado 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: lidar com o fluxo de login manualmente
Ao contrário de outros provedores OAuth com suporte do Firebase, como Google, Facebook e Twitter, onde o login pode ser feito diretamente com credenciais baseadas em token de acesso OAuth, o Firebase Auth não oferece suporte ao mesmo recurso para provedores como a Microsoft devido à incapacidade do Servidor Firebase Auth para verificar o público dos tokens de acesso Microsoft OAuth. Este é um requisito crítico de segurança e pode expor aplicativos e sites a ataques repetidos em que um token de acesso Microsoft OAuth obtido para um projeto (invasor) pode ser usado para entrar em outro projeto (vítima). Em vez disso, o Firebase Auth oferece a capacidade de lidar com todo o fluxo OAuth e a troca de código de autorização usando o ID do cliente OAuth e o segredo configurados no Firebase Console. Como o código de autorização só pode ser usado em conjunto com um ID/segredo de cliente específico, um código de autorização obtido para um projeto não pode ser usado com outro.
Se for necessário 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 último para trocar a credencial do provedor por um token personalizado.
Depois que um usuário faz login pela primeira vez, uma nova conta de usuário é criada e vinculada às credenciais (ou seja, nome de usuário e senha, número de telefone ou informações do provedor de autenticação) com as quais o usuário fez login. Essa nova conta é armazenada como parte do seu projeto do Firebase e pode ser usada para identificar um usuário em todos os aplicativos do seu projeto, independentemente de como o usuário faz login.
Nos seus aplicativos, você pode obter as informações básicas do perfil do usuário no objeto
User
. Consulte Gerenciar usuários .Nas regras de segurança do Firebase Realtime Database e do Cloud Storage , você pode obter o ID de usuário exclusivo do usuário conectado na variável
auth
e usá-lo para controlar quais dados um usuário pode acessar.
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.
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;
}
Você também pode adicionar código de tratamento de erros para toda a gama de erros de autenticação. Consulte Tratamento de erros .