Uwierzytelnij przez Apple z JavaScriptem

Aby umożliwić użytkownikom uwierzytelnianie się w Firebase za pomocą Apple ID, możesz użyć pakietu Firebase SDK do przeprowadzenia kompleksowego procesu logowania OAuth 2.0.

Zanim zaczniesz

Aby umożliwić użytkownikom logowanie się za pomocą Apple, najpierw skonfiguruj logowanie z Apple na stronie dewelopera Apple, a następnie włącz Apple jako dostawcę logowania w swoim projekcie Firebase.

Dołącz do Programu deweloperów Apple

Logowanie przez Apple może skonfigurować tylko osoba należąca do Programu dla deweloperów Apple.

Konfigurowanie logowania przez Apple

Na stronie Apple Developer wykonaj te czynności:

  1. Połącz witrynę z aplikacją zgodnie z opisem w pierwszej sekcji artykułu Konfigurowanie logowania z Apple w internecie. Gdy pojawi się taka prośba, zarejestruj ten adres URL jako powrotny adres URL:

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

    Identyfikator projektu Firebase znajdziesz na stronie ustawień Firebase konsoli Firebase.

    Gdy skończysz, zanotuj nowy identyfikator usługi, którego będziesz potrzebować w następnej sekcji.

  2. Utwórz klucz prywatny „Zaloguj się przez Apple”. W następnej sekcji będziesz potrzebować nowego klucza prywatnego i identyfikatora klucza.
  3. Jeśli używasz funkcji Firebase Authentication, które wysyłają e-maile do użytkowników, w tym funkcji logowania za pomocą linku e-mail, weryfikacji adresu e-mail, zmiany konta i cofnięcia uprawnień, skonfiguruj prywatną usługę przekaźnika poczty e-mail Apple i zarejestruj noreply@YOUR_FIREBASE_PROJECT_ID.firebaseapp.com (lub swoją niestandardową domenę szablonu e-maila), aby Apple mógł przekazywać e-maile wysyłane przez Firebase Authentication na anonimowe adresy e-mail Apple.

Włączanie logowania przez Apple jako dostawcy

  1. Dodaj Firebase do projektu.
  2. W konsoli Firebase otwórz sekcję Autoryzacja. Na karcie Metoda logowania włącz dostawcę Apple. Podaj identyfikator usługi utworzony w poprzedniej sekcji. W sekcji Konfiguracja procedury kodu OAuth podaj identyfikator zespołu Apple oraz klucz prywatny i identyfikator klucza utworzone w poprzedniej sekcji.

Zapewnij zgodność z wymaganiami Apple dotyczącymi danych zanonimizowanych

Logowanie z 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 w swojej aplikacji używasz funkcji Logowanie przez Apple, musisz przestrzegać wszystkich zasad lub warunków Apple dotyczących anonimowych identyfikatorów Apple.

Obejmuje to uzyskanie wymaganej zgody użytkownika przed powiązaniem jakichkolwiek danych osobowych umożliwiających bezpośrednią identyfikację z użyciem anonimowego identyfikatora Apple. Jeśli używasz Uwierzytelniania Firebase, może to obejmować te działania:

  • Połącz adres e-mail z anonimowym identyfikatorem Apple ID lub odwrotnie.
  • Łączenie numeru telefonu z utworzonym anonimowo identyfikatorem Apple ID lub na odwrót
  • Połącz nieanonimowe dane logowania do sieci społecznościowej (Facebook, Google itp.) z anonimowym identyfikatorem Apple ID lub odwrotnie.

Powyższa lista nie jest wyczerpująca. Aby sprawdzić, czy Twoja aplikacja spełnia wymagania Apple, zapoznaj się z Apple Developer Program License Agreement w sekcji Membership na koncie dewelopera.

Obsługa procesu logowania za pomocą pakietu SDK Firebase

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

