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

يمكنك السماح للمستخدمين بالمصادقة مع Firebase باستخدام معرف Apple الخاص بهم باستخدام Firebase SDK لتنفيذ تدفق تسجيل الدخول من طرف إلى طرف OAuth 2.0.

قبل ان تبدأ

لتسجيل دخول المستخدمين باستخدام Apple ، قم أولاً بتكوين Sign In with Apple على موقع مطوري Apple ، ثم قم بتمكين Apple كموفر تسجيل الدخول لمشروع Firebase الخاص بك.

انضم إلى برنامج Apple Developer

لا يمكن تكوين تسجيل الدخول باستخدام Apple إلا من قبل أعضاء برنامج Apple Developer Program .

قم بتكوين تسجيل الدخول مع Apple

في موقع Apple Developer ، قم بما يلي:

  1. قم بربط موقع الويب الخاص بك بتطبيقك كما هو موضح في القسم الأول من تكوين تسجيل الدخول باستخدام Apple للويب . عند المطالبة ، قم بتسجيل عنوان URL التالي كعنوان URL للعودة:

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

    يمكنك الحصول على معرّف مشروع Firebase في صفحة إعدادات وحدة تحكم Firebase .

    عند الانتهاء ، قم بتدوين معرف الخدمة الجديد الخاص بك ، والذي ستحتاج إليه في القسم التالي.

  2. قم بإنشاء تسجيل الدخول باستخدام مفتاح Apple الخاص . ستحتاج إلى مفتاحك الخاص الجديد ومعرف المفتاح في القسم التالي.
  3. إذا كنت تستخدم أيًا من ميزات Firebase Authentication التي ترسل رسائل بريد إلكتروني إلى المستخدمين ، بما في ذلك تسجيل الدخول إلى رابط البريد الإلكتروني والتحقق من عنوان البريد الإلكتروني وإلغاء تغيير الحساب وغير ذلك ، فقم بتهيئة خدمة ترحيل البريد الإلكتروني الخاص من Apple وتسجيل noreply@ YOUR_FIREBASE_PROJECT_ID .firebaseapp.com (أو مجال قالب البريد الإلكتروني المخصص الخاص بك) حتى تتمكن Apple من ترحيل رسائل البريد الإلكتروني المرسلة بواسطة Firebase Authentication إلى عناوين بريد إلكتروني مجهولة الهوية من Apple.

قم بتمكين Apple كموفر تسجيل الدخول

  1. أضف Firebase إلى مشروعك .
  2. في وحدة تحكم Firebase ، افتح قسم المصادقة . في علامة التبويب طريقة تسجيل الدخول ، قم بتمكين موفر Apple . حدد معرّف الخدمة الذي أنشأته في القسم السابق. أيضًا ، في قسم تكوين تدفق كود OAuth ، حدد معرف فريق Apple الخاص بك والمفتاح الخاص ومعرف المفتاح اللذين أنشأتهما في القسم السابق.

الامتثال لمتطلبات البيانات المجهولة الهوية من Apple

يمنح تسجيل الدخول مع Apple المستخدمين خيار إخفاء هوية بياناتهم ، بما في ذلك عنوان بريدهم الإلكتروني ، عند تسجيل الدخول. المستخدمون الذين يختارون هذا الخيار لديهم عناوين بريد إلكتروني مع المجال privaterelay.appleid.com . عندما تستخدم تسجيل الدخول مع Apple في تطبيقك ، يجب أن تمتثل لأي سياسات مطور أو شروط مطبقة من Apple فيما يتعلق بمعرفات Apple المجهولة الهوية.

يتضمن ذلك الحصول على أي موافقة مطلوبة من المستخدم قبل ربط أي معلومات شخصية تحدد الهوية مباشرة بمعرف Apple المجهول. عند استخدام مصادقة Firebase ، قد يشمل ذلك الإجراءات التالية:

  • اربط عنوان بريد إلكتروني بمعرف Apple المجهول أو العكس.
  • اربط رقم هاتف بمعرف Apple المجهول أو العكس
  • اربط بيانات اعتماد اجتماعية غير مجهولة (Facebook و Google وما إلى ذلك) بمعرف Apple مجهول أو العكس.

القائمة أعلاه ليست شاملة. راجع اتفاقية ترخيص برنامج مطوري Apple في قسم العضوية لحساب المطور الخاص بك للتأكد من أن تطبيقك يلبي متطلبات Apple.

تعامل مع تدفق تسجيل الدخول باستخدام Firebase SDK

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

