Catch up on everthing we announced at this year's Firebase Summit. Learn more

Autenticar usando a Apple com JavaScript

Você pode usar o SDK do Firebase para permitir que os usuários façam a autenticação com o Firebase usando o ID Apple deles para realizar todo o fluxo de login do OAuth 2.0.

Antes de começar

Para fazer login com usuários usando a Apple, primeiro configure o recurso Iniciar sessão com a Apple no site do desenvolvedor da Apple e a ative como um provedor de login para seu projeto do Firebase.

Participe do Programa para desenvolvedores da Apple

O recurso Iniciar sessão com a Apple só pode ser configurado por membros do Programa para desenvolvedores da Apple.

Como configurar o recurso "Iniciar sessão com a Apple"

No site do Desenvolvedor da Apple, faça o seguinte:

  1. Associe seu site ao seu aplicativo conforme descrito na primeira seção de Configurar Login com a Apple para a Web. Quando solicitado, registre o URL a seguir como um URL de retorno:

    https://YOUR_FIREBASE_PROJECT_ID.firebaseapp.com/__/auth/handler

    Você pode acessar o ID do projeto do Firebase na página de configurações do Console do Firebase.

    Quando terminar, anote o novo ID de serviço, que será necessário na próxima seção.

  2. Crie um Login com a chave privada da Apple. Você precisará da sua nova chave privada e do ID da chave na próxima seção.
  3. Se você usar qualquer um dos recursos do Firebase Authentication que enviam e-mails para os usuários, incluindo login com o link de e-mail, verificação de endereço de e-mail, revogação de alteração de conta e outros, configure o serviço de redirecionamento de e-mail privado da Apple e registre noreply@YOUR_FIREBASE_PROJECT_ID.firebaseapp.com ou seu domínio de modelo de e-mail personalizado para que a Apple possa retransmitir os e-mails enviados pelo Firebase Authentication para endereços anônimos de e-mail da Apple.

Ativar a Apple como um provedor de login

  1. Adicione o Firebase ao seu projeto.
  2. No Console do Firebase, abra a seção Auth. Na guia Método de login, ative o provedor Apple. Especifique o ID do serviço que você criou na seção anterior. Além disso, na seção de configuração do fluxo de código do OAuth, especifique o ID de equipe da Apple, a chave privada e o ID da chave que você criou na seção anterior.

Obedeça aos requisitos de dados anônimos da Apple

O recurso Iniciar sessão com a Apple permite que os usuários deixem seus dados anônimos, incluindo o endereço de e-mail, ao fazer login. Os usuários que escolhem essa opção têm endereços de e-mail com o domínio privaterelay.appleid.com. Ao usar o recurso Iniciar sessão com a Apple no seu aplicativo, você precisa estar em conformidade com todos os termos ou políticas do desenvolvedor aplicáveis da Apple relacionados a esses IDs anônimos da Apple.

Isso inclui obter o consentimento do usuário exigido antes de associar qualquer informação pessoal de identificação direta a um ID anônimo da Apple. O uso do Firebase Authentication pode incluir as seguintes ações:

  • Vincular um endereço de e-mail a um ID Apple ou vice-versa.
  • Vincular um número de telefone a um ID Apple anônimo ou vice-versa.
  • Vincular uma credencial social não anônima (Facebook, Google etc.) a um ID Apple anônimo ou vice-versa.

Essa não é uma lista completa. Consulte o "Contrato de licença do programa para desenvolvedores da Apple" na seção de associação da sua conta de desenvolvedor para verificar se o app atende aos requisitos da Apple.

Processar o fluxo de login com o SDK do Firebase

Se você estiver criando um app da Web, a maneira mais fácil de autenticar seus usuários com o Firebase usando contas da Apple é gerenciar todo o fluxo de login com o SDK do Firebase para JavaScript.

