Autenticar usando o OpenID Connect em plataformas Apple

Se você fez upgrade para o Firebase Authentication com o Identity Platform, autentique os usuários com o Firebase usando o provedor em compliance com OpenID Connect (OIDC) que quiser. Isso permite usar provedores de identidade que não têm compatibilidade nativa com o Firebase.

Antes de começar

Para fazer login de usuários usando um provedor OIDC, primeiro você precisa coletar algumas informações do provedor:

  • ID do cliente: uma string exclusiva do provedor que identifica seu app. Seu provedor pode atribuir um ID do cliente diferente para cada plataforma compatível. Esse é um dos valores da declaração aud nos tokens de ID emitidos pelo provedor.

  • Chave secreta do cliente: uma string secreta usada pelo provedor para confirmar a propriedade de um ID do cliente. Para cada ID do cliente, você precisará de uma chave secreta correspondente. Esse valor é obrigatório somente se você usa o fluxo de código de autenticação, o que é recomendado.

  • Emissor: uma string que identifica seu provedor. Esse valor precisa ser um URL que, quando anexado com /.well-known/openid-configuration, é o local do documento de descoberta do OIDC do provedor. Por exemplo, se o emissor é https://auth.example.com, o documento de descoberta precisa estar disponível em https://auth.example.com/.well-known/openid-configuration.

Depois de ter as informações acima, ative o OpenID Connect como um provedor de login do seu projeto do Firebase:

  1. Adicione o Firebase ao projeto do iOS.

  2. Se você não fez upgrade para o Firebase Authentication com o Identity Platform, faça isso. A autenticação do OpenID Connect só está disponível em projetos atualizados.

  3. Na página Provedores de login do Console do Firebase, clique em Adicionar novo provedor e, em seguida, clique em OpenID Connect.

  4. Defina se você vai usar o fluxo do código de autorização ou o fluxo de concessão implícito.

    Use sempre o fluxo de código se seu provedor for compatível. O fluxo implícito é menos seguro, e o uso dele não é recomendado.

  5. Dê um nome a esse provedor. O ID do provedor gerado é algo como oidc.example-provider. Você precisará desse ID ao adicionar o código de login ao seu app.

  6. Especifique o ID e a chave secreta do cliente, além da string do emissor do seu provedor. Esses valores precisam ser iguais aos atribuídos pelo provedor.

  7. Salve as mudanças.

Processar o fluxo de login com o SDK do Firebase

A maneira mais fácil de autenticar seus usuários com o Firebase usando o provedor OIDC é processar todo 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:

  1. Adicione esquemas de URL personalizado ao seu projeto do Xcode:

    1. 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.
    2. 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:

      Captura de tela da interface de configuração do esquema de URL personalizado do Xcode
  2. Crie uma instância de um OAuthProvider usando o ID do provedor que você recebeu no Console do Firebase.

    Swift

    var provider = OAuthProvider(providerID: "oidc.example-provider")
    

    Objective-C

    FIROAuthProvider *provider = [FIROAuthProvider providerWithProviderID:@"oidc.example-provider"];
    
  3. Opcional: especifique os parâmetros OAuth personalizados que você quer enviar com a solicitação OAuth.

    Swift

    provider.customParameters = [
      "login_hint": "user@example.com"
    ]
    

    Objective-C

    [provider setCustomParameters:@{@"login_hint": @"user@example.com"}];
    

    Verifique com seu provedor os parâmetros compatíveis com ele. Não é possível transmitir os parâmetros exigidos pelo Firebase com setCustomParameters. Esses parâmetros são client_id, response_type, redirect_uri, state, scope e response_mode.

  4. Opcional: especifique os outros escopos de OAuth 2.0 além do perfil básico que você quer solicitar ao provedor de autenticação.

    Swift

    provider.scopes = ["mail.read", "calendars.read"]
    

    Objective-C

    [provider setScopes:@[@"mail.read", @"calendars.read"]];
    

    Verifique com o provedor os escopos compatíveis.

  5. Opcional: se você quiser personalizar a forma como o app apresenta SFSafariViewController ou UIWebView ao exibir o reCAPTCHA ao usuário, crie uma classe personalizada em conformidade com o protocolo AuthUIDelegate.

  6. Use o objeto de provedor do OAuth para a autenticação no Firebase.

    Swift

    // If you created a custom class that conforms to AuthUIDelegate,
    // pass it instead of nil:
    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
        }
      }
    }
    

    Objective-C

    // If you created a custom class that conforms to AuthUIDelegate,
    // pass it instead of nil:
    [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
        }];
      }
    }];
    
  7. Os exemplos acima se concentram nos fluxos de login, mas também é possível vincular um provedor OIDC a um usuário atual usando linkWithCredential. Por exemplo, vincule vários provedores ao mesmo usuário e permita o login com qualquer um deles.

    Swift

    Auth().currentUser.link(withCredential: credential) { authResult, error in
      if error != nil {
        // Handle error.
      }
      // OIDC 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
    }
    

    Objective-C

    [[FIRAuth auth].currentUser
        linkWithCredential:credential
                completion:^(FIRAuthDataResult * _Nullable authResult, NSError * _Nullable error) {
      if (error) {
        // Handle error.
      }
      // OIDC 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
    }];
    
  8. É possível usar o mesmo padrão com reauthenticateWithCredential, que pode ser utilizado para recuperar credenciais novas de operações confidenciais que exigem um login recente.

    Swift

    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
    }
    

    Objective-C

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

Processar o fluxo de login manualmente

Se você já tiver implementado o fluxo de login do OpenID Connect no seu app, poderá usar o token de ID diretamente para autenticar com o Firebase:

Swift

let credential = OAuthProvider.credential(
    withProviderID: "oidc.example-provider",  // As registered in Firebase console.
    idToken: idToken,  // ID token from OpenID Connect flow.
    rawNonce: nil
)
Auth.auth().signIn(with: credential) { authResult, error in
    if error {
        // Handle error.
        return
    }
    // User is signed in.
    // IdP data available in authResult?.additionalUserInfo?.profile
}

Objective-C

FIROAuthCredential *credential =
    [FIROAuthProvider credentialWithProviderID:@"oidc.example-provider"  // As registered in Firebase console.
                                       IDToken:idToken  // ID token from OpenID Connect flow.
                                      rawNonce:nil];
[[FIRAuth auth] signInWithCredential:credential
                          completion:^(FIRAuthDataResult * _Nullable authResult,
                                      NSError * _Nullable error) {
    if (error != nil) {
        // Handle error.
        return;
    }
    // User is signed in.
    // IdP data available in authResult.additionalUserInfo.profile
}];

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 do Firebase Realtime Database e do Cloud Storage, é possível acessar na variável auth o ID exclusivo do usuário que fez login e usar esse ID para controlar quais dados uma pessoa 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:.

Swift

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

Objective-C

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.