אימות באמצעות Microsoft באמצעות JavaScript

כדי לאפשר למשתמשים לבצע אימות ב-Firebase באמצעות ספקי OAuth כמו Microsoft Azure Active Directory, אפשר לשלב באפליקציה שלכם כניסה גנרית באמצעות OAuth באמצעות Firebase SDK כדי לבצע את תהליך הכניסה מקצה לקצה.

לפני שמתחילים

כדי לאפשר למשתמשים להיכנס באמצעות חשבונות Microsoft (Azure Active Directory וחשבונות Microsoft אישיים), קודם צריך להפעיל את Microsoft כספק כניסה לפרויקט Firebase:

  1. מוסיפים את Firebase לפרויקט JavaScript.
  2. במסוף Firebase, פותחים את הקטע Auth.
  3. בכרטיסייה Sign in method (שיטת כניסה), מפעילים את הספק Microsoft.
  4. מוסיפים את מזהה הלקוח ואת סוד הלקוח ממסוף הפיתוח של הספק להגדרות הספק:
    1. כדי לרשום לקוח OAuth של Microsoft, פועלים לפי ההוראות במאמר תחילת העבודה: רישום אפליקציה בנקודת הקצה של Azure Active Directory v2.0. חשוב לזכור שאפשר להשתמש בנקודת הקצה הזו כדי להיכנס באמצעות חשבונות אישיים של Microsoft וגם באמצעות חשבונות Azure Active Directory. מידע נוסף על Azure Active Directory v2.0
    2. כשרושמים אפליקציות אצל הספקים האלה, חשוב לרשום את הדומיין *.firebaseapp.com של הפרויקט כדומיין להפניה אוטומטית של האפליקציה.
  5. לוחצים על שמירה.

טיפול בתהליך הכניסה באמצעות Firebase SDK

אם אתם מפתחים אפליקציית אינטרנט, הדרך הקלה ביותר לאמת את המשתמשים ב-Firebase באמצעות חשבונות Microsoft שלהם היא לטפל בתהליך הכניסה כולו באמצעות ה-SDK של Firebase ל-JavaScript.

