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 para realizar todo o fluxo de login do OAuth 2.0.
Antes de começar
Para fazer login de usuários usando a Apple, primeiro configure o recurso Iniciar sessão com a Apple no site do desenvolvedor da Apple e ative-a como um provedor de login para seu projeto do Firebase.
Participar 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.
Configurar o recurso "Iniciar sessão com a Apple"
No site do Desenvolvedor da Apple, faça o seguinte:
-
Associe seu site ao app conforme descrito na primeira seção de Configurar o login com a Apple para 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.
- Crie uma chave privada de Início de sessão com a Apple. Você precisará da sua nova chave privada e do ID da chave na próxima seção.
-
Se você usar qualquer um dos recursos do Firebase Authentication que enviam e-mails aos usuários, incluindo o login por link de e-mail, a verificação de endereço de e-mail, a revogação de alterações na conta, entre 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 redirecionar os e-mails enviados pelo Firebase Authentication para endereços de e-mail anônimos da Apple.
Ativar a Apple como um provedor de login
- Adicione o Firebase ao seu projeto.
- No console do Firebase, abra a seção Autenticação. Na guia Método de login, ative o provedor da 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.
Atenda os requisitos de dados anônimos da Apple
O recurso Iniciar sessão com a Apple permite que os usuários decidam se querem que seus dados fiquem 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 anonimizado ou vice-versa.
- Vincular um número de telefone a um ID Apple anonimizado ou vice-versa.
- Vincular uma credencial social não anônima (Facebook, Google etc.) a um ID Apple anonimizado 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:
Crie uma instância de um OAuthProvider usando o ID de provedor apple.com correspondente.
Web
import { OAuthProvider } from "firebase/auth"; const provider = new OAuthProvider('apple.com');
Web
var provider = new firebase.auth.OAuthProvider('apple.com');
Opcional: especifique escopos adicionais do OAuth 2.0 além do padrão que você quer solicitar ao provedor de autenticação.
Web
provider.addScope('email'); provider.addScope('name');
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ê mudar 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.
Opcional: se você quiser mostrar a tela de login da Apple em um idioma diferente do inglês, configure o parâmetro
locale
. Consulte Fazer login com os documentos da Apple para ver as localidades compatíveis.Web
provider.setCustomParameters({ // Localize the Apple authentication screen in French. locale: 'fr' });
Web
provider.setCustomParameters({ // Localize the Apple authentication screen in French. locale: 'fr' });
Use o objeto de provedor do OAuth para a autenticação com o Firebase. Você pode solicitar que os usuários façam login com as respectivas 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()
: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; // IdP data available using getAdditionalUserInfo(result) // ... }) .catch((error) => { // Handle Errors here. const errorCode = error.code; const errorMessage = error.message; // The email of the user's account used. const email = error.customData.email; // The credential that was used. const credential = OAuthProvider.credentialFromError(error); // ... });
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; // IdP data available using getAdditionalUserInfo(result) // ... }) .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()
:
Web
import { getAuth, signInWithRedirect } from "firebase/auth"; const auth = getAuth(); signInWithRedirect(auth, provider);
Web
firebase.auth().signInWithRedirect(provider);
Depois que o usuário fizer login e retornar à página, chame
getRedirectResult()
para saber o resultado do login.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.customData.email; // The credential that was used. const credential = OAuthProvider.credentialFromError(error); // ... });
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; // IdP data available in result.additionalUserInfo.profile. // ... } // 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 é aqui que você identifica e corrige erros. Para conferir uma lista de códigos de erro, consulte a Referência da API.
Diferentemente de outros provedores que recebem suporte do Firebase Auth, a Apple não fornece um URL de foto.
Além disso, quando o usuário opta por não compartilhar o e-mail 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 redirecionamento de e-mail privado, a Apple encaminhará os e-mails enviados ao endereço anonimizado 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. Ele pode ser obtido 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:
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.customData.email; // The credential that was used. const credential = OAuthProvider.credentialFromError(error); // ... });
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; // IdP data available in result.additionalUserInfo.profile. // ... }) .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 o 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 do login do usuário no Facebook:
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. });
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. });
Autenticar com Firebase em uma extensão do Chrome
Se você estiver criando um app de extensão do Google Chrome, consulte a Guia de documentos fora da tela.
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
Revogação de token
A Apple exige que os apps compatíveis com a criação de contas permitam que os usuários iniciem a exclusão da conta no app, conforme descrito nas Diretrizes de avaliação da App Store.
Para atender a esse requisito, implemente as seguintes etapas:
Verifique se você preencheu as seções ID dos serviços e Configuração do fluxo do código OAuth da configuração de provedor de Login com a Apple, conforme descrito na seção Configurar o Login com a Apple.
Como o Firebase não armazena tokens de usuário quando os usuários são criados com o Login com a Apple, você precisa solicitar que o usuário faça login novamente antes de revogar o token e excluir a conta.
Em seguida, receba o token de acesso OAuth da Apple de
OAuthCredential
e use-o para chamarrevokeAccessToken(auth, token)
e revogar o token de acesso OAuth da Apple.const provider = new OAuthProvider('apple.com'); provider.addScope('email'); provider.addScope('name'); const auth = getAuth(); signInWithPopup(auth, provider).then(result => { // Get the Apple OAuth access token. const credential = OAuthProvider.credentialFromResult(result); const accessToken = credential.accessToken; // Revoke the Apple OAuth access token. revokeAccessToken(auth, accessToken) .then(() => { // Token revoked. // Delete the user account. // ... }) .catch(error => { // An error happened. // ... }); });
Por fim, exclua a conta de usuário e todos os dados associados a ela.
Avançado: autenticar com o Firebase no Node.js
Para autenticar com o Firebase em um aplicativo Node.js:
Faça o 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:
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 o seu back-end e os servidores de autenticação da Apple.
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.slice(0, length); }; const unhashedNonce = generateNonce(10); // SHA256-hashed nonce in hex const hashedNonceHex = crypto.createHash('sha256') .update(unhashedNonce).digest().toString('hex');
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.slice(0, length); }; const unhashedNonce = generateNonce(10); // SHA256-hashed nonce in hex const hashedNonceHex = crypto.createHash('sha256') .update(unhashedNonce).digest().toString('hex');
Na página de login, especifique o nonce com hash na configuração "Iniciar sessão 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>
Receba 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.
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:
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); });
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 objetoUser
. 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
:
Web
import { getAuth, signOut } from "firebase/auth"; const auth = getAuth(); signOut(auth).then(() => { // Sign-out successful. }).catch((error) => { // An error happened. });
Web
firebase.auth().signOut().then(() => { // Sign-out successful. }).catch((error) => { // An error happened. });