Eseguire l'autenticazione con Apple con JavaScript

Puoi consentire agli utenti di autenticarsi con Firebase utilizzando il proprio ID Apple tramite l'SDK Firebase per eseguire il flusso di accesso OAuth 2.0 end-to-end.

Prima di iniziare

Per consentire agli utenti di accedere utilizzando Apple, configura prima Accedi con Apple sul sito per sviluppatori di Apple, quindi attiva Apple come provider di accesso per il tuo progetto Firebase.

Partecipa al programma per sviluppatori Apple

Accedi con Apple può essere configurato solo dai membri del programma Apple Developer.

Configurare Accedi con Apple

Sul sito Apple Developer, segui questi passaggi:

  1. Associa il tuo sito web alla tua app come descritto nella prima sezione di Configurare Accedi con Apple per il web. Quando richiesto, registra il seguente URL come URL di ritorno:

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

    Puoi recuperare l'ID progetto Firebase nella Firebase pagina di impostazioni della console.

    Al termine, prendi nota del nuovo ID servizio, che ti servirà nella sezione successiva.

  2. Crea una chiave privata per Accedi con Apple. Nella sezione successiva avrai bisogno della nuova chiave privata e del nuovo ID chiave.
  3. Se utilizzi una delle funzionalità di Firebase Authentication che inviano email agli utenti, tra cui l'accesso tramite link email, la verifica dell'indirizzo email, la revoca della modifica dell'account e altre, configura il servizio di inoltro email privato di Apple e registra noreply@YOUR_FIREBASE_PROJECT_ID.firebaseapp.com (o il dominio del modello email personalizzato) in modo che Apple possa inoltrare le email inviate da Firebase Authentication ad indirizzi email Apple anonimizzati.

Attivare Apple come provider di accesso

  1. Aggiungi Firebase al tuo progetto.
  2. Nella console Firebase, apri la sezione Auth. Nella scheda Metodo di accesso, attiva il provider Apple. Specifica l'ID servizio che hai creato nella sezione precedente. Inoltre, nella sezione di configurazione del flusso di codice OAuth, specifica il tuo ID team Apple e la chiave privata e l'ID chiave che hai creato nella sezione precedente.

Rispettare i requisiti di Apple relativi ai dati anonimizzati

Accedi con Apple offre agli utenti la possibilità di anonimizzare i propri dati, incluso l'indirizzo email, quando accedono. Gli utenti che scelgono questa opzione hanno indirizzi email con il dominio privaterelay.appleid.com. Quando utilizzi Accedi con Apple nella tua app, devi rispettare eventuali norme o termini per gli sviluppatori di Apple applicabili in merito a questi ID Apple anonimizzati.

Ciò include l'ottenimento del consenso dell'utente richiesto prima di associare informazioni personali che consentono l'identificazione diretta a un ID Apple anonimizzato. Quando utilizzi Firebase Authentication, potrebbero essere incluse le seguenti azioni:

  • Collega un indirizzo email a un ID Apple anonimizzato o viceversa.
  • Collegare un numero di telefono a un ID Apple anonimizzato o viceversa
  • Collegare una credenziale social non anonima (Facebook, Google e così via) a un ID Apple anonimizzato o viceversa.

L'elenco riportato sopra non è esaustivo. Consulta il Contratto di licenza del Programma sviluppatori Apple nella sezione Abbonamento del tuo account sviluppatore per assicurarti che la tua app soddisfi i requisiti di Apple.

Gestire il flusso di accesso con l'SDK Firebase

Se stai creando un'app web, il modo più semplice per autenticare i tuoi utenti con Firebase utilizzando i loro account Apple è gestire l'intero flusso di accesso con l'SDK Firebase JavaScript.

Per gestire il flusso di accesso con l'SDK Firebase JavaScript, segui questi passaggi:

  1. Crea un'istanza di un OAuthProvider utilizzando l'ID fornitore corrispondente apple.com.

    Web

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

    Web

    var provider = new firebase.auth.OAuthProvider('apple.com');
  2. Facoltativo:specifica gli ambiti OAuth 2.0 aggiuntivi rispetto a quelli predefiniti che vuoi richiedere al provider di autenticazione.

    Web

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

    Web

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

    Per impostazione predefinita, quando l'opzione Un account per indirizzo email è attivata, Firebase richiede gli ambiti email e nome. Se imposti questa impostazione su Più account per indirizzo email, Firebase non richiede alcun ambito ad Apple, a meno che tu non li specifichi.

  3. Facoltativo:se vuoi visualizzare la schermata di accesso di Apple in una lingua diversa dall'inglese, imposta il parametro locale. Consulta la documentazione di Accedi con Apple per conoscere le lingue supportate.

    Web

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

    Web

    provider.setCustomParameters({
      // Localize the Apple authentication screen in French.
      locale: 'fr'
    });
  4. Esegui l'autenticazione con Firebase utilizzando l'oggetto provider OAuth. Puoi invitare gli utenti ad accedere con i propri account Apple aprendo una finestra popup o reindirizzandoli alla pagina di accesso. Il metodo di reindirizzamento è preferito sui dispositivi mobili.

    • Per accedere con una finestra popup, chiama 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;
      
          // ...
        });
    • Per accedere tramite il reindirizzamento alla pagina di accesso, chiama signInWithRedirect():

    Segui le best practice quando utilizzi signInWithRedirect, linkWithRedirect o reauthenticateWithRedirect.

    Web

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

    Web

    firebase.auth().signInWithRedirect(provider);

    Dopo che l'utente ha completato l'accesso e torna alla pagina, puoi ottenere il risultato dell'accesso chiamando getRedirectResult():

    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;
    
        // ...
      });

    Qui puoi anche rilevare e gestire gli errori. Per un elenco dei codici di errore, consulta il riferimento all'API.

    A differenza di altri provider supportati da Firebase Auth, Apple non fornisce un URL della foto.

    Inoltre, quando l'utente sceglie di non condividere il proprio indirizzo email con l'app, Apple fornisce un indirizzo email univoco per l'utente (del tipo xyz@privaterelay.appleid.com), che condivide con la tua app. Se hai configurato il servizio di inoltro email privato, Apple inoltra le email inviate all'indirizzo anonimizzato all'indirizzo email reale dell'utente.

    Apple condivide le informazioni utente, come il nome visualizzato, con le app solo la prima volta che un utente accede. In genere, Firebase memorizza il nome visualizzato la prima volta che un utente accede con Apple, che puoi ottenere con firebase.auth().currentUser.displayName. Tuttavia, se in precedenza hai utilizzato Apple per far accedere un utente all'app senza utilizzare Firebase, Apple non fornirà a Firebase il nome visualizzato dell'utente.

Riconvalida e collegamento dell'account

Lo stesso pattern può essere utilizzato con reauthenticateWithPopup() e reauthenticateWithRedirect(), che puoi utilizzare per recuperare una nuova credenziale per operazioni sensibili che richiedono l'accesso 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;

    // ...
  });

Inoltre, puoi utilizzare linkWithPopup() e linkWithRedirect() per collegare diversi provider di identità agli account esistenti.

Tieni presente che Apple ti richiede di ottenere il consenso esplicito degli utenti prima di collegare i loro account Apple ad altri dati.

Ad esempio, per collegare un account Facebook all'account Firebase corrente, utilizza il token di accesso ottenuto dall'accesso dell'utente a 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.
    });

Eseguire l'autenticazione con Firebase in un'estensione di Chrome

Se stai creando un'app di estensione di Chrome, consulta la guida Documenti fuori schermo.

Tieni presente che devi comunque verificare il dominio personalizzato con Apple, come per il dominio firebaseapp.com predefinito:

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

Revoca del token

Apple richiede che le app che supportano la creazione di account debbano consentire agli utenti di avviare l'eliminazione del proprio account all'interno dell'app, come descritto nelle linee guida per la revisione dell'App Store.

Per soddisfare questo requisito, implementa i seguenti passaggi:

  1. Assicurati di aver compilato la sezione ID servizi e Configurazione del flusso codice OAuth della configurazione del fornitore di Sign in with Apple, come indicato nella sezione Configurare Sign in with Apple.

  2. Poiché Firebase non memorizza i token utente quando vengono creati con Accedi con Apple, devi chiedere all'utente di accedere di nuovo prima di revocare il token e di eliminare l'account.

    Quindi, ottieni il token di accesso OAuth di Apple da OAuthCredential e utilizzalo per chiamare revokeAccessToken(auth, token) per revocare il token di accesso OAuth di 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.
          // ...
        });
    });
    
  3. Infine, elimina l'account utente (e tutti i dati associati).

Avanzato: autenticazione con Firebase in Node.js

Per eseguire l'autenticazione con Firebase in un'applicazione Node.js:

  1. Chiedi all'utente di accedere con il proprio Account Apple e ottieni il token ID Apple dell'utente. Esistono diversi modi per farlo. Ad esempio, se la tua app Node.js ha un front-end del browser:

    1. Nel tuo backend, genera una stringa casuale ("nonce") e calcola il relativo hash SHA256. Il nonce è un valore monouso utilizzato per convalidare un singolo viaggio di andata e ritorno tra il tuo backend e i server di autenticazione di 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');
    2. Nella pagina di accesso, specifica il nonce sottoposto ad hashing nella configurazione di Accedi con 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. Recupera il token ID Apple dalla risposta di autenticazione POSTata lato server:

      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).
        }
      });
      

    Consulta anche Configurare la pagina web per Accedi con Apple.

  2. Dopo aver ottenuto il token ID Apple dell'utente, utilizzalo per creare un oggetto Credential e poi fai accedere l'utente con la credenziale:

    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);
      });

Passaggi successivi

Dopo che un utente ha eseguito l'accesso per la prima volta, viene creato un nuovo account utente e collegato alle credenziali, ovvero nome utente e password, numero di telefono o informazioni del fornitore di autenticazione, con cui l'utente ha eseguito l'accesso. Questo nuovo account viene archiviato nel tuo progetto Firebase e può essere utilizzato per identificare un utente in tutte le app del progetto, indipendentemente da come accede.

  • Nelle tue app, il modo consigliato per conoscere lo stato di autenticazione dell'utente è impostare un osservatore sull'oggetto Auth. Puoi quindi recuperare le informazioni di base del profilo dell'utente dall'oggetto User. Vedi Gestire gli utenti.

  • Nelle Regole di sicurezza Firebase Realtime Database e Cloud Storage, puoi recuperare l'ID utente univoco dell'utente che ha eseguito l'accesso dalla variabile auth e utilizzarlo per controllare a quali dati può accedere un utente.

Puoi consentire agli utenti di accedere alla tua app utilizzando più provider di autenticazione collegando le credenziali del provider di autenticazione a un account utente esistente.

Per scollegare un utente, chiama 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.
});