כדי לטפל בתהליך הכניסה באמצעות Firebase JavaScript SDK:

  1. יוצרים מופע של OAuthProvider באמצעות מזהה הספק microsoft.com.

    WebWeb
    import { OAuthProvider } from "firebase/auth";
    
    const provider = new OAuthProvider('microsoft.com');
    var provider = new firebase.auth.OAuthProvider('microsoft.com');
  2. אופציונלי: מציינים פרמטרים מותאמים אישית נוספים של OAuth שרוצים לשלוח עם בקשת ה-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'
    });

    הפרמטרים שבהם Microsoft תומכת מפורטים במסמכי התיעוד של Microsoft OAuth. שימו לב: אי אפשר להעביר פרמטרים שנדרשים ל-Firebase באמצעות setCustomParameters(). הפרמטרים האלה הם client_id,‏ response_type, ‏ redirect_uri, ‏ state, ‏ scope ו-response_mode.

    כדי לאפשר רק למשתמשים מדייר מסוים ב-Azure AD להיכנס לאפליקציה, אפשר להשתמש בשם הדומיין הידידותי של הדייר ב-Azure AD או במזהה ה-GUID של הדייר. כדי לעשות זאת, מציינים את השדה tenant באובייקט הפרמטרים המותאמים אישית.

    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. אופציונלי: מציינים היקפי הרשאות נוספים של OAuth 2.0, מעבר לפרופיל הבסיסי, שרוצים לבקש מספק האימות.

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

    למידע נוסף, אפשר לעיין במסמכי התיעוד בנושא הרשאות והסכמה של Microsoft.

  4. אימות באמצעות Firebase באמצעות אובייקט הספק של OAuth. אתם יכולים לבקש מהמשתמשים להיכנס באמצעות חשבונות Microsoft שלהם על ידי פתיחת חלון קופץ או על ידי הפניה לדף הכניסה. השיטה להפניה אוטומטית היא המועדפת במכשירים ניידים.

    • כדי להיכנס באמצעות חלון קופץ, צריך לבצע את הפעולות הבאות: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.
      });
    • כדי להיכנס לחשבון על ידי הפניה לדף הכניסה, צריך להתקשר למספר signInWithRedirect:

    מומלץ לפעול לפי השיטות המומלצות כשמשתמשים ב-signInWithRedirect, ב-linkWithRedirect או ב-reauthenticateWithRedirect.

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

    אחרי שהמשתמש משלים את הכניסה וחוזרים לדף, אפשר לקבל את תוצאת הכניסה באמצעות קריאה ל-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.
      });

    בסיום התהליך, אפשר לאחזר את אסימון הגישה של OAuth שמשויך לספק מהאובייקט firebase.auth.UserCredential שמוחזר.

    באמצעות אסימון הגישה של OAuth, אפשר לבצע קריאה ל-Microsoft Graph API.

    לדוגמה, כדי לקבל את פרטי הפרופיל הבסיסיים, אפשר להפעיל את ה-API ל-REST הבא:

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

    בניגוד לספקים אחרים שנתמכים על ידי אימות Firebase, Microsoft לא מספקת כתובת URL של תמונה. במקום זאת, צריך לבקש את הנתונים הבינאריים של תמונת הפרופיל דרך Microsoft Graph API.

    בנוסף לאסימון הגישה של OAuth, אפשר לאחזר מהאובייקט firebase.auth.UserCredential גם את אסימון המזהה של המשתמש ב-OAuth. ההצהרה sub באסימון המזהה ספציפית לאפליקציה, והיא לא תואמת למזהה המשתמש המאוחד שבו נעשה שימוש באימות Firebase, ואפשר לגשת אליו דרך user.providerData[0].uid. במקום זאת, צריך להשתמש בשדה ההצהרה oid. כשמשתמשים בדייר Azure AD כדי להיכנס לחשבון, ההצהרה oid תהיה תואמת בדיוק. עם זאת, במקרה של חשבון שאינו של דייר, השדה oid ממולא. למזהה מאוחד 4b2eabcdefghijkl, ה-oid יהיה בפורמט 00000000-0000-0000-4b2e-abcdefghijkl.

  5. הדוגמאות שלמעלה מתמקדות בתהליכי כניסה, אבל יש לכם גם אפשרות לקשר ספק של Microsoft למשתמש קיים באמצעות linkWithPopup/linkWithRedirect. לדוגמה, אתם יכולים לקשר כמה ספקים לאותו משתמש ולאפשר לו להיכנס באמצעות כל אחד מהם.

    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. אפשר להשתמש באותו דפוס עם reauthenticateWithPopup/reauthenticateWithRedirect, כדי לאחזר פרטי כניסה עדכניים לפעולות רגישות שדורשות התחברות מהזמן האחרון.

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

אם הפעלתם את ההגדרה One account per email address (חשבון אחד לכל כתובת אימייל) במסוף Firebase, כשמשתמש ינסה להיכנס לספק (כמו Microsoft) עם כתובת אימייל שכבר קיימת אצל ספק אחר של משתמש ב-Firebase (כמו Google), תוצג הודעת השגיאה auth/account-exists-with-different-credential עם אובייקט AuthCredential (פרטי כניסה של Microsoft). כדי להשלים את הכניסה לספק הרצוי, המשתמש צריך להיכנס קודם לספק הקיים (Google) ואז לקשר ל-AuthCredential הקודם (פרטי הכניסה ל-Microsoft).

אם אתם משתמשים ב-signInWithPopup, תוכלו לטפל בשגיאות auth/account-exists-with-different-credential באמצעות קוד כמו הדוגמה הבאה:

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

מצב ניתוב אוטומטי

הטיפול בשגיאה הזו דומה במצב ההפניה האוטומטית, עם ההבדל שצריך לשמור את פרטי הכניסה בהמתנה במטמון בין ההפניות האוטומטיות של הדפים (לדוגמה, באמצעות אחסון הסשן).