Para processar o fluxo de login com o SDK do Firebase para JavaScript, siga estas etapas:

  1. Crie uma instância de um OAuthProvider usando o ID de provedor apple.com correspondente.

    Versão 9 para a Web

    import { OAuthProvider } from "firebase/auth";
    
    const provider = new OAuthProvider('apple.com');

    Versão 8 para a Web

    var provider = new firebase.auth.OAuthProvider('apple.com');
  2. Opcional: especifique escopos adicionais do OAuth 2.0 além do padrão que você quer solicitar ao provedor de autenticação.

    Versão 9 para a Web

    provider.addScope('email');
    provider.addScope('name');

    Versão 8 para a Web

    provider.addScope('email');
    provider.addScope('name');

    Por padrão, quando a opção Uma conta por endereço de e-mail é ativada, o Firebase solicita escopos de nome e e-mail. Se você alterar essa configuração para Várias contas por endereço de e-mail, o Firebase não solicitará nenhum escopo da Apple, a não ser que você os especifique.

  3. Opcional: se você quiser exibir a tela de login da Apple em um idioma diferente do inglês, defina o parâmetro locale. Consulte Fazer login com os documentos da Apple para ver as localidades com suporte.

    Versão 9 para a Web

    provider.setCustomParameters({
      // Localize the Apple authentication screen in French.
      locale: 'fr'
    });

    Versão 8 para a Web

    provider.setCustomParameters({
      // Localize the Apple authentication screen in French.
      locale: 'fr'
    });
  4. Use o objeto de provedor do OAuth para a autenticação no Firebase. Você pode solicitar que os usuários façam login com suas "Contas da Apple" abrindo uma janela pop-up ou redirecionando para a página de login. O método de redirecionamento é recomendável para dispositivos móveis.

    • Para fazer login com uma janela pop-up, chame signInWithPopup():

      Versão 9 para a Web

      import { getAuth, signInWithPopup, OAuthProvider } from "firebase/auth";
      
      const auth = getAuth();
      signInWithPopup(auth, provider)
        .then((result) => {
          // The signed-in user info.
          const user = result.user;
      
          // Apple credential
          const credential = OAuthProvider.credentialFromResult(result);
          const accessToken = credential.accessToken;
          const idToken = credential.idToken;
      
          // ...
        })
        .catch((error) => {
          // Handle Errors here.
          const errorCode = error.code;
          const errorMessage = error.message;
          // The email of the user's account used.
          const email = error.email;
          // The credential that was used.
          const credential = OAuthProvider.credentialFromError(error);
      
          // ...
        });

      Versão 8 para a Web

      firebase
        .auth()
        .signInWithPopup(provider)
        .then((result) => {
          /** @type {firebase.auth.OAuthCredential} */
          var credential = result.credential;
      
          // The signed-in user info.
          var user = result.user;
      
          // You can also get the Apple OAuth Access and ID Tokens.
          var accessToken = credential.accessToken;
          var idToken = credential.idToken;
      
          // ...
        })
        .catch((error) => {
          // Handle Errors here.
          var errorCode = error.code;
          var errorMessage = error.message;
          // The email of the user's account used.
          var email = error.email;
          // The firebase.auth.AuthCredential type that was used.
          var credential = error.credential;
      
          // ...
        });
    • Para redirecionar os usuários à página de login, chame signInWithRedirect():

      Versão 9 para a Web

      import { getAuth, signInWithRedirect } from "firebase/auth";
      
      const auth = getAuth();
      signInWithRedirect(auth, provider);

      Versão 8 para a Web

      firebase.auth().signInWithRedirect(provider);

      Depois que o usuário concluir o login e retornar à página, você poderá ver o resultado do login chamando getRedirectResult():

      Versão 9 para a Web

      import { getAuth, getRedirectResult, OAuthProvider } from "firebase/auth";
      
      // Result from Redirect auth flow.
      const auth = getAuth();
      getRedirectResult(auth)
        .then((result) => {
          const credential = OAuthProvider.credentialFromResult(result);
          if (credential) {
            // You can also get the Apple OAuth Access and ID Tokens.
            const accessToken = credential.accessToken;
            const idToken = credential.idToken;
          }
          // The signed-in user info.
          const user = result.user;
        })
        .catch((error) => {
          // Handle Errors here.
          const errorCode = error.code;
          const errorMessage = error.message;
          // The email of the user's account used.
          const email = error.email;
          // The credential that was used.
          const credential = OAuthProvider.credentialFromError(error);
      
          // ...
        });

      Versão 8 para a Web

      // Result from Redirect auth flow.
      firebase
        .auth()
        .getRedirectResult()
        .then((result) => {
          if (result.credential) {
            /** @type {firebase.auth.OAuthCredential} */
            var credential = result.credential;
      
            // You can get the Apple OAuth Access and ID Tokens.
            var accessToken = credential.accessToken;
            var idToken = credential.idToken;
      
            // ...
          }
          // The signed-in user info.
          var user = result.user;
        })
        .catch((error) => {
          // Handle Errors here.
          var errorCode = error.code;
          var errorMessage = error.message;
          // The email of the user's account used.
          var email = error.email;
          // The firebase.auth.AuthCredential type that was used.
          var credential = error.credential;
      
          // ...
        });

      Também é nesse local que você identifica e corrige erros. Para receber uma lista de códigos de erro, consulte a Referência da API.

    Diferentemente de outros provedores que suportam o Firebase Auth, a Apple não fornece um URL de foto.

    Além disso, quando o usuário opta por não compartilhar e-mails com o app, a Apple fornece um endereço de e-mail exclusivo para esse usuário, no formato xyz@privaterelay.appleid.com, que é compartilhado com seu app. Se você tiver configurado o serviço de retransmissão de e-mail privado, a Apple encaminhará os e-mails enviados ao endereço anônimo para o endereço de e-mail real do usuário.

    A Apple só compartilha informações do usuário, como o nome de exibição, com apps na primeira vez que um usuário faz login. Normalmente, o Firebase armazena o nome de exibição na primeira vez que um usuário faz login com a Apple, que você pode obter com firebase.auth().currentUser.displayName. No entanto, se você já usou a Apple para fazer login de um usuário no app sem usar o Firebase, a Apple não fornecerá ao Firebase o nome de exibição do usuário.

