المصادقة باستخدام Microsoft مع JavaScript

يمكنك السماح للمستخدمين بالمصادقة باستخدام Firebase من خلال مقدّمي خدمات OAuth، مثل Microsoft Azure Active Directory، وذلك من خلال دمج ميزة تسجيل الدخول العامة باستخدام OAuth في تطبيقك باستخدام حزمة تطوير البرامج (SDK) لمنصّة Firebase لتنفيذ عملية تسجيل الدخول من البداية إلى النهاية.

قبل البدء

لتسجيل دخول المستخدمين باستخدام حسابات Microsoft (Azure Active Directory وحسابات Microsoft الشخصية)، عليك أولاً تفعيل Microsoft كمقدّم خدمة تسجيل الدخول لمشروعك على Firebase:

  1. أضِف Firebase إلى مشروع JavaScript.
  2. في وحدة تحكّم Firebase، افتح قسم Auth.
  3. في علامة التبويب طريقة تسجيل الدخول، فعِّل موفِّر Microsoft.
  4. أضِف معرّف العميل وسر العميل من وحدة تحكّم المطوّر لدى موفِّر الخدمة إلى إعدادات موفِّر الخدمة:
    1. لتسجيل عميل Microsoft OAuth، اتّبِع التعليمات الواردة في البدء السريع: تسجيل تطبيق باستخدام نقطة نهاية Azure Active Directory 2.0. يُرجى العِلم أنّ نقطة النهاية هذه تتيح تسجيل الدخول باستخدام حسابات Microsoft الشخصية وحسابات Azure Active Directory. مزيد من المعلومات عن الإصدار 2.0 من Azure Active Directory
    2. عند تسجيل التطبيقات لدى مقدّمي الخدمة هؤلاء، احرص على تسجيل نطاق *.firebaseapp.com لمشروعك كسمة نطاق إعادة التوجيه لتطبيقك.
  5. انقر على حفظ.

التعامل مع مسار تسجيل الدخول باستخدام حزمة تطوير البرامج (SDK) لمنصّة Firebase

إذا كنت بصدد إنشاء تطبيق ويب، فإنّ أسهل طريقة لمصادقة المستخدمين باستخدام Firebase باستخدام حساباتهم على Microsoft هي معالجة عملية تسجيل الدخول بالكامل باستخدام حزمة تطوير البرامج (SDK) لـ JavaScript في Firebase.

لمعالجة عملية تسجيل الدخول باستخدام حزمة تطوير البرامج 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) للمستأجر. ويمكن إجراء ذلك من خلال تحديد الحقل "مستأجر" في عنصر المَعلمات المخصّصة.

    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 object المعروض.

    باستخدام رمز الوصول OAuth، يمكنك استدعاء Microsoft Graph API.

    على سبيل المثال، للحصول على المعلومات الأساسية للملف الشخصي، يمكن استدعاء واجهة برمجة التطبيقات REST API التالية:

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

    على عكس مقدّمي الخدمات الآخرين المتوافقين مع Firebase Auth، لا تقدّم Microsoft عنوان URL للصورة، وبدلاً من ذلك، يجب طلب البيانات الثنائية لصورة الملف الشخصي من خلال Microsoft Graph API.

    بالإضافة إلى رمز دخول OAuth، يمكن أيضًا استرداد رمز تعريف OAuth الخاص بالمستخدم من عنصر firebase.auth.UserCredential. تكون مطالبة sub في رمز التعريف خاصة بالتطبيق ولن تتطابق مع معرّف المستخدِم الموحّد الذي تستخدمه Firebase Auth ويمكن الوصول إليه من خلال 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 الذي يمكن استخدامه ل retrieving fresh credentials for sensitive operations that require recent login.

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

إذا فعّلت الإعداد حساب واحد لكل عنوان بريد إلكتروني في وحدة تحكّم 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 Auth الميزة نفسها لمقدّمي خدمات مثل Microsoft بسبب عدم تمكّن خادم Firebase Auth من التحقّق من جمهور رموز الوصول OAuth من Microsoft. هذا شرط أمان مهم ويمكن أن يعرّض التطبيقات والمواقع الإلكترونية لهجمات إعادة التشغيل التي يمكن فيها استخدام رمز مميّز للوصول إلى Microsoft OAuth تم الحصول عليه لمشروع واحد (المهاجم) لتسجيل الدخول إلى مشروع آخر (الضحية). بدلاً من ذلك، توفّر Firebase Auth إمكانية معالجة مسار OAuth بالكامل وتبادل رمز التفويض باستخدام معرّف عميل OAuth وسرّه اللذين تم ضبطهما في "وحدة تحكّم Firebase". بما أنّه لا يمكن استخدام رمز التفويض إلا مع معرّف/مفتاح سري محدّد للعميل، لا يمكن استخدام رمز التفويض الذي تم الحصول عليه لمشروع معيّن مع مشروع آخر.

إذا كان من المطلوب استخدام مقدّمي الخدمات هؤلاء في بيئات غير متوافقة، يجب استخدام مكتبة OAuth تابعة لجهة خارجية و مصادقة مخصّصة في Firebase. ويُستخدَم الأول للمصادقة مع مقدّم الخدمة، ويُستخدَم الثاني لتبادل بيانات اعتماد مقدّم الخدمة للحصول على رمز مميّز مخصّص.

المصادقة باستخدام Firebase في إضافة Chrome

إذا كنت بصدد إنشاء تطبيق إضافة Chrome، اطّلِع على دليل "المستندات التي لا تظهر على الشاشة".

عند إنشاء المشروع، ستنشئ Firebase نطاقًا فرعيًا فريدًا لمشروعك: https://my-app-12345.firebaseapp.com.

وسيتم استخدامه أيضًا كآلية إعادة التوجيه لتسجيل الدخول باستخدام OAuth. يجب أن يكون هذا النطاق مسموحًا به لجميع موفّري OAuth المتوافقين. ومع ذلك، يعني ذلك أنّه قد يظهر للمستخدمين النطاق أثناء تسجيل الدخول إلى Microsoft قبل إعادة التوجيه إلى التطبيق: متابعة إلى: https://my-app-12345.firebaseapp.com.

لتجنّب عرض نطاقك الفرعي، يمكنك إعداد نطاق خاص باستخدام Firebase Hosting:

  1. اتّبِع الخطوات من 1 إلى 3 في مقالة إعداد نطاقك لخدمة Hosting. عند إثبات ملكية نطاقك، يوفّر Hosting شهادة طبقة المقابس الآمنة لنطاقك المخصّص.
  2. أضِف نطاقك المخصّص إلى قائمة النطاقات المعتمَدة في وحدة تحكّم Firebase: auth.custom.domain.com.
  3. في Microsoft developer console أو صفحة إعداد 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.
});