Uwierzytelnij za pomocą Apple z JavaScript

Możesz zezwolić użytkownikom na uwierzytelnianie w Firebase przy użyciu ich identyfikatora Apple ID przy użyciu pakietu Firebase SDK do przeprowadzania kompleksowego procesu logowania OAuth 2.0.

Zanim zaczniesz

Aby logować użytkowników za pomocą Apple, najpierw skonfiguruj opcję Logowanie się z Apple w witrynie dla programistów Apple, a następnie włącz Apple jako dostawcę logowania dla swojego projektu Firebase.

Dołącz do Programu dla programistów Apple

Logowanie się przez Apple może być skonfigurowane tylko przez członków programu Apple Developer Program .

Skonfiguruj logowanie za pomocą Apple

W witrynie Apple Developer wykonaj następujące czynności:

  1. Powiąż swoją witrynę internetową z aplikacją zgodnie z opisem w pierwszej sekcji Konfigurowanie logowania przez Apple w Internecie . Po wyświetleniu monitu zarejestruj następujący adres URL jako zwrotny adres URL:

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

    Identyfikator projektu Firebase możesz uzyskać na stronie ustawień konsoli Firebase .

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

  2. Utwórz logowanie za pomocą klucza prywatnego Apple . W następnej sekcji będziesz potrzebować nowego klucza prywatnego i identyfikatora klucza.
  3. Jeśli korzystasz z funkcji uwierzytelniania Firebase, które wysyłają e-maile do użytkowników, w tym logowania za pomocą łącza e-mail, weryfikacji adresu e-mail, cofnięcia zmiany konta i innych, skonfiguruj usługę przekazywania prywatnej poczty e-mail Apple i zarejestruj noreply@ YOUR_FIREBASE_PROJECT_ID .firebaseapp.com (lub Twoja dostosowana domena szablonu wiadomości e-mail), aby firma Apple mogła przekazywać wiadomości e-mail wysyłane przez uwierzytelnianie Firebase na anonimowe adresy e-mail firmy Apple.

Włącz Apple jako dostawcę logowania

  1. Dodaj Firebase do swojego projektu .
  2. W konsoli Firebase otwórz sekcję Auth . Na karcie Metoda logowania włącz dostawcę Apple . Określ identyfikator usługi utworzony w poprzedniej sekcji. Ponadto w sekcji konfiguracji przepływu kodu OAuth podaj swój Apple Team ID oraz klucz prywatny i identyfikator klucza utworzone w poprzedniej sekcji.

Przestrzegaj wymagań Apple dotyczących danych anonimowych

Funkcja Zaloguj się z Apple umożliwia użytkownikom anonimizację danych, w tym adresu e-mail, podczas logowania. Użytkownicy, którzy wybiorą tę opcję, mają adresy e-mail w domenie privaterelay.appleid.com . Gdy używasz Logowania się przez Apple w swojej aplikacji, musisz przestrzegać wszelkich obowiązujących zasad deweloperskich lub warunków Apple dotyczących tych anonimowych identyfikatorów Apple ID.

Obejmuje to uzyskanie wszelkiej wymaganej zgody użytkownika przed powiązaniem jakichkolwiek bezpośrednio identyfikujących danych osobowych z anonimowym identyfikatorem Apple ID. W przypadku korzystania z uwierzytelniania Firebase może to obejmować następujące działania:

  • Połącz adres e-mail z anonimowym identyfikatorem Apple ID lub odwrotnie.
  • Połącz numer telefonu z anonimowym identyfikatorem Apple ID lub odwrotnie
  • Połącz nieanonimowe dane uwierzytelniające z serwisów społecznościowych (Facebook, Google itp.) z anonimowym identyfikatorem Apple ID lub odwrotnie.

Powyższa lista nie jest wyczerpująca. Zapoznaj się z Umową licencyjną Apple Developer Program w sekcji Członkostwo na swoim koncie programisty, aby upewnić się, że Twoja aplikacja spełnia wymagania Apple.