Reautenticação e vinculação de contas

O mesmo padrão pode ser usado com reauthenticateWithPopup() e reauthenticateWithRedirect(), que você pode usar para recuperar uma nova credencial para operações confidenciais que exigem login recente:

Versão 9 para a Web

import { getAuth, reauthenticateWithPopup, OAuthProvider } from "firebase/auth";

// Result from Redirect auth flow.
const auth = getAuth();
const provider = new OAuthProvider('apple.com');

reauthenticateWithPopup(auth.currentUser, provider)
  .then((result) => {
    // User is re-authenticated with fresh tokens minted and can perform
    // sensitive operations like account deletion, or updating their email
    // address or password.

    // The signed-in user info.
    const user = result.user;

    // You can also get the Apple OAuth Access and ID Tokens.
    const credential = OAuthProvider.credentialFromResult(result);
    const accessToken = credential.accessToken;
    const idToken = credential.idToken;

    // ...
  })
  .catch((error) => {
    // Handle Errors here.
    const errorCode = error.code;
    const errorMessage = error.message;
    // The email of the user's account used.
    const email = error.email;
    // The credential that was used.
    const credential = OAuthProvider.credentialFromError(error);

    // ...
  });

Versão 8 para a Web

const provider = new firebase.auth.OAuthProvider('apple.com');

firebase
  .auth()
  .currentUser
  .reauthenticateWithPopup(provider)
  .then((result) => {
    // User is re-authenticated with fresh tokens minted and can perform
    // sensitive operations like account deletion, or updating their email
    // address or password.
    /** @type {firebase.auth.OAuthCredential} */
    var credential = result.credential;

    // The signed-in user info.
    var user = result.user;
     // You can also get the Apple OAuth Access and ID Tokens.
    var accessToken = credential.accessToken;
    var idToken = credential.idToken;

    // ...
  })
  .catch((error) => {
    // Handle Errors here.
    var errorCode = error.code;
    var errorMessage = error.message;
    // The email of the user's account used.
    var email = error.email;
    // The firebase.auth.AuthCredential type that was used.
    var credential = error.credential;

    // ...
  });

Além disso, você pode usar linkWithPopup() e linkWithRedirect() para vincular diferentes provedores de identidade a contas existentes.