للتعامل مع تدفق تسجيل الدخول باستخدام Firebase JavaScript SDK ، اتبع الخطوات التالية:

  1. أنشئ مثيلاً لـ OAuthProvider باستخدام معرف الموفر المقابل 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. اختياري: حدد نطاقات OAuth 2.0 إضافية بخلاف النطاق الافتراضي الذي تريد طلبه من موفر المصادقة.

    Web modular API

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

    Web namespaced API

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

    بشكل افتراضي ، عند تمكين حساب واحد لكل عنوان بريد إلكتروني ، يطلب Firebase نطاقات البريد الإلكتروني والاسم. إذا قمت بتغيير هذا الإعداد إلى حسابات متعددة لكل عنوان بريد إلكتروني ، فلن يطلب Firebase أي نطاقات من Apple ما لم تحددها.

  3. اختياري: إذا كنت تريد عرض شاشة تسجيل الدخول إلى Apple بلغة أخرى غير الإنجليزية ، فقم بتعيين معلمة locale . راجع تسجيل الدخول باستخدام مستندات Apple للتعرف على اللغات المدعومة.

    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. مصادقة مع Firebase باستخدام كائن موفر OAuth. يمكنك مطالبة المستخدمين بتسجيل الدخول بحساباتهم على Apple إما عن طريق فتح نافذة منبثقة أو عن طريق إعادة التوجيه إلى صفحة تسجيل الدخول. طريقة إعادة التوجيه مفضلة على الأجهزة المحمولة.

    • لتسجيل الدخول من خلال نافذة منبثقة ، اتصل بـ 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;
      
          // ...
        });
    • لتسجيل الدخول عن طريق إعادة التوجيه إلى صفحة تسجيل الدخول ، اتصل بـ signInWithRedirect() :

    اتبع أفضل الممارسات عند استخدام signInWithRedirect أو linkWithRedirect أو reauthenticateWithRedirect .

    Web modular API

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

    Web namespaced API

    firebase.auth().signInWithRedirect(provider);

    بعد أن يكمل المستخدم تسجيل الدخول والعودة إلى الصفحة ، يمكنك الحصول على نتيجة تسجيل الدخول عن طريق استدعاء 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;
    
        // ...
      });

    هذا هو المكان الذي يمكنك فيه اكتشاف الأخطاء ومعالجتها. للحصول على قائمة برموز الخطأ ، راجع مرجع API .

    على عكس الموفرين الآخرين المدعومين من Firebase Auth ، لا تقدم Apple عنوان URL للصورة.

    أيضًا ، عندما يختار المستخدم عدم مشاركة بريده الإلكتروني مع التطبيق ، توفر Apple عنوان بريد إلكتروني فريدًا لهذا المستخدم (بالشكل xyz@privaterelay.appleid.com ) ، والذي تشاركه مع تطبيقك. إذا قمت بتكوين خدمة ترحيل البريد الإلكتروني الخاص ، فإن Apple تعيد توجيه رسائل البريد الإلكتروني المرسلة إلى العنوان المجهول إلى عنوان البريد الإلكتروني الحقيقي للمستخدم.

    تشارك Apple معلومات المستخدم فقط مثل اسم العرض مع التطبيقات في المرة الأولى التي يسجل فيها المستخدم الدخول. عادةً ما يخزن Firebase اسم العرض في المرة الأولى التي يسجل فيها المستخدم الدخول مع Apple ، والذي يمكنك الحصول عليه باستخدام firebase.auth().currentUser.displayName . ومع ذلك ، إذا سبق لك استخدام Apple لتسجيل دخول مستخدم إلى التطبيق دون استخدام Firebase ، فلن تقدم Apple اسم عرض المستخدم لـ Firebase.

إعادة المصادقة وربط الحساب

يمكن استخدام النمط نفسه مع reauthenticateWithPopup() reauthenticateWithRedirect() ، والتي يمكنك استخدامها لاسترداد بيانات اعتماد حديثة للعمليات الحساسة التي تتطلب تسجيل دخول حديثًا:

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;

    // ...
  });

ويمكنك استخدام linkWithPopup() و linkWithRedirect() لربط موفري الهوية المختلفين بالحسابات الموجودة.

لاحظ أن Apple تطلب منك الحصول على موافقة صريحة من المستخدمين قبل ربط حسابات Apple الخاصة بهم ببيانات أخرى.

على سبيل المثال ، لربط حساب Facebook بحساب Firebase الحالي ، استخدم رمز الوصول الذي حصلت عليه من تسجيل دخول المستخدم إلى Facebook:

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

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

