Uwierzytelniaj za pomocą oprogramowania Microsoft i JavaScript

Możesz umożliwić użytkownikom uwierzytelnianie się w Firebase za pomocą dostawców OAuth, takich jak Microsoft Azure Active Directory. Aby przeprowadzić cały proces logowania, zintegruj ogólne logowanie OAuth z aplikacją za pomocą pakietu SDK Firebase.

Zanim zaczniesz

Aby umożliwić użytkownikom logowanie się za pomocą kont Microsoft (Azure Active Directory i osobistych kont Microsoft), musisz najpierw włączyć Microsoft jako dostawcę logowania w projekcie Firebase:

  1. Dodaj Firebase do projektu JavaScript.
  2. W konsoli Firebase otwórz sekcję Autoryzacja.
  3. Na karcie Metoda logowania włącz dostawcę Microsoft.
  4. Dodaj Identyfikator klienta i Tajny klucz klienta z konsoli deweloperskiej tego dostawcy do konfiguracji tego dostawcy:
    1. Aby zarejestrować klienta OAuth firmy Microsoft, wykonaj instrukcje podane w  Przewodnik dla początkujących: rejestrowanie aplikacji za pomocą punktu końcowego Azure Active Directory w wersji 2.0. Pamiętaj, że ten punkt końcowy obsługuje logowanie się za pomocą kont osobistych Microsoft oraz kont Azure Active Directory. Dowiedz się więcej o Azure Active Directory w wersji 2.0.
    2. Podczas rejestrowania aplikacji u tych dostawców pamiętaj, aby zarejestrować domenę *.firebaseapp.com dla projektu jako domenę przekierowania dla aplikacji.
  5. Kliknij Zapisz.