Observe que a Apple exige que você receba consentimento explícito dos usuários antes de vincular as contas da Apple a outros dados.

Por exemplo, para vincular uma conta do Facebook à conta atual do Firebase, use o token de acesso da assinatura do usuário no Facebook:

Versão 9 para a Web

import { getAuth, linkWithPopup, FacebookAuthProvider } from "firebase/auth";

const auth = getAuth();
const provider = new FacebookAuthProvider();
provider.addScope('user_birthday');

// Assuming the current user is an Apple user linking a Facebook provider.
linkWithPopup(auth.currentUser, provider)
    .then((result) => {
      // Facebook credential is linked to the current Apple user.
      // ...

      // The user can now sign in to the same account
      // with either Apple or Facebook.
    })
    .catch((error) => {
      // Handle error.
    });

Versão 8 para a Web

const provider = new firebase.auth.FacebookAuthProvider();
provider.addScope('user_birthday');

// Assuming the current user is an Apple user linking a Facebook provider.
firebase.auth().currentUser.linkWithPopup(provider)
    .then((result) => {
      // Facebook credential is linked to the current Apple user.
      // Facebook additional data available in result.additionalUserInfo.profile,

      // Additional Facebook OAuth access token can also be retrieved.
      // result.credential.accessToken

      // The user can now sign in to the same account
      // with either Apple or Facebook.
    })
    .catch((error) => {
      // Handle error.
    });

Fazer autenticação com o Firebase em uma extensão do Chrome

Se você está criando um app de extensão do Chrome, é necessário adicionar o ID da extensão:

  1. Abra seu projeto no Console do Firebase.
  2. Na seção Autenticação, abra a página Método de login.
  3. Adicione um URI como o seguinte à lista de domínios autorizados:
    chrome-extension://CHROME_EXTENSION_ID

Somente as operações pop-up (signInWithPopup, linkWithPopup e reauthenticateWithPopup) estão disponíveis para as extensões do Chrome. Isso ocorre porque as extensões não podem usar redirecionamentos de HTTP. Chame esses métodos usando uma página em segundo plano porque, se usar o pop-up de ação do navegador, ele será cancelado pelo pop-up de autenticação. Os métodos pop-up só podem ser usados em extensões que usam o Manifest V2. O Manifest V3 mais recente só permite scripts em segundo plano na forma de service workers, que não podem realizar as operações pop-up.

No arquivo de manifesto da sua extensão do Chrome, adicione o URL https://apis.google.com à lista de permissões content_security_policy.

Observe que você ainda precisa verificar o domínio personalizado com a Apple de forma semelhante ao domínio padrão firebaseapp.com:

http://auth.custom.example.com/.well-known/apple-developer-domain-association.txt

Avançado: autenticar com o Firebase no Node.js