Aby obsłużyć proces logowania za pomocą pakietu Firebase JavaScript SDK, wykonaj te czynności:

  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, które chcesz poprosić od dostawcy 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 adresów e-mail i nazwy. Jeśli zmienisz to ustawienie na Wiele kont na adres e-mail, Firebase nie będzie prosić Apple o żadne uprawnienia, chyba że je określisz.

  3. Opcjonalnie: jeśli chcesz wyświetlić ekran logowania Apple w języku innym niż angielski, ustaw parametr locale. Informacje o obsługiwanych lokalizacjach znajdziesz w dokumentacji logowania za pomocą 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, używając obiektu dostawcy OAuth. Możesz poprosić użytkowników o zalogowanie się na swoje konta Apple, otwierając wyskakujące okienko lub przekierowując ich na stronę logowania. Na urządzeniach mobilnych preferowana jest metoda przekierowania.

    • Aby zalogować się w wyskakującym okienku, zadzwoń pod numer 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, zadzwoń pod numer:signInWithRedirect()

    Stosuj sprawdzone metody podczas używania funkcji signInWithRedirect, linkWithRedirect lub reauthenticateWithRedirect.

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

    Tutaj możesz też wykrywać i rozwiązywać błędy. Listę kodów błędów znajdziesz w przewodniku po interfejsie API.

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

    Jeśli użytkownik zdecyduje się nie udostępniać aplikacji swojego adresu e-mail, Apple udostępni Twojej aplikacji unikalny adres e-mail tego użytkownika (w formie xyz@privaterelay.appleid.com). Jeśli skonfigurujesz prywatną usługę przekaźnika poczty e-mail, Apple przekieruje e-maile wysłane na anonimowy adres na prawdziwy adres e-mail użytkownika.

    Apple udostępnia aplikacjom informacje o użytkowniku, takie jak wyświetlana nazwa, tylko wtedy, gdy użytkownik zaloguje się po raz pierwszy. Zwykle Firebase przechowuje wyświetlaną nazwę podczas pierwszego logowania użytkownika za pomocą Apple. Możesz ją uzyskać za pomocą funkcji firebase.auth().currentUser.displayName. Jeśli jednak wcześniej logowanie użytkownika w aplikacji zostało wykonane za pomocą Apple bez użycia Firebase, Apple nie przekaże Firebase nazwy wyświetlanej użytkownika.

Ponowna weryfikacja i połączenie konta

Tego samego wzorca można używać w przypadku funkcji reauthenticateWithPopup()reauthenticateWithRedirect(), które umożliwiają pobranie nowych danych logowania na potrzeby operacji związanych z danymi wrażliwymi, które wymagają niedawnego zalogowania:

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()linkWithRedirect(), aby połączyć różne dostawców tożsamości z dotychczasowymi kontami.

Pamiętaj, że zanim połączysz konta użytkowników Apple z innymi danymi, musisz uzyskać ich wyraźną zgodę.

Aby na przykład połączyć konto Facebook z bieżącym kontem Firebase, użyj tokena dostępu uzyskanego po zalogowaniu 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 rozszerzenie do Chrome, zapoznaj się z  przewodnikiem po dokumentach poza ekranem.

Pamiętaj, że musisz nadal weryfikować domenę niestandardową w Apple w sposób podobny do domeny domyślnej firebaseapp.com:

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

Unieważnienie tokena

Apple wymaga, aby aplikacje, które umożliwiają tworzenie kont, pozwalały użytkownikom na usunięcie konta z poziomu aplikacji zgodnie z opisem w wytycznych dotyczących weryfikacji App Store.

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

  1. Sprawdź, czy w sekcji konfiguracji logowania za pomocą Apple wypełnione są pola Identyfikator usługKonfigurowanie procedury kodu OAuth, zgodnie z opisem w sekcji Konfigurowanie logowania za pomocą Apple.

  2. Firebase nie przechowuje tokenów użytkowników, gdy są oni tworzeni za pomocą funkcji Zaloguj się przez Apple. Zanim cofniesz token i usuniesz konto, musisz poprosić użytkownika o zalogowanie się ponownie.

    Następnie uzyskaj token dostępu OAuth Apple z OAuthCredential i użyj go do wywołania revokeAccessToken(auth, token), aby cofnąć 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 dane).

Zaawansowane: uwierzytelnianie w Firebase w Node.js

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

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

    1. Na backendzie wygeneruj losowy ciąg znaków (tzw. „nonce”) i oblicz jego hasz SHA256. Wartość nonce to jednorazowy parametr, który służy do weryfikacji pojedynczego połączenia 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 haszowany nonce w konfiguracji logowania z 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. Pobieranie tokena Apple ID z zapytania o autoryzację przesłanego metodą 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 konfigurowaniem strony internetowej na potrzeby logowania Apple.

  2. Po uzyskaniu tokena identyfikatora Apple ID użytkownika użyj go do utworzenia obiektu danych uwierzytelniających, a następnie zaloguj użytkownika przy użyciu tych danych:

    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 dostawcy uwierzytelniania, za pomocą których użytkownik się zalogował. To nowe konto jest przechowywane w projekcie Firebase i może służyć do identyfikowania użytkownika we wszystkich aplikacjach w projekcie, niezależnie od tego, jak użytkownik się loguje.

  • W swoich aplikacjach zalecamy ustalanie stanu uwierzytelniania użytkownika przez ustawienie obserwatora w obiekcie Auth. Następnie możesz uzyskać podstawowe informacje o profilu użytkownika z obiektu User. Zobacz Zarządzanie użytkownikami.

  • W regułach Firebase Realtime DatabaseCloud Storage Regułach bezpieczeństwa możesz pobrać z zmiennej auth unikalny identyfikator zalogowanego użytkownika i używać go do kontrolowania dostępu użytkownika do danych.

Możesz zezwolić użytkownikom na logowanie się w aplikacji za pomocą danych uwierzytelniających od różnych dostawców, łącząc je z dotychczasowym 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.
});