Obsługuj proces logowania za pomocą Firebase SDK

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

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

  1. Utwórz instancję OAuthProvider przy użyciu odpowiedniego identyfikatora dostawcy apple.com .

    Web modular API

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

    Web namespaced API

    var provider = new firebase.auth.OAuthProvider('apple.com');
  2. Opcjonalne: Określ dodatkowe zakresy OAuth 2.0 wykraczające poza zakres domyślny, o które chcesz poprosić dostawcę uwierzytelniania.

    Web modular API

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

    Web namespaced API

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

    Domyślnie, gdy włączona jest opcja Jedno konto na adres e-mail , Firebase żąda zakresów adresów e-mail i nazw. Jeśli zmienisz to ustawienie na Wiele kont na adres e-mail , Firebase nie zażąda żadnych zakresów od Apple, chyba że je określisz.

  3. Opcjonalnie: jeśli chcesz wyświetlić ekran logowania Apple w języku innym niż angielski, ustaw parametr ustawień locale . Zapoznaj się z dokumentacją Logowanie się za pomocą Apple, aby poznać obsługiwane języki.

    Web modular API

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

    Web namespaced API

    provider.setCustomParameters({
      // Localize the Apple authentication screen in French.
      locale: 'fr'
    });
  4. Uwierzytelnij się w Firebase przy użyciu obiektu dostawcy OAuth. Możesz poprosić użytkowników o zalogowanie się przy użyciu ich kont Apple, otwierając wyskakujące okienko lub przekierowując na stronę logowania. Metoda przekierowania jest preferowana na urządzeniach mobilnych.

    • Aby zalogować się za pomocą wyskakującego okienka, wywołaj funkcję signInWithPopup() :

      Web modular API

      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 namespaced API

      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 do strony logowania, wywołaj funkcję signInWithRedirect() :

    Postępuj zgodnie z najlepszymi praktykami podczas korzystania signInWithRedirect , linkWithRedirect lub reauthenticateWithRedirect .

    Web modular API

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

    Web namespaced API

    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 modular API

    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 namespaced API

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

    Jest to również miejsce, w którym można wychwytywać i obsługiwać błędy. Aby uzyskać listę kodów błędów, zapoznaj się z dokumentacją interfejsu API .

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

    Ponadto, gdy użytkownik zdecyduje się nie udostępniać aplikacji swojego adresu e-mail, firma Apple przydziela mu unikalny adres e-mail (w postaci xyz@privaterelay.appleid.com ), który udostępnia aplikacji. Jeśli skonfigurowałeś usługę przekazywania prywatnych wiadomości e-mail, Apple przekazuje wiadomości e-mail wysłane na anonimowy adres na prawdziwy adres e-mail użytkownika.

    Apple udostępnia aplikacjom informacje o użytkowniku, takie jak nazwa wyświetlana, tylko przy pierwszym logowaniu użytkownika. Zwykle Firebase przechowuje nazwę wyświetlaną przy pierwszym logowaniu użytkownika w Apple, którą można uzyskać za pomocą firebase.auth().currentUser.displayName . Jeśli jednak wcześniej używałeś Apple do logowania użytkownika w aplikacji bez korzystania z Firebase, Apple nie udostępni Firebase nazwy wyświetlanej użytkownika.

Ponowne uwierzytelnianie i łączenie kont

Tego samego wzorca można użyć z reauthenticateWithPopup() i reauthenticateWithRedirect() , których można użyć do pobrania nowych danych uwierzytelniających dla poufnych operacji wymagających niedawnego logowania:

Web modular API

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 namespaced API

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 także użyć linkWithPopup() i linkWithRedirect() , aby połączyć różnych dostawców tożsamości z istniejącymi kontami.

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

Na przykład, aby połączyć konto na Facebooku z bieżącym kontem Firebase, użyj tokena dostępu otrzymanego po zalogowaniu użytkownika na Facebooku:

Web modular API

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 namespaced API

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

Uwierzytelnij się za pomocą Firebase w rozszerzeniu Chrome

Jeśli tworzysz aplikację rozszerzającą Chrome, musisz dodać swój identyfikator rozszerzenia Chrome:

  1. Otwórz swój projekt w konsoli Firebase .
  2. W sekcji Uwierzytelnianie otwórz stronę Metoda logowania .
  3. Dodaj identyfikator URI podobny do następującego do listy autoryzowanych domen:
    chrome-extension://CHROME_EXTENSION_ID

Tylko operacje wyskakujące ( signInWithPopup , linkWithPopup i reauthenticateWithPopup ) są dostępne dla rozszerzeń Chrome, ponieważ rozszerzenia Chrome nie mogą używać przekierowań HTTP. Powinieneś wywoływać te metody ze skryptu strony w tle, a nie z wyskakującego okienka akcji przeglądarki, ponieważ wyskakujące okienko uwierzytelniania anuluje wyskakujące okienko akcji przeglądarki. Metody wyskakujące mogą być używane tylko w rozszerzeniach korzystających z Manifest V2 . Nowszy Manifest V3 zezwala tylko na skrypty działające w tle w postaci service workerów, które w ogóle nie mogą wykonywać operacji wyskakujących okienek.

W pliku manifestu rozszerzenia Chrome dodaj adres URL https://apis.google.com do listy dozwolonych content_security_policy .

Pamiętaj, że nadal musisz zweryfikować domenę niestandardową w Apple, podobnie jak domyślną domenę firebaseapp.com:

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

Zaawansowane: uwierzytelnianie za pomocą Firebase w Node.js

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

  1. Zaloguj użytkownika przy użyciu jego konta Apple i uzyskaj token Apple ID użytkownika. Możesz to osiągnąć na kilka sposobów. Na przykład, jeśli Twoja aplikacja Node.js ma interfejs przeglądarki:

    1. Na swoim zapleczu wygeneruj losowy ciąg („nonce”) i oblicz jego skrót SHA256. Wartość nonce to jednorazowa wartość używana do sprawdzania poprawności pojedynczej podróży w obie strony między zapleczem a serwerami uwierzytelniającymi firmy Apple.

      Web modular API

      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 namespaced API

      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 podaj zahaszowaną wartość jednorazową w konfiguracji logowania za pomocą 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. Uzyskaj token Apple ID z POSTed auth response 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).
        }
      });
      

    Zobacz także Konfigurowanie strony internetowej do logowania się przez Apple .

  2. Po uzyskaniu tokena Apple ID użytkownika użyj go do zbudowania obiektu Credential, a następnie zaloguj użytkownika przy użyciu poświadczeń:

    Web modular API

    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 namespaced API

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

Następne kroki

Gdy użytkownik zaloguje się po raz pierwszy, tworzone jest nowe konto użytkownika, które jest łączone z poświadczeniami — czyli nazwą użytkownika i hasłem, numerem telefonu lub informacjami o dostawcy uwierzytelniania — za pomocą których użytkownik się logował. To nowe konto jest przechowywane jako część Twojego projektu Firebase i może służyć do identyfikacji użytkownika w każdej aplikacji w Twoim projekcie, niezależnie od tego, jak użytkownik się loguje.

  • W twoich aplikacjach zalecanym sposobem poznania statusu autoryzacji użytkownika jest ustawienie obserwatora na obiekcie Auth . Następnie można uzyskać podstawowe informacje o profilu użytkownika z obiektu User . Zobacz Zarządzanie użytkownikami .

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

Możesz zezwolić użytkownikom na logowanie się do Twojej aplikacji przy użyciu wielu dostawców uwierzytelniania, łącząc poświadczenia dostawcy uwierzytelniania z istniejącym kontem użytkownika.

Aby wylogować użytkownika, wywołaj signOut :

Web modular API

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

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

Web namespaced API

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