בניגוד לספקים אחרים של OAuth שנתמכים על ידי Firebase, כמו Google,‏ Facebook ו-Twitter, שבהם אפשר להיכנס ישירות באמצעות פרטי כניסה שמבוססים על אסימון גישה של OAuth, אימות ב-Firebase לא תומך באותה יכולת עבור ספקים כמו Microsoft, כי שרת האימות ב-Firebase לא יכול לאמת את הקהל של אסימוני הגישה של Microsoft ב-OAuth. זוהי דרישת אבטחה קריטית, והיא עלולה לחשוף אפליקציות ואתרים למתקפות של שחזור, שבהן אפשר להשתמש באסימון גישה של Microsoft OAuth שנוצר לפרויקט אחד (תוקף) כדי להיכנס לפרויקט אחר (קורבן). במקום זאת, Firebase Auth מאפשר לטפל בכל תהליך OAuth ובהחלפת קוד ההרשאה באמצעות מזהה הלקוח והסוד של OAuth שהוגדרו במסוף Firebase. מכיוון שאפשר להשתמש בקוד ההרשאה רק בשילוב עם מזהה לקוח או סוד לקוח ספציפיים, אי אפשר להשתמש בקוד הרשאה שהתקבל לפרויקט אחד בפרויקט אחר.

אם צריך להשתמש בספקים האלה בסביבות שלא נתמכות, צריך להשתמש בספריית OAuth של צד שלישי ובאימות מותאם אישית של Firebase. הראשון נדרש לאימות מול הספק, והשני נדרש כדי להחליף את פרטי הכניסה של הספק באסימון מותאם אישית.

אימות באמצעות Firebase בתוסף ל-Chrome

אם אתם מפתחים אפליקציה לתוסף ל-Chrome, כדאי לעיין במדריך בנושא מסמכים מחוץ למסך.

בזמן יצירת הפרויקט, מערכת Firebase תקצה תת-דומיין ייחודי לפרויקט: https://my-app-12345.firebaseapp.com.

הוא ישמש גם כמנגנון להפניה אוטומטית לכניסה באמצעות OAuth. צריך להעניק הרשאה לדומיין הזה לכל ספקי OAuth הנתמכים. עם זאת, פירוש הדבר הוא שהמשתמשים עשויים לראות את הדומיין הזה בזמן הכניסה ל-Microsoft, לפני ההפניה האוטומטית חזרה לאפליקציה: Continue to: https://my-app-12345.firebaseapp.com.

כדי למנוע הצגה של תת-הדומיין, אפשר להגדיר דומיין מותאם אישית באמצעות Firebase Hosting:

  1. פועלים לפי השלבים 1 עד 3 במאמר הגדרת הדומיין ל-Hosting. כשמאמתים את הבעלות על הדומיין, Hosting מקצה אישור SSL לדומיין המותאם אישית.
  2. מוסיפים את הדומיין המותאם אישית לרשימת הדומיינים המורשים במסוף Firebase: auth.custom.domain.com.
  3. במסוף הפיתוח של Microsoft או בדף ההגדרה של OAuth, מוסיפים לרשימת ההיתרים את כתובת ה-URL של דף ההפניה האוטומטית, שאפשר יהיה לגשת אליה בדומיין המותאם אישית: https://auth.custom.domain.com/__/auth/handler.
  4. כשמאתחלים את ספריית ה-JavaScript, מציינים את הדומיין המותאם אישית באמצעות השדה 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);

השלבים הבאים

אחרי שמשתמש נכנס לחשבון בפעם הראשונה, נוצר חשבון משתמש חדש שמקושר לפרטי הכניסה – כלומר שם המשתמש והסיסמה, מספר הטלפון או פרטי ספק האימות – שבאמצעותם המשתמש נכנס לחשבון. החשבון החדש הזה מאוחסן כחלק מפרויקט Firebase, וניתן להשתמש בו כדי לזהות משתמש בכל האפליקציות בפרויקט, ללא קשר לאופן שבו המשתמש נכנס לחשבון.

  • באפליקציות, הדרך המומלצת לדעת את סטטוס האימות של המשתמש היא להגדיר משתמש מעקב על האובייקט Auth. לאחר מכן תוכלו לקבל את פרטי הפרופיל הבסיסיים של המשתמש מהאובייקט User. ניהול משתמשים

  • בכללי האבטחה של Firebase Realtime Database ו-Cloud Storage, אפשר לקבל את מזהה המשתמש הייחודי של המשתמש שנכנס לחשבון מהמשתנה auth, ולהשתמש בו כדי לקבוע לאילו נתונים למשתמש תהיה גישה.

כדי לאפשר למשתמשים להיכנס לאפליקציה באמצעות כמה ספקי אימות, אפשר לקשר את פרטי הכניסה של ספק האימות לחשבון משתמש קיים.

כדי להוציא משתמש מהחשבון, קוראים לפונקציה 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.
});