Obsługa procesu logowania za pomocą pakietu SDK Firebase

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

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

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

    WebWeb
    import { OAuthProvider } from "firebase/auth";
    
    const provider = new OAuthProvider('microsoft.com');
    var provider = new firebase.auth.OAuthProvider('microsoft.com');
  2. Opcjonalnie: określ dodatkowe niestandardowe parametry OAuth, które chcesz wysłać z prośbą OAuth.

    WebWeb
    provider.setCustomParameters({
      // Force re-consent.
      prompt: 'consent',
      // Target specific email with login hint.
      login_hint: 'user@firstadd.onmicrosoft.com'
    });
    provider.setCustomParameters({
      // Force re-consent.
      prompt: 'consent',
      // Target specific email with login hint.
      login_hint: 'user@firstadd.onmicrosoft.com'
    });

    Informacje o parametrach obsługiwanych przez firmę Microsoft znajdziesz w dokumentacji OAuth firmy Microsoft. Pamiętaj, że za pomocą parametru setCustomParameters() nie możesz przekazywać parametrów wymaganych przez Firebase. Są to: client_id, response_type, redirect_uri, state, scope i response_mode.

    Aby zezwolić na logowanie się w aplikacji tylko użytkownikom z danej dzierżawy Azure AD, możesz użyć przyjaznej nazwy domeny dzierżawy w Azure AD lub identyfikatora GUID dzierżawy. Aby to zrobić, w obiekcie parametrów niestandardowych podaj pole „tenant” (najemca).

    WebWeb
    provider.setCustomParameters({
      // Optional "tenant" parameter in case you are using an Azure AD tenant.
      // eg. '8eaef023-2b34-4da1-9baa-8bc8c9d6a490' or 'contoso.onmicrosoft.com'
      // or "common" for tenant-independent tokens.
      // The default value is "common".
      tenant: 'TENANT_ID'
    });
    provider.setCustomParameters({
      // Optional "tenant" parameter in case you are using an Azure AD tenant.
      // eg. '8eaef023-2b34-4da1-9baa-8bc8c9d6a490' or 'contoso.onmicrosoft.com'
      // or "common" for tenant-independent tokens.
      // The default value is "common".
      tenant: 'TENANT_ID'
    });
  3. Opcjonalnie: określ dodatkowe zakresy OAuth 2.0 poza podstawowym profilem, o które chcesz poprosić dostawcę usługi uwierzytelniania.

    provider.addScope('mail.read');
    provider.addScope('calendars.read');

    Więcej informacji znajdziesz w dokumentacji firmy Microsoft na temat uprawnień i zgód.

  4. Uwierzytelnij się w Firebase, używając obiektu dostawcy OAuth. Możesz poprosić użytkowników o zalogowanie się na swoje konta Microsoft, otwierając okno wyskakujące 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:
    WebWeb
    import { getAuth, signInWithPopup, OAuthProvider } from "firebase/auth";
    
    const auth = getAuth();
    signInWithPopup(auth, provider)
      .then((result) => {
        // User is signed in.
        // IdP data available in result.additionalUserInfo.profile.
    
        // Get the OAuth access token and ID Token
        const credential = OAuthProvider.credentialFromResult(result);
        const accessToken = credential.accessToken;
        const idToken = credential.idToken;
      })
      .catch((error) => {
        // Handle error.
      });
    firebase.auth().signInWithPopup(provider)
      .then((result) => {
        // IdP data available in result.additionalUserInfo.profile.
        // ...
    
        /** @type {firebase.auth.OAuthCredential} */
        var credential = result.credential;
    
        // OAuth access and id tokens can also be retrieved:
        var accessToken = credential.accessToken;
        var idToken = credential.idToken;
      })
      .catch((error) => {
        // Handle error.
      });
    • Aby zalogować się przez przekierowanie na stronę logowania, zadzwoń pod numer signInWithRedirect:

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

    WebWeb
    import { getAuth, signInWithRedirect } from "firebase/auth";
    
    const auth = getAuth();
    signInWithRedirect(auth, provider);
    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.

    WebWeb
    import { getAuth, getRedirectResult, OAuthProvider } from "firebase/auth";
    
    const auth = getAuth();
    getRedirectResult(auth)
      .then((result) => {
        // User is signed in.
        // IdP data available in result.additionalUserInfo.profile.
    
        // Get the OAuth access token and ID Token
        const credential = OAuthProvider.credentialFromResult(result);
        const accessToken = credential.accessToken;
        const idToken = credential.idToken;
      })
      .catch((error) => {
        // Handle error.
      });
    firebase.auth().getRedirectResult()
      .then((result) => {
        // IdP data available in result.additionalUserInfo.profile.
        // ...
    
        /** @type {firebase.auth.OAuthCredential} */
        var credential = result.credential;
    
        // OAuth access and id tokens can also be retrieved:
        var accessToken = credential.accessToken;
        var idToken = credential.idToken;
      })
      .catch((error) => {
        // Handle error.
      });

    Po pomyślnym zakończeniu operacji z zwróconego obiektu firebase.auth.UserCredential można pobrać token dostępu OAuth powiązany z dostawcą.

    Za pomocą tokena dostępu OAuth możesz wywoływać interfejs API Microsoft Graph.

    Aby na przykład uzyskać podstawowe informacje o profilu, możesz wywołać ten interfejs API REST:

    curl -i -H "Authorization: Bearer ACCESS_TOKEN" https://graph.microsoft.com/v1.0/me

    W przeciwieństwie do innych dostawców obsługiwanych przez Firebase Auth Microsoft nie udostępnia adresu URL zdjęcia. Zamiast tego dane binarne zdjęcia profilowego należy poprosić o interfejs Microsoft Graph API.

    Oprócz tokena dostępu OAuth z obiektu firebase.auth.UserCredential można też pobrać token identyfikacyjny użytkownika. Założenie sub w tokenie identyfikacyjnym jest specyficzne dla aplikacji i nie będzie pasować do identyfikatora użytkownika sfederowanego używanego przez Uwierzytelnianie Firebase i dostępnego za pomocą założenia user.providerData[0].uid. Należy użyć pola oid. Gdy logujesz się za pomocą dzierżaw Azure AD, identyfikator oid będzie dokładnym dopasowaniem. W przypadku braku najemcy pole oid jest jednak wypełnione. W przypadku federacyjnego identyfikatora 4b2eabcdefghijkl element oid będzie miał postać 00000000-0000-0000-4b2e-abcdefghijkl.

  5. Powyższe przykłady koncentrują się na procesach logowania, ale za pomocą elementów linkWithPopup/linkWithRedirect możesz też połączyć dostawcę Microsoft z dotychczasowym użytkownikiem. Możesz na przykład połączyć kilku dostawców z tym samym użytkownikiem, aby umożliwić mu logowanie się za pomocą dowolnego z nich.

    WebWeb
    import { getAuth, linkWithPopup, OAuthProvider } from "firebase/auth";
    
    const provider = new OAuthProvider('microsoft.com');
    const auth = getAuth();
    
    linkWithPopup(auth.currentUser, provider)
        .then((result) => {
          // Microsoft credential is linked to the current user.
          // IdP data available in result.additionalUserInfo.profile.
    
          // Get the OAuth access token and ID Token
          const credential = OAuthProvider.credentialFromResult(result);
          const accessToken = credential.accessToken;
          const idToken = credential.idToken;
        })
        .catch((error) => {
          // Handle error.
        });
    var provider = new firebase.auth.OAuthProvider('microsoft.com');
    firebase.auth().currentUser.linkWithPopup(provider)
        .then((result) => {
          // Microsoft credential is linked to the current user.
          // IdP data available in result.additionalUserInfo.profile.
          // OAuth access token can also be retrieved:
          // result.credential.accessToken
          // OAuth ID token can also be retrieved:
          // result.credential.idToken
        })
        .catch((error) => {
          // Handle error.
        });
  6. Tego samego wzorca można używać w przypadku parametrów reauthenticateWithPopup/reauthenticateWithRedirect, które umożliwiają pobieranie nowych danych logowania w przypadku operacji wrażliwych wymagających niedawnego zalogowania.

    WebWeb
    import { getAuth, reauthenticateWithPopup, OAuthProvider } from "firebase/auth";
    
    const provider = new OAuthProvider('microsoft.com');
    const auth = getAuth();
    reauthenticateWithPopup(auth.currentUser, provider)
        .then((result) => {
          // User is re-authenticated with fresh tokens minted and
          // should be able to perform sensitive operations like account
          // deletion and email or password update.
          // IdP data available in result.additionalUserInfo.profile.
    
          // Get the OAuth access token and ID Token
          const credential = OAuthProvider.credentialFromResult(result);
          const accessToken = credential.accessToken;
          const idToken = credential.idToken;
        })
        .catch((error) => {
          // Handle error.
        });
    var provider = new firebase.auth.OAuthProvider('microsoft.com');
    firebase.auth().currentUser.reauthenticateWithPopup(provider)
        .then((result) => {
          // User is re-authenticated with fresh tokens minted and
          // should be able to perform sensitive operations like account
          // deletion and email or password update.
          // IdP data available in result.additionalUserInfo.profile.
          // OAuth access token can also be retrieved:
          // result.credential.accessToken
          // OAuth ID token can also be retrieved:
          // result.credential.idToken
        })
        .catch((error) => {
          // Handle error.
        });