Para autenticar com o Firebase em um aplicativo Node.js:

  1. Faça login do usuário com a conta da Apple e receba o token do ID da Apple do usuário. Isso pode ser feito de várias maneiras. Por exemplo, se seu app Node.js tiver um front-end de navegador:

    1. No seu back-end, gere uma string aleatória ("nonce") e calcule o hash SHA256 dela. O nonce é um valor de uso único utilizado para validar uma única ida e volta entre os servidores de back-end e de autenticação da Apple.

      Versão 9 para a Web

      const crypto = require("crypto");
      const string_decoder = require("string_decoder");
      
      // Generate a new random string for each sign-in
      const generateNonce = (length) => {
        const decoder = new string_decoder.StringDecoder("ascii");
        const buf = Buffer.alloc(length);
        let nonce = "";
        while (nonce.length < length) {
          crypto.randomFillSync(buf);
          nonce = decoder.write(buf);
        }
        return nonce.substr(0, length);
      };
      
      const unhashedNonce = generateNonce(10);
      
      // SHA256-hashed nonce in hex
      const hashedNonceHex = crypto.createHash('sha256')
        .update(unhashedNonce).digest().toString('hex');

      Versão 8 para a Web

      const crypto = require("crypto");
      const string_decoder = require("string_decoder");
      
      // Generate a new random string for each sign-in
      const generateNonce = function(length) {
        const decoder = new string_decoder.StringDecoder("ascii");
        const buf = Buffer.alloc(length);
        var nonce = "";
        while (nonce.length < length) {
          crypto.randomFillSync(buf);
          nonce = decoder.write(buf);
        }
        return nonce.substr(0, length);
      };
      
      const unhashedNonce = generateNonce(10);
      
      // SHA256-hashed nonce in hex
      const hashedNonceHex = crypto.createHash('sha256')
        .update(unhashedNonce).digest().toString('hex');
    2. Na página de login, especifique o nonce com hash na configuração "Fazer login com a Apple":

      <script src="https://appleid.cdn-apple.com/appleauth/static/jsapi/appleid/1/en_US/appleid.auth.js"></script>
      <div id="appleid-signin" data-color="black" data-border="true" data-type="sign in"></div>
      <script>
          AppleID.auth.init({
              clientId: YOUR_APPLE_CLIENT_ID,
              scope: 'name email',
              redirectURI: URL_TO_YOUR_REDIRECT_HANDLER,  // See the next step.
              state: '[STATE]',  // Optional value that Apple will send back to you
                                 // so you can return users to the same context after
                                 // they sign in.
              nonce: HASHED_NONCE  // The hashed nonce you generated in the previous step.
          });
      </script>
      
    3. Receber o token do ID da Apple da resposta do POSTed auth no servidor:

      app.post('/redirect', (req, res) => {
        const savedState = req.cookies.__session;
        const code = req.body.code;
        const state = req.body.state;
        const appleIdToken = req.body.id_token;
        if (savedState !== state || !code) {
          res.status(403).send('403: Permission denied');
        } else {
          // Sign in with Firebase using appleIdToken. (See next step).
        }
      });
      

    Consulte também Como configurar sua página da Web para fazer login com a Apple.

  2. Depois de receber o token do ID da Apple do usuário, use-o para criar um objeto Credential e, em seguida, faça o login do usuário com a credencial:

    Versão 9 para a Web

    import { getAuth, signInWithCredential, OAuthProvider } from "firebase/auth";
    
    const auth = getAuth();
    
    // Build Firebase credential with the Apple ID token.
    const provider = new OAuthProvider('apple.com');
    const authCredential = provider.credential({
      idToken: appleIdToken,
      rawNonce: unhashedNonce,
    });
    
    // Sign in with credential form the Apple user.
    signInWithCredential(auth, authCredential)
      .then((result) => {
        // User signed in.
      })
      .catch((error) => {
        // An error occurred. If error.code == 'auth/missing-or-invalid-nonce',
        // make sure you're sending the SHA256-hashed nonce as a hex string
        // with your request to Apple.
        console.log(error);
      });

    Versão 8 para a Web

    // Build Firebase credential with the Apple ID token.
    const provider = new firebase.auth.OAuthProvider('apple.com');
    const authCredential = provider.credential({
      idToken: appleIdToken,
      rawNonce: unhashedNonce,
    });
    
    // Sign in with credential form the Apple user.
    firebase.auth().signInWithCredential(authCredential)
      .then((result) => {
        // User signed in.
      })
      .catch((error) => {
        // An error occurred. If error.code == 'auth/missing-or-invalid-nonce',
        // make sure you're sending the SHA256-hashed nonce as a hex string
        // with your request to Apple.
        console.log(error);
      });

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.

  • Nos apps, a maneira recomendada de saber o status de autenticação do seu usuário é definindo um observador no objeto Auth. É possível, então, receber as informações básicas de perfil do usuário do objeto User. Consulte Gerenciar usuários.

  • Nas Regras de segurança do Firebase Realtime Database e do Cloud Storage, é possível receber o ID exclusivo do usuário conectado da variável auth e usar esse ID 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:

Versão 9 para a Web

import { getAuth, signOut } from "firebase/auth";

const auth = getAuth();
signOut(auth).then(() => {
  // Sign-out successful.
}).catch((error) => {
  // An error happened.
});

Versão 8 para a Web

firebase.auth().signOut().then(() => {
  // Sign-out successful.
}).catch((error) => {
  // An error happened.
});