إذا كنت بصدد إنشاء تطبيق ملحق Chrome ، فيجب عليك إضافة معرف إضافة Chrome الخاص بك:

  1. افتح مشروعك في وحدة تحكم Firebase .
  2. في قسم المصادقة ، افتح صفحة طريقة تسجيل الدخول .
  3. أضف URI مثل ما يلي إلى قائمة المجالات المصرح بها:
    chrome-extension://CHROME_EXTENSION_ID

تتوفر فقط العمليات المنبثقة ( signInWithPopup و linkWithPopup و reauthenticateWithPopup ) لإضافات Chrome ، نظرًا لأن ملحقات Chrome لا يمكنها استخدام عمليات إعادة توجيه HTTP. يجب عليك استدعاء هذه الأساليب من برنامج نصي لصفحة الخلفية بدلاً من نافذة منبثقة لإجراء المستعرض ، حيث ستلغي نافذة المصادقة المنبثقة نافذة إجراء المتصفح المنبثقة. لا يجوز استخدام الأساليب المنبثقة إلا في الامتدادات التي تستخدم Manifest V2 . يسمح إصدار Manifest V3 الأحدث فقط بنصوص الخلفية في شكل عمال خدمة ، ولا يمكنهم تنفيذ عمليات النوافذ المنبثقة على الإطلاق.

في ملف البيان الخاص بامتداد Chrome ، تأكد من إضافة https://apis.google.com URL إلى content_security_policy allowlist.

لاحظ أنه لا يزال يتعين عليك التحقق من المجال المخصص مع Apple بشكل مشابه لمجال firebaseapp.com الافتراضي:

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

متقدم: المصادقة باستخدام Firebase في Node.js

للمصادقة مع Firebase في تطبيق Node.js:

  1. قم بتسجيل الدخول إلى المستخدم باستخدام حساب Apple الخاص به واحصل على رمز معرف Apple الخاص بالمستخدم. يمكنك تحقيق ذلك بعدة طرق. على سبيل المثال ، إذا كان تطبيق Node.js الخاص بك يحتوي على واجهة أمامية للمتصفح:

    1. على الواجهة الخلفية ، أنشئ سلسلة عشوائية ("nonce") واحسب تجزئة SHA256. nonce هي قيمة تستخدم لمرة واحدة تستخدمها للتحقق من رحلة واحدة ذهابًا وإيابًا بين الواجهة الخلفية وخوادم مصادقة 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. في صفحة تسجيل الدخول الخاصة بك ، حدد الرقم غير المجزأ في تكوين تسجيل الدخول باستخدام 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. احصل على رمز Apple ID المميز من جانب الخادم استجابة المصادقة POSTed:

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

    راجع أيضًا تكوين صفحة الويب الخاصة بك لتسجيل الدخول مع Apple .

  2. بعد الحصول على رمز معرف Apple الخاص بالمستخدم ، استخدمه لإنشاء كائن بيانات الاعتماد ثم تسجيل دخول المستخدم باستخدام بيانات الاعتماد:

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

الخطوات التالية

بعد أن يقوم المستخدم بتسجيل الدخول لأول مرة ، يتم إنشاء حساب مستخدم جديد وربطه ببيانات الاعتماد - أي اسم المستخدم وكلمة المرور أو رقم الهاتف أو معلومات موفر المصادقة - المستخدم الذي قام بتسجيل الدخول باستخدام. يتم تخزين هذا الحساب الجديد كجزء من مشروع Firebase الخاص بك ، ويمكن استخدامه لتحديد هوية مستخدم عبر كل تطبيق في مشروعك ، بغض النظر عن كيفية تسجيل المستخدم للدخول.

  • في تطبيقاتك ، الطريقة الموصى بها لمعرفة حالة المصادقة للمستخدم الخاص بك هي تعيين مراقب على كائن Auth . يمكنك بعد ذلك الحصول على معلومات ملف التعريف الأساسية للمستخدم من كائن User . انظر إدارة المستخدمين .

  • في قاعدة بيانات Firebase Realtime وقواعد أمان التخزين السحابي ، يمكنك الحصول على معرف المستخدم الفريد للمستخدم الذي قام بتسجيل الدخول من متغير auth ، واستخدامه للتحكم في البيانات التي يمكن للمستخدم الوصول إليها.

يمكنك السماح للمستخدمين بتسجيل الدخول إلى تطبيقك باستخدام موفري مصادقة متعددين عن طريق ربط بيانات اعتماد موفر المصادقة بحساب مستخدم حالي.

لتسجيل خروج مستخدم ، قم 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.
});