Jeśli w konsoli Firebase masz włączone ustawienie Jedno konto na adres e-mail, gdy użytkownik spróbuje zalogować się do dostawcy (np. Microsoft) przy użyciu adresu e-mail, który jest już używany przez innego użytkownika Firebase (np. Google), zostanie zwrócony błądauth/account-exists-with-different-credential wraz z obiektem AuthCredential (dane logowania Microsoft). Aby dokończyć logowanie do wybranego dostawcy, użytkownik musi najpierw zalogować się w dostawcy, którego używa obecnie (Google), a potem połączyć konto z poprzednim AuthCredential (dane logowania Microsoft).

Jeśli używasz signInWithPopup, możesz obsługiwać błędy auth/account-exists-with-different-credential za pomocą kodu podobnego do tego:

import {
  getAuth,
  linkWithCredential,
  signInWithPopup,
  OAuthProvider,
} from "firebase/auth";

try {
  // Step 1: User tries to sign in using Microsoft.
  let result = await signInWithPopup(getAuth(), new OAuthProvider());
} catch (error) {
  // Step 2: User's email already exists.
  if (error.code === "auth/account-exists-with-different-credential") {
    // The pending Microsoft credential.
    let pendingCred = error.credential;

    // Step 3: Save the pending credential in temporary storage,

    // Step 4: Let the user know that they already have an account
    // but with a different provider, and let them choose another
    // sign-in method.
  }
}

// ...

try {
  // Step 5: Sign the user in using their chosen method.
  let result = await signInWithPopup(getAuth(), userSelectedProvider);

  // Step 6: Link to the Microsoft credential.
  // TODO: implement `retrievePendingCred` for your app.
  let pendingCred = retrievePendingCred();

  if (pendingCred !== null) {
    // As you have access to the pending credential, you can directly call the
    // link method.
    let user = await linkWithCredential(result.user, pendingCred);
  }

  // Step 7: Continue to app.
} catch (error) {
  // ...
}

Tryb przekierowania

Ten błąd jest obsługiwany w podobny sposób w trybie przekierowania, z tą różnicą, że oczekujące dane logowania muszą zostać zapisane w pamięci podręcznej między przekierowaniami stron (np. za pomocą pamięci sesji).

W odróżnieniu od innych dostawców OAuth obsługiwanych przez Firebase, takich jak Google, Facebook i Twitter, gdzie logowanie może odbywać się bezpośrednio za pomocą danych logowania opartych na tokenach dostępu OAuth, usługa Firebase Auth nie obsługuje tej samej funkcji w przypadku dostawców takich jak Microsoft, ponieważ serwer Firebase Auth nie może zweryfikować odbiorców tokenów dostępu OAuth Microsoft. Jest to kluczowe wymaganie dotyczące bezpieczeństwa, ponieważ może narazić aplikacje i witryny na ataki polegające na odtwarzaniu, w których token dostępu OAuth firmy Microsoft uzyskany dla jednego projektu (atakujący) może być użyty do zalogowania się w innym projekcie (ofiara). Zamiast tego Firebase Auth umożliwia obsługę całego procesu OAuth i wymiany kodu autoryzacji za pomocą identyfikatora klienta OAuth i tajemnego klucza skonfigurowanych w Konsoli Firebase. Kod autoryzacji można użyć tylko w połączeniu z konkretnym identyfikatorem klienta lub kluczem tajnym. Kod autoryzacji uzyskany w jednym projekcie nie może być użyty w innym.

Jeśli te usługi są wymagane w nieobsługiwanych środowiskach, musisz użyć biblioteki OAuth innej firmy i niestandardowej autoryzacji Firebase. Pierwszy z nich jest potrzebny do uwierzytelnienia się u dostawcy, a drugi do wymiany danych logowania dostawcy na token niestandardowy.

Uwierzytelnianie w Firebase w rozszerzeniu do Chrome

Jeśli tworzysz rozszerzenie do Chrome, zapoznaj się z  przewodnikiem po dokumentach poza ekranem.

Podczas tworzenia projektu Firebase udostępni unikalną domenę podrzędną dla Twojego projektu:https://my-app-12345.firebaseapp.com.

Będzie on też używany jako mechanizm przekierowania w przypadku logowania OAuth. Ta domena musi być dozwolona dla wszystkich obsługiwanych dostawców OAuth. Oznacza to jednak, że użytkownicy mogą zobaczyć tę domenę podczas logowania się w usłudze Microsoft, zanim zostaną przekierowani z powrotem do aplikacji: Przejdź do https://my-app-12345.firebaseapp.com.

Aby uniknąć wyświetlania subdomeny, możesz skonfigurować domenę niestandardową za pomocą Firebase Hosting:

  1. Wykonaj czynności opisane w sekwencji Konfigurowanie domeny dla usługi Hosting. Gdy potwierdzisz własność domeny, Hosting zarezerwuje certyfikat SSL dla Twojej domeny niestandardowej.
  2. Dodaj swoją domenę niestandardową do listy autoryzowanych domen w konsoli Firebase: auth.custom.domain.com.
  3. W konsoli deweloperów Microsoft lub na stronie konfiguracji OAuth dodaj do białej listy adres URL strony przekierowania, która będzie dostępna w domenie niestandardowej:https://auth.custom.domain.com/__/auth/handler.
  4. Podczas inicjowania biblioteki JavaScript podaj domenę niestandardową w polu authDomain:
    var config = {
      apiKey: '...',
      // Changed from 'PROJECT_ID.firebaseapp.com'.
      authDomain: 'auth.custom.domain.com',
      databaseURL: 'https://PROJECT_ID.firebaseio.com',
      projectId: 'PROJECT_ID',
      storageBucket: 'PROJECT_ID.firebasestorage.app',
      messagingSenderId: 'SENDER_ID'
    };
    firebase.initializeApp(config);

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:

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

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