Uwierzytelnij przez Apple z JavaScriptem

Możesz umożliwić użytkownikom uwierzytelnianie się w Firebase za pomocą identyfikatora Apple ID, korzystając z pakietu Firebase SDK do przeprowadzenia pełnego procesu logowania OAuth 2.0.

Zanim zaczniesz

Aby umożliwić użytkownikom logowanie się za pomocą Apple, najpierw skonfiguruj funkcję Zaloguj się przez Apple w witrynie dla deweloperów Apple, a potem włącz Apple jako dostawcę logowania w projekcie w Firebase.

Dołącz do programu Apple Developer Program

Funkcję Zaloguj się przez Apple mogą konfigurować tylko członkowie programu Apple Developer Program.

Konfigurowanie funkcji Zaloguj się przez Apple

W witrynie dla deweloperów Apple wykonaj te czynności:

  1. Powiąż swoją witrynę z aplikacją zgodnie z opisem w pierwszej sekcji artykułu Konfigurowanie funkcji Zaloguj się przez Apple w internecie. Gdy pojawi się prośba, zarejestruj ten adres URL jako adres URL przekierowania:

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

    Identyfikator projektu w Firebase znajdziesz w Ustawienia > Ogólne tab konsoli Firebase.

    Gdy skończysz, zanotuj nowy identyfikator usługi, który będzie Ci potrzebny w następnej sekcji.

  2. Utwórz klucz prywatny funkcji Zaloguj się przez Apple. W następnej sekcji będziesz potrzebować nowego klucza prywatnego i identyfikatora klucza.
  3. Jeśli używasz którejś z funkcji Firebase Authentication, która wysyła e-maile do użytkowników, w tym logowania za pomocą linku w e-mailu, weryfikacji adresu e-mail, odwoływania zmian konta itp., skonfiguruj usługę przekazywania prywatnych e-maili Apple i zarejestruj noreply@YOUR_FIREBASE_PROJECT_ID.firebaseapp.com (lub domenę niestandardowego szablonu e-maila), aby Apple mogło przekazywać e-maile wysyłane przez Firebase Authentication na anonimowe adresy e-mail Apple.

Włączanie Apple jako dostawcy logowania

  1. Dodaj Firebase do projektu.
  2. W konsoli Firebase otwórz Zabezpieczenia > Uwierzytelnianie.
  3. Na karcie Metoda logowania włącz dostawcę logowania Apple. Określ identyfikator usługi utworzony w poprzedniej sekcji. W sekcji Konfiguracja procesu kodu OAuth określ też identyfikator zespołu Apple oraz klucz prywatny i identyfikator klucza utworzone w poprzedniej sekcji.

Spełnianie wymagań Apple dotyczących anonimowych danych

Funkcja Zaloguj się przez Apple umożliwia użytkownikom anonimizację danych, w tym adresu e-mail, podczas logowania. Użytkownicy, którzy wybiorą tę opcję, będą mieć adresy e-mail w domenie privaterelay.appleid.com. Jeśli używasz funkcji Zaloguj się przez Apple w swojej aplikacji, musisz przestrzegać wszystkich obowiązujących zasad i warunków dla deweloperów Apple dotyczących tych anonimowych identyfikatorów Apple.

Obejmuje to uzyskanie wymaganej zgody użytkownika przed powiązaniem jakichkolwiek informacji osobowych umożliwiających bezpośrednią identyfikację z anonimowym identyfikatorem Apple. W przypadku korzystania z Uwierzytelniania Firebase może to obejmować te działania:

  • Powiązanie adresu e-mail z anonimowym identyfikatorem Apple lub odwrotnie.
  • Powiązanie numeru telefonu z anonimowym identyfikatorem Apple lub odwrotnie.
  • Powiązanie nieanonimowych danych logowania w mediach społecznościowych (Facebook, Google itp.) z anonimowym identyfikatorem Apple lub odwrotnie.

Powyższa lista nie jest wyczerpująca. Aby mieć pewność, że Twoja aplikacja spełnia wymagania Apple, zapoznaj się z Umową licencyjną programu Apple Developer Program w sekcji Członkostwo na koncie dewelopera, aby mieć pewność, że Twoja aplikacja spełnia wymagania Apple.

Obsługa procesu logowania za pomocą pakietu Firebase SDK

Jeśli tworzysz aplikację internetową, najłatwiejszym sposobem uwierzytelniania użytkowników w Firebase za pomocą ich kont Apple jest obsługa całego procesu logowania za pomocą pakietu Firebase JavaScript SDK.

Aby obsługiwać proces logowania za pomocą pakietu Firebase JavaScript SDK:

  1. Utwórz instancję OAuthProvider , używając odpowiedniego identyfikatora dostawcy apple.com.

    Web

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

    Web

    var provider = new firebase.auth.OAuthProvider('apple.com');
  2. Opcjonalnie: określ dodatkowe zakresy OAuth 2.0 poza domyślnymi, o które chcesz poprosić dostawcę uwierzytelniania.

    Web

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

    Web

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

    Domyślnie, gdy włączona jest opcja Jedno konto na adres e-mail, Firebase prosi o zakresy adresu e-mail i nazwy. Jeśli zmienisz to ustawienie na Wiele kont na adres e-mail, Firebase nie będzie prosić Apple o żadne zakresy chyba że je określisz.

  3. Opcjonalnie: jeśli chcesz wyświetlać ekran logowania Apple w języku innym niż angielski, ustaw parametr locale. Obsługiwane ustawienia regionalne znajdziesz w dokumentacji funkcji Zaloguj się przez Apple.

    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. Uwierzytelnij się w Firebase za pomocą obiektu dostawcy OAuth. Możesz poprosić użytkowników o zalogowanie się za pomocą kont Apple, otwierając wyskakujące okienko lub przekierowując ich na stronę logowania. Na urządzeniach mobilnych preferowana jest metoda przekierowania.

    • Aby zalogować się za pomocą wyskakującego okienka, wywołaj funkcję 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;
      
          // ...
        });
    • Aby zalogować się przez przekierowanie na stronę logowania, wywołaj funkcję signInWithRedirect():

    Podczas korzystania z funkcji signInWithRedirect, linkWithRedirect lub reauthenticateWithRedirect stosuj sprawdzone metody.

    Web

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

    Web

    firebase.auth().signInWithRedirect(provider);

    Gdy użytkownik zakończy logowanie i wróci na stronę, możesz uzyskać wynik logowania, wywołując funkcję 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;
    
        // ...
      });

    W tym miejscu możesz też przechwytywać i obsługiwać błędy. Listę kodów błędów znajdziesz w dokumentacji API.

    W przeciwieństwie do innych dostawców obsługiwanych przez Firebase Auth Apple nie udostępnia adresu URL zdjęcia.

    Gdy użytkownik zdecyduje się nie udostępniać swojego adresu e-mail aplikacji, Apple udostępni mu unikalny adres e-mail (w formacie xyz@privaterelay.appleid.com), który udostępni Twojej aplikacji. Jeśli skonfigurujesz usługę przekazywania prywatnych e-maili, Apple będzie przekazywać e-maile wysyłane na anonimowy adres na prawdziwy adres e-mail użytkownika.

    Apple udostępnia aplikacjom informacje o użytkownikach, takie jak wyświetlana nazwa, tylko przy pierwszym logowaniu. Zwykle Firebase zapisuje nazwę wyświetlaną przy pierwszym logowaniu użytkownika za pomocą Apple, którą możesz uzyskać za pomocą funkcji firebase.auth().currentUser.displayName. Jeśli jednak wcześniej logowałeś(-aś) użytkownika w aplikacji za pomocą Apple bez użycia Firebase, Apple nie udostępni Firebase nazwy wyświetlanej użytkownika.

Ponowne uwierzytelnianie i łączenie kont

Tego samego wzorca można używać z funkcjami reauthenticateWithPopup() i reauthenticateWithRedirect(), których możesz użyć do pobrania nowych danych logowania w przypadku operacji wymagających niedawnego logowania:

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;

    // ...
  });

Możesz też użyć funkcji linkWithPopup() i linkWithRedirect(), aby połączyć różne usługi tożsamości z istniejącymi kontami.

Pamiętaj, że Apple wymaga uzyskania wyraźnej zgody użytkowników przed połączeniem ich kont Apple z innymi danymi.

Aby na przykład połączyć konto na Facebooku z bieżącym kontem Firebase, użyj tokena dostępu uzyskanego podczas logowania użytkownika na Facebooku:

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

Uwierzytelnianie w Firebase w rozszerzeniu do Chrome

Jeśli tworzysz aplikację jako rozszerzenie do Chrome, zapoznaj się z przewodnikiem po dokumentach pozaekranowych.

Pamiętaj, że musisz potwierdzić własność domeny niestandardowej w Apple podobnie jak w przypadku domyślnej domeny firebaseapp.com:

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

Odwoływanie tokena

Zgodnie z wytycznymi dotyczącymi sprawdzania w App Storeaplikacje, które obsługują tworzenie kont, muszą umożliwiać użytkownikom inicjowanie usunięcia konta w aplikacji.

Aby spełnić to wymaganie, wykonaj te czynności:

  1. Upewnij się, że w sekcji Identyfikator usługi i Konfiguracja procesu kodu OAuth konfiguracja w konfiguracji dostawcy Zaloguj się przez Apple zostały wypełnione wszystkie pola zgodnie z opisem w sekcji Konfigurowanie funkcji Zaloguj się przez Apple sekcja.

  2. Ponieważ Firebase nie przechowuje tokenów użytkowników utworzonych za pomocą funkcji Zaloguj się przez Apple, przed odwołaniem tokena i usunięciem konta musisz poprosić użytkownika o ponowne zalogowanie się.

    Następnie pobierz token dostępu OAuth Apple z obiektu OAuthCredential i użyj go do wywołania funkcji revokeAccessToken(auth, token), aby odwołać token dostępu OAuth 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. Na koniec usuń konto użytkownika (i wszystkie powiązane z nim dane).

Zaawansowane: uwierzytelnianie w Firebase w Node.js

Aby uwierzytelnić się w Firebase w aplikacji Node.js:

  1. Zaloguj użytkownika za pomocą jego konta Apple i pobierz token identyfikatora Apple. Możesz to zrobić na kilka sposobów. Jeśli na przykład Twoja aplikacja Node.js ma frontend przeglądarki:

    1. W backendzie wygeneruj losowy ciąg znaków („nonce”) i oblicz jego skrót SHA256. Nonce to wartość jednorazowa, której używasz do weryfikacji pojedynczego cyklu między backendem a serwerami uwierzytelniania 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. Na stronie logowania określ skrót nonce w konfiguracji funkcji Zaloguj się przez 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. Pobierz token identyfikatora Apple z odpowiedzi uwierzytelniającej POST po stronie serwera:

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

    Zapoznaj się też z artykułem Konfigurowanie strony internetowej na potrzeby logowania przez Apple.

  2. Gdy uzyskasz token identyfikatora Apple użytkownika, użyj go do utworzenia obiektu Credential, a następnie zaloguj użytkownika za pomocą tych danych logowania:

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

Dalsze kroki

Gdy użytkownik zaloguje się po raz pierwszy, zostanie utworzone nowe konto użytkownika i połączone z danymi logowania, czyli nazwą użytkownika i hasłem, numerem telefonu lub informacjami o dostawcy uwierzytelniania, za pomocą których użytkownik się zalogował. To nowe konto jest przechowywane w ramach projektu w Firebase i może służyć do identyfikowania użytkownika w każdej aplikacji w projekcie, niezależnie od sposobu logowania.

  • W aplikacjach zalecanym sposobem sprawdzenia stanu uwierzytelnienia użytkownika jest ustawienie obserwatora w obiekcie Auth. Następnie możesz pobrać podstawowe informacje o profilu użytkownika z obiektu User. Więcej informacji znajdziesz w artykule Zarządzanie użytkownikami.

  • W regułach bezpieczeństwa Firebase Realtime Database i Cloud Storage Bazy danych czasu rzeczywistego Firebase i Cloud Storage, możesz uzyskać unikalny identyfikator zalogowanego użytkownika z zmiennej auth, i użyć go do kontrolowania, do jakich danych użytkownik może mieć dostęp.

Możesz zezwolić użytkownikom na logowanie się w aplikacji za pomocą kilku dostawców uwierzytelniania przez połączenie danych logowania dostawcy uwierzytelniania z istniejącym kontem użytkownika.

Aby wylogować użytkownika, wywołaj funkcję 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.
});