OAuth 2.0 لتطبيقات الويب من جهة العميل

تنظيم صفحاتك في مجموعات يمكنك حفظ المحتوى وتصنيفه حسب إعداداتك المفضّلة.

يوضح هذا المستند كيفية تنفيذ تفويض OAuth 2.0 للدخول إلى Google APIs من تطبيق ويب جافا سكريبت. يتيح بروتوكول OAuth 2.0 للمستخدمين مشاركة بيانات محدّدة مع تطبيق مع الحفاظ على خصوصية أسماء المستخدمين وكلمات المرور والمعلومات الأخرى. على سبيل المثال، يمكن للتطبيق استخدام OAuth 2.0 للحصول على إذن من المستخدمين لتخزين الملفات في Google Drive.

ويُطلق على تدفق OAuth 2.0 هذا اسم مسار المنح الضمني. وهي مصممة للتطبيقات التي تدخل إلى واجهات برمجة التطبيقات فقط أثناء وجود المستخدم في التطبيق. ولا يمكن لهذه التطبيقات تخزين المعلومات السرية.

في هذه العملية، يفتح تطبيقك عنوان URL من Google يستخدم معلَمات طلب البحث لتحديد تطبيقك ونوع الوصول إلى واجهة برمجة التطبيقات الذي يطلبه التطبيق. يمكنك فتح عنوان URL في نافذة المتصفّح الحالية أو نافذة منبثقة. يمكن للمستخدم المصادقة مع Google ومنح الأذونات المطلوبة. وبعد ذلك، تُعيد Google توجيه المستخدم مرة أخرى إلى تطبيقك. وتتضمّن عملية إعادة التوجيه رمزًا مميّزًا للوصول يتحقق منه تطبيقك ثم يستخدمه في إجراء طلبات البيانات من واجهة برمجة التطبيقات.

المتطلبات الأساسية

تفعيل واجهات برمجة التطبيقات لمشروعك

يحتاج أي تطبيق يستدعي Google APIs إلى تفعيل واجهات برمجة التطبيقات هذه في API Console.

لتمكين واجهة برمجة تطبيقات لمشروعك:

  1. Open the API Library في Google API Console.
  2. If prompted, select a project, or create a new one.
  3. يضم API Library القائمة جميع واجهات برمجة التطبيقات المتاحة، مجمّعةً حسب عائلة المنتج وشعبيته. إذا كانت واجهة برمجة التطبيقات التي تريد تفعيلها غير مرئية في القائمة، استخدم البحث للعثور عليها، أو انقر على عرض الكل في مجموعة المنتجات التي تنتمي إليها.
  4. حدد واجهة برمجة التطبيقات التي تريد تمكينها، ثم انقر على الزر تمكين.
  5. If prompted, enable billing.
  6. If prompted, read and accept the API's Terms of Service.

إنشاء بيانات اعتماد التفويض

يجب أن يحتوي أي تطبيق يستخدم OAuth 2.0 للدخول إلى Google APIs على بيانات اعتماد مصادقة تحدد التطبيق في خادم OAuth 2.0 في Google. توضّح الخطوات التالية كيفية إنشاء بيانات اعتماد لمشروعك. ويمكن للتطبيقات بعد ذلك استخدام بيانات الاعتماد للوصول إلى واجهات برمجة التطبيقات التي فعّلتها لهذا المشروع.

  1. Go to the Credentials page.
  2. انقر على إنشاء بيانات اعتماد > معرِّف عميل OAuth.
  3. حدد نوع تطبيق تطبيق الويب.
  4. أكمل النموذج. يجب أن تحدِّد التطبيقات التي تستخدم JavaScript لإجراء طلبات Google API مُعتمَدة مصادر JavaScript المعتمَدة. تحدد المصادر النطاقات التي يمكن لتطبيقك إرسال طلبات من خلالها إلى خادم OAuth 2.0. ويجب أن تكون هذه المصادر متوافقة مع قواعد التحقّق من صحّة Google.

تحديد نطاقات الوصول

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

قبل البدء في تنفيذ تفويض OAuth 2.0، ننصحك بتحديد النطاقات التي سيحتاج تطبيقك إلى إذن للوصول إليها.

يحتوي مستند نطاقات واجهة برمجة التطبيقات OAuth 2.0 على قائمة كاملة بالنطاقات التي يمكنك استخدامها للوصول إلى Google APIs.

الحصول على رموز دخول OAuth 2.0 المميزة

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

الخطوة 1: ضبط كائن العميل

إذا كنت تستخدم مكتبة عميل "واجهات برمجة تطبيقات Google" للغة JavaScript للتعامل مع تدفق OAuth 2.0، عليك أولاً ضبط الكائنين gapi.auth2 وgapi.client. وتمكِّن هذه الكائنات تطبيقك من الحصول على تفويض المستخدم من خلال طلب بيانات من واجهة برمجة التطبيقات.

يحدد كائن العميل النطاقات التي يطلب تطبيقك الحصول على إذن للوصول إليها. تُعلِم هذه القيم شاشة الموافقة التي تعرضها Google للمستخدم.

مكتبة عميل JavaScript

تبسّط مكتبة عميل JavaScript العديد من جوانب عملية التفويض:

  1. ويتم إنشاء عنوان URL لإعادة التوجيه لخادم تفويض Google، كما يوفر طريقة لتوجيه المستخدم إلى عنوان URL هذا.
  2. وتعالج هذه العملية إعادة التوجيه من هذا الخادم إلى تطبيقك.
  3. ويتحقق من صحة رمز الدخول المميز الذي يعرضه خادم المصادقة.
  4. وهو يخزّن رمز الدخول المميز الذي يرسله خادم التفويض إلى تطبيقك ويسترده عند إجراء تطبيقك لاستدعاءات واجهة برمجة التطبيقات المصرح بها لاحقًا.

مقتطف الرمز أدناه هو مقتطف من المثال الكامل الموضح لاحقًا في هذا المستند. يؤدي هذا الرمز إلى تهيئة الكائن gapi.client، والذي سيستخدمه تطبيقك لاحقًا لإجراء طلبات بيانات من واجهة برمجة التطبيقات. عند إنشاء هذا الكائن، يتم أيضًا إعداد الكائن gapi.auth2، الذي يستخدمه تطبيقك للتحقق من حالة التفويض للمستخدم ومراقبتها.

يحدد الاستدعاء إلى gapi.client.init الحقول التالية:

  • تحدد القيم apiKey وclientId بيانات اعتماد مصادقة التطبيق. كما تمت مناقشته في القسم إنشاء بيانات اعتماد التفويض، يمكن الحصول على هذه القيم في API Console. وتجدر الإشارة إلى أنّ السمة clientId مطلوبة إذا كان تطبيقك يقدّم طلبات مُعتمَدة من واجهة برمجة التطبيقات. يمكن للتطبيقات التي تجري طلبات غير مصرّح بها فقط تحديد مفتاح واجهة برمجة تطبيقات.
  • يحدّد الحقل scope قائمة مفصولة بمسافات من نطاقات الوصول التي تتوافق مع الموارد التي يمكن لتطبيقك الوصول إليها نيابةً عن المستخدم. وتحدِّد هذه القيم شاشة طلب الموافقة التي تعرضها Google للمستخدم.

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

  • يحدّد الحقل discoveryDocs قائمة بمستندات "اكتشاف واجهة برمجة التطبيقات" التي يستخدمها تطبيقك. ويوضّح المستند أثناء التصفّح مساحة من واجهة برمجة التطبيقات، بما في ذلك مخططات الموارد، وتستخدم مكتبة عميل JavaScript هذه المعلومات لإنشاء طرق يمكن للتطبيقات استخدامها. في هذا المثال، تسترد الشفرة مستند الاكتشاف للإصدار 3 من واجهة برمجة تطبيقات Google Drive.

بعد اكتمال الاستدعاء gapi.client.init، تضبط الرمز المتغيّر GoogleAuth لتحديد كائن Google Auth. وأخيرًا، يحدّد الرمز أداة معالجة تعمل على استدعاء وظيفة عند تغيّر حالة تسجيل دخول المستخدم. (لم يتم تعريف هذه الدالة في المقتطف).

var GoogleAuth; // Google Auth object.
function initClient() {
  gapi.client.init({
      'apiKey': 'YOUR_API_KEY',
      'clientId': 'YOUR_CLIENT_ID',
      'scope': 'https://www.googleapis.com/auth/drive.metadata.readonly',
      'discoveryDocs': ['https://www.googleapis.com/discovery/v1/apis/drive/v3/rest']
  }).then(function () {
      GoogleAuth = gapi.auth2.getAuthInstance();

      // Listen for sign-in state changes.
      GoogleAuth.isSignedIn.listen(updateSigninStatus);
  });
}

نقاط نهاية OAuth 2.0

إذا كنت تدخل مباشرةً إلى نقاط نهاية OAuth 2.0، يمكنك المتابعة إلى الخطوة التالية.

الخطوة 2: إعادة التوجيه إلى خادم OAuth 2.0 من Google

لطلب إذن للوصول إلى بيانات المستخدم، أعِد توجيه المستخدم إلى خادم OAuth 2.0 في Google.

مكتبة عميل JavaScript

وعليك استدعاء الطريقة GoogleAuth.signIn() لتوجيه المستخدم إلى خادم تفويض Google.

GoogleAuth.signIn();

عمليًا، قد يضبط تطبيقك قيمة منطقية لتحديد ما إذا كان سيتم طلب طريقة signIn() قبل محاولة إجراء طلب بيانات من واجهة برمجة التطبيقات.

يوضح مقتطف الشفرة أدناه كيفية بدء تدفق تفويض المستخدم. لاحظ النقاط التالية عن المقتطف:

  • الكائن GoogleAuth المُشار إليه في الرمز هو نفسه المتغير العمومي المحدّد في مقتطف الرمز في الخطوة 1.

  • الدالة updateSigninStatus هي أداة معالجة تستمع إلى التغييرات في حالة تفويض المستخدم. وتم أيضًا تحديد دور المستمع في مقتطف الرمز في الخطوة 1:
    GoogleAuth.isSignedIn.listen(updateSigninStatus);
  • يحدد المقتطف متغيرين عموميين إضافيين:

    • isAuthorized هي متغير منطقي يشير إلى ما إذا كان المستخدم قد سجّل الدخول. يمكن ضبط هذه القيمة عند تحميل التطبيق وتحديثه إذا سجّل المستخدم الدخول إلى التطبيق أو الخروج منه.

      في هذا المقتطف، تتحقّق الدالة sendAuthorizedApiRequest من قيمة المتغيّر لتحديد ما إذا كان على التطبيق محاولة طلب واجهة برمجة التطبيقات الذي يتطلب إذنًا أو مطالبة المستخدم بتفويض التطبيق.

    • currentApiRequest هي كائن يخزّن تفاصيل حول آخر طلب من واجهة برمجة التطبيقات حاول المستخدم تنفيذه. يتم ضبط قيمة الكائن عندما يطلب التطبيق الوظيفة sendAuthorizedApiRequest.

      في حال فوَّض المستخدم التطبيق، سيتم تنفيذ الطلب على الفور. وإلا ستعيد الدالة توجيه المستخدم لتسجيل الدخول. بعد أن يسجِّل المستخدم الدخول، تستدعي الدالة updateSignInStatus sendAuthorizedApiRequest، مع تمرير الطلب نفسه الذي تمت محاولة إجرائه قبل بدء عملية التفويض.

var isAuthorized;
var currentApiRequest;

/**
 * Store the request details. Then check to determine whether the user
 * has authorized the application.
 *   - If the user has granted access, make the API request.
 *   - If the user has not granted access, initiate the sign-in flow.
 */
function sendAuthorizedApiRequest(requestDetails) {
  currentApiRequest = requestDetails;
  if (isAuthorized) {
    // Make API request
    // gapi.client.request(requestDetails)

    // Reset currentApiRequest variable.
    currentApiRequest = {};
  } else {
    GoogleAuth.signIn();
  }
}

/**
 * Listener called when user completes auth flow. If the currentApiRequest
 * variable is set, then the user was prompted to authorize the application
 * before the request executed. In that case, proceed with that API request.
 */
function updateSigninStatus(isSignedIn) {
  if (isSignedIn) {
    isAuthorized = true;
    if (currentApiRequest) {
      sendAuthorizedApiRequest(currentApiRequest);
    }
  } else {
    isAuthorized = false;
  }
}

نقاط نهاية OAuth 2.0

يمكنك إنشاء عنوان URL لطلب الوصول من نقطة نهاية OAuth 2.0 من Google على https://accounts.google.com/o/oauth2/v2/auth. يمكن الوصول إلى نقطة النهاية هذه عبر HTTPS، ويتم رفض اتصالات HTTP العادية.

يتيح خادم تفويض Google معلَمات سلسلة طلب البحث التالية لتطبيقات خادم الويب:

المعلَمات
client_id مطلوب

معرِّف العميل لتطبيقك. ويمكنك العثور على هذه القيمة في API Console Credentials page.

redirect_uri مطلوب

يحدِّد هذا الإعداد الموضع الذي يُعيد فيه خادم واجهة برمجة التطبيقات توجيه المستخدم بعد أن يُكمل عملية التفويض. يجب أن تتطابق القيمة تطابقًا تامًا مع أحد معرّفات الموارد المنتظمة (URI) المُعتمَدة لإعادة التوجيه لعميل OAuth 2.0 الذي تم إعداده في API Console Credentials pageللعميل. وإذا لم تتطابق هذه القيمة مع معرّف الموارد المنتظم (URI) المُعتمَد لإعادة التوجيه للسمة client_id المقدَّمة، ستظهر لك رسالة خطأ redirect_uri_mismatch.

تجدر الإشارة إلى أنه يجب أن يتطابق كل من الرمز http أو https والشرطة والشرطة المائلة اللاحقة ("/").

response_type مطلوب

تحتاج تطبيقات JavaScript إلى ضبط قيمة المعلّمة على token. توجِّه هذه القيمة خادم تفويض Google إلى إعادة رمز الدخول المميز كزوج من name=value في معرِّف الجزء من URI (#) الذي تتم إعادة توجيه المستخدم إليه بعد إكمال عملية التفويض.

scope مطلوب

قائمة من النطاقات المحدّدة بمسافات تحدّد الموارد التي يمكن لتطبيقك الوصول إليها نيابةً عن المستخدم. تُعلِم هذه القيم شاشة الموافقة التي تعرضها Google للمستخدم.

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

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

state سمة مقترَحة

لتحديد أي قيمة سلسلة يستخدمها تطبيقك للحفاظ على الحالة بين طلب التفويض واستجابة خادم التفويض. يعرض الخادم القيمة الدقيقة التي ترسلها كزوج name=value في معرّف جزء عنوان URL (#) من redirect_uri بعد موافقة المستخدم على طلب وصول تطبيقك أو رفضه.

ويمكنك استخدام هذه المعلّمة لأغراض متعدّدة، مثل توجيه المستخدم إلى المورد الصحيح في تطبيقك وإرسال معلومات خاصة والتقليل من تزييف الطلبات عبر المواقع الإلكترونية. بما أنّه يمكن تخمين redirect_uri، يمكن أن يؤدي استخدام القيمة state إلى زيادة ضمان أنّ الاتصال الوارد هو نتيجة لطلب مصادقة. إذا أنشأت سلسلة عشوائية أو رمّزت تجزئة ملف تعريف ارتباط أو قيمة أخرى ترصد حالة العميل، يمكنك التحقّق من صحة الاستجابة بالإضافة إلى التأكد من أنّ الطلب والاستجابة صدرا من متصفّح واحد، ما يوفّر الحماية من الهجمات مثل تزوير الطلب من عدة مواقع إلكترونية. يمكنك الاطّلاع على مستندات OpenID Connect للتعرّف على مثال عن كيفية إنشاء رمز مميّز state وتأكيده.

include_granted_scopes اختياريّ

للسماح للتطبيقات باستخدام التفويض المتزايد لطلب الوصول إلى نطاقات إضافية في السياق. في حال ضبط قيمة هذه المَعلمة على true والموافقة على طلب التفويض، سيغطي رمز الدخول الجديد أيضًا أي نطاقات سبق أن منح المستخدم إذن الوصول إليها. يمكنك الاطّلاع على قسم التفويض المتزايد للحصول على أمثلة.

login_hint اختياريّ

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

اضبط قيمة المَعلمة على عنوان بريد إلكتروني أو معرّف sub، والذي يعادل رقم تعريف Google للمستخدم.

prompt اختياريّ

قائمة تتضمّن رسائل مطالبة لتوفير مساحة للمستخدم مفصولة بفواصل وحساسة لحالة الأحرف. إذا لم تحدِّد هذه المعلمة، سيُطلب من المستخدم الدخول فقط في المرة الأولى التي يطلب فيها مشروعك الوصول. اطّلِع على طلب إعادة الموافقة لمزيد من المعلومات.

القيم المحتملة هي:

none لا تعرض أي شاشات مصادقة أو موافقة. ويجب عدم تحديد قيم أخرى.
consent اطلب من المستخدم الموافقة.
select_account اطلب من المستخدم اختيار حساب.

نموذج إعادة التوجيه إلى خادم تفويض Google

في ما يلي مثال لعنوان URL، مع فواصل الأسطر والمسافات لسهولة القراءة.

https://accounts.google.com/o/oauth2/v2/auth?
 scope=https%3A//www.googleapis.com/auth/drive.metadata.readonly&
 include_granted_scopes=true&
 response_type=token&
 state=state_parameter_passthrough_value&
 redirect_uri=https%3A//oauth2.example.com/code&
 client_id=client_id

بعد إنشاء عنوان URL للطلب، أعِد توجيه المستخدم إليه.

نموذج شفرة جافا سكريبت

يعرض مقتطف JavaScript التالي طريقة بدء تدفق التفويض في JavaScript بدون استخدام "مكتبة عميل Google APIs" للغة JavaScript. بما أنّ نقطة نهاية بروتوكول OAuth 2.0 هذه لا تتوافق مع ميزة مشاركة الموارد المشتركة المنشأ (CORS)، فإن المقتطف ينشئ نموذجًا يفتح الطلب إلى نقطة النهاية هذه.

/*
 * Create form to request access token from Google's OAuth 2.0 server.
 */
function oauthSignIn() {
  // Google's OAuth 2.0 endpoint for requesting an access token
  var oauth2Endpoint = 'https://accounts.google.com/o/oauth2/v2/auth';

  // Create <form> element to submit parameters to OAuth 2.0 endpoint.
  var form = document.createElement('form');
  form.setAttribute('method', 'GET'); // Send as a GET request.
  form.setAttribute('action', oauth2Endpoint);

  // Parameters to pass to OAuth 2.0 endpoint.
  var params = {'client_id': 'YOUR_CLIENT_ID',
                'redirect_uri': 'YOUR_REDIRECT_URI',
                'response_type': 'token',
                'scope': 'https://www.googleapis.com/auth/drive.metadata.readonly',
                'include_granted_scopes': 'true',
                'state': 'pass-through value'};

  // Add form parameters as hidden input values.
  for (var p in params) {
    var input = document.createElement('input');
    input.setAttribute('type', 'hidden');
    input.setAttribute('name', p);
    input.setAttribute('value', params[p]);
    form.appendChild(input);
  }

  // Add form to page and submit it to open the OAuth 2.0 endpoint.
  document.body.appendChild(form);
  form.submit();
}

الخطوة 3: تطلب Google من المستخدم الموافقة

في هذه الخطوة، يقرر المستخدم ما إذا كان يريد منح التطبيق إمكانية الوصول المطلوبة أم لا. في هذه المرحلة، تعرض Google نافذة موافقة تعرض اسم تطبيقك وخدمات Google API التي تطلب إذنًا للوصول إليها من خلال بيانات اعتماد التفويض الخاصة بالمستخدم، بالإضافة إلى ملخص لنطاقات الوصول التي سيتم منحها. ويمكن للمستخدم بعد ذلك الموافقة على منح إمكانية الوصول إلى نطاق واحد أو أكثر من النطاقات التي يطلبها تطبيقك أو رفض الطلب.

لا يحتاج تطبيقك إلى اتخاذ أي إجراء في هذه المرحلة وهو ينتظر استجابة من خادم OAuth 2.0 من Google تشير إلى ما إذا كان قد تم منح أي إذن بالوصول أم لا. يتم شرح هذه الإجابة في الخطوة التالية.

الأخطاء

قد تعرض الطلبات المرسلة إلى نقطة نهاية تفويض OAuth 2.0 من Google رسائل خطأ موجهة للمستخدم بدلاً من تدفقات المصادقة والمصادقة المتوقعة. في ما يلي رموز الأخطاء الشائعة ودرجات الدقة المقترحة.

admin_policy_enforced

يتعذّر على حساب Google تفويض نطاق واحد أو أكثر من النطاقات المطلوبة بسبب سياسات مشرف Google Workspace. يُرجى الاطِّلاع على مقالة مساعدة مشرف Google Workspace التحكُّم في اختيار التطبيقات التابعة لجهات خارجية والتطبيقات الداخلية التي يمكنها الوصول إلى بيانات Google Workspace للحصول على مزيد من المعلومات عن كيفية تقييد المشرف لإمكانية الوصول إلى جميع النطاقات أو النطاقات الحساسة والمقيَّدة إلى أن يتم منح الوصول صراحةً إلى معرِّف عميل OAuth.

disallowed_useragent

يتم عرض نقطة نهاية التفويض داخل وكيل مستخدم مضمّن لا تسمح به سياسات OAuth 2.0 في Google.

Android

قد تظهر لمطوّري برامج Android رسالة الخطأ هذه عند فتح طلبات التفويض في android.webkit.WebView. وعلى مطوّري البرامج استخدام مكتبات Android، مثل تسجيل الدخول بحساب Google لنظام التشغيل Android أو AppAuth لأجهزة Android الخاصة بمؤسسة OpenID.

قد يواجه مطوّرو برامج الويب هذا الخطأ عندما يفتح تطبيق Android رابط ويب عامًا في وكيل مستخدم مضمّنًا وينتقل المستخدم إلى نقطة نهاية تفويض OAuth 2.0 من Google من موقعك الإلكتروني. على مطوّري البرامج السماح بفتح الروابط العامة في معالج الروابط التلقائي لنظام التشغيل، ويشمل ذلك معالجات روابط تطبيقات Android أو تطبيق المتصفّح التلقائي، علمًا بأنّ مكتبة علامات التبويب المخصّصة لنظام التشغيل Android هي خيار متوافق أيضًا.

iOS

قد يظهر هذا الخطأ لمطوّري تطبيقات iOS وmacOS عند فتح طلبات التفويض في WKWebView. وعلى مطوّري البرامج استخدام مكتبات iOS، مثل تسجيل الدخول بحساب Google لنظام التشغيل iOS أو AppAuth لنظام التشغيل iOS في مؤسسة OpenID.

قد يواجه مطوّرو البرامج على الويب هذا الخطأ عندما يفتح تطبيق iOS أو macOS رابط ويب عامًا في وكيل مستخدم مضمّنًا وينتقل المستخدم إلى نقطة نهاية تفويض OAuth 2.0 من Google من موقعك الإلكتروني. وعلى مطوّري البرامج السماح بفتح الروابط العامة في معالج الروابط التلقائي لنظام التشغيل، ويشمل ذلك معالجات الروابط العامة أو تطبيق المتصفّح التلقائي، علمًا بأنّ مكتبة SFSafariViewController هي خيار متوافق أيضًا.

org_internal

إنّ معرّف عميل OAuth في الطلب جزء من مشروع يحد من الوصول إلى حسابات Google في مؤسسة Google Cloud محددة. لمزيد من المعلومات عن خيار الضبط هذا، يمكنك الاطّلاع على القسم نوع المستخدم في مقالة المساعدة "إعداد شاشة موافقة OAuth".

invalid_client

إن المصدر الذي تم تقديم الطلب منه غير مصرّح به لهذا العميل. يمكنك الاطّلاع على origin_mismatch.

invalid_grant

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

origin_mismatch

قد لا يتطابق مخطط و/أو نطاق و/أو منفذ JavaScript الذي ينشئ طلب التفويض مع معرف الموارد المنتظم (URI) لأصل JavaScript المسجّل لمعرِّف عميل OAuth. راجِع مصادر JavaScript المعتمَدة في Google API Console Credentials page.

redirect_uri_mismatch

لا يتطابق رمز redirect_uri الذي تم تمريره في طلب التفويض مع معرِّف الموارد المنتظم (URI) المُعتمَد لإعادة التوجيه لمعرِّف عميل OAuth. راجِع معرّفات الموارد المنتظمة (URI) المُعتمَدة لإعادة التوجيه في Google API Console Credentials page.

قد لا يتطابق مخطط و/أو نطاق و/أو منفذ JavaScript الذي ينشئ طلب التفويض مع معرف الموارد المنتظم (URI) لأصل JavaScript المسجّل لمعرِّف عميل OAuth. راجِع مصادر JavaScript المعتمَدة في Google API Console Credentials page.

قد تشير المعلمة redirect_uri إلى مسار بروتوكول OAuth خارج النطاق (OOB) الذي تم إيقافه ولم يعد متوافقًا. يُرجى الرجوع إلى دليل نقل البيانات لتعديل عملية الدمج.

الخطوة 4: معالجة استجابة خادم OAuth 2.0

مكتبة عميل JavaScript

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

نقاط نهاية OAuth 2.0

يرسل خادم OAuth 2.0 استجابة إلى redirect_uri المحددة في طلب رمز الدخول.

إذا وافق المستخدم على الطلب، ستحتوي الاستجابة على رمز دخول. إذا لم يوافق المستخدم على الطلب، ستحتوي الاستجابة على رسالة خطأ. يتم عرض رمز الدخول أو رسالة الخطأ في جزء علامة التجزئة الخاص بمعرّف الموارد المنتظم (URI) لإعادة التوجيه، كما هو موضح أدناه:

  • استجابة رمز الدخول:

    https://oauth2.example.com/callback#access_token=4/P7q7W91&token_type=Bearer&expires_in=3600

    بالإضافة إلى المعلَمة access_token، تحتوي سلسلة الجزء أيضًا على المعلَمة token_type التي يتم ضبطها دائمًا على Bearer، والمَعلمة expires_in التي تحدد القيمة الدائمة للرمز المميّز بالثواني. إذا تم تحديد المعلمة state في طلب رمز الدخول، يتم تضمين قيمتها أيضًا في الاستجابة.

  • استجابة خطأ:
    https://oauth2.example.com/callback#error=access_denied

نموذج استجابة خادم OAuth 2.0

يمكنك اختبار هذه العملية بالنقر على نموذج عنوان URL التالي، والذي يطلب حق الوصول للقراءة فقط لعرض البيانات الوصفية للملفات في Google Drive:

https://accounts.google.com/o/oauth2/v2/auth?
 scope=https%3A//www.googleapis.com/auth/drive.metadata.readonly&
 include_granted_scopes=true&
 response_type=token&
 state=state_parameter_passthrough_value&
 redirect_uri=https%3A//oauth2.example.com/code&
 client_id=client_id

بعد إكمال مسار OAuth 2.0، ستتم إعادة توجيهك إلى http://localhost/oauth2callback. سيؤدي عنوان URL هذا إلى عرض رسالة خطأ 404 NOT FOUND إلا إذا عرض جهازك المحلي ملفًا على هذا العنوان. تقدم الخطوة التالية مزيدًا من التفاصيل حول المعلومات التي يتم عرضها في معرف الموارد المنتظم (URI) عند إعادة توجيه المستخدم مرة أخرى إلى تطبيقك.

استدعاء واجهات Google APIs

مكتبة عميل JavaScript

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

تدعم مكتبة العميل طريقتين لطلب طرق واجهة برمجة التطبيقات. في حال تحميل مستند أثناء التصفّح، ستحدّد واجهة برمجة التطبيقات الوظائف الخاصة بطريقة معيّنة. يمكنك أيضًا استخدام الدالة gapi.client.request لاستدعاء طريقة واجهة برمجة التطبيقات. يعرض المقتطفان التاليان هذه الخيارات لطريقة about.get واجهة برمجة تطبيقات Drive.

// Example 1: Use method-specific function
var request = gapi.client.drive.about.get({'fields': 'user'});

// Execute the API request.
request.execute(function(response) {
  console.log(response);
});


// Example 2: Use gapi.client.request(args) function
var request = gapi.client.request({
  'method': 'GET',
  'path': '/drive/v3/about',
  'params': {'fields': 'user'}
});
// Execute the API request.
request.execute(function(response) {
  console.log(response);
});

نقاط نهاية OAuth 2.0

بعد حصول تطبيقك على رمز دخول، يمكنك استخدام الرمز المميز لإجراء استدعاءات لواجهة برمجة تطبيقات Google نيابةً عن حساب مستخدم معيّن إذا تم منح نطاق الوصول المطلوب لواجهة برمجة التطبيقات. ولإجراء ذلك، يمكنك تضمين رمز الدخول في طلب إلى واجهة برمجة التطبيقات من خلال تضمين إما مَعلمة طلب البحث access_token أو قيمة Authorization لرأس HTTP Bearer. ويُفضّل استخدام عنوان HTTP كلما أمكن، لأن سلاسل طلبات البحث غالبًا ما تكون مرئية في سجلات الخادم. وفي معظم الحالات، يمكنك استخدام مكتبة برامج لإعداد عمليات استدعاء إلى Google APIs (على سبيل المثال، عند استدعاء واجهة برمجة تطبيقات ملفات Drive).

يمكنك تجربة جميع واجهات برمجة تطبيقات Google وعرض نطاقاتها في مساحة تخزين بروتوكول OAuth 2.0.

أمثلة HTTP GET

يمكن أن يبدو استدعاء نقطة نهاية drive.files (واجهة برمجة تطبيقات ملفات Drive) باستخدام رأس Authorization: Bearer HTTP على النحو التالي. لاحظ أنه يلزمك تحديد رمز الدخول الخاص بك:

GET /drive/v2/files HTTP/1.1
Host: www.googleapis.com
Authorization: Bearer access_token

في ما يلي استدعاء لواجهة برمجة التطبيقات نفسها للمستخدم الذي تمت المصادقة عليه باستخدام معلمة سلسلة طلب البحث access_token:

GET https://www.googleapis.com/drive/v2/files?access_token=access_token

أمثلة على curl

يمكنك اختبار هذه الأوامر باستخدام تطبيق سطر الأوامر curl. وفي ما يلي مثال يستخدم خيار رأس HTTP (مفضّل):

curl -H "Authorization: Bearer access_token" https://www.googleapis.com/drive/v2/files

أو بدلاً من ذلك، خيار معلمة سلسلة طلب البحث:

curl https://www.googleapis.com/drive/v2/files?access_token=access_token

نموذج شفرة جافا سكريبت

يوضح مقتطف الرمز أدناه كيفية استخدام مشاركة الموارد المشتركة المنشأ (CORS) لإرسال طلب إلى Google API. لا يستخدم هذا المثال مكتبة عميل "واجهات برمجة تطبيقات Google" للغة JavaScript. ومع ذلك، حتى إذا كنت لا تستخدم مكتبة العملاء، من المرجح أن يساعدك دليل دعم سياسة مشاركة الموارد المتعددة المصادر (CORS) في مستندات هذه المكتبة على فهم هذه الطلبات بشكل أفضل.

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

var xhr = new XMLHttpRequest();
xhr.open('GET',
    'https://www.googleapis.com/drive/v3/about?fields=user&' +
    'access_token=' + params['access_token']);
xhr.onreadystatechange = function (e) {
  console.log(xhr.response);
};
xhr.send(null);

مثال كامل

مكتبة عميل JavaScript

إصدار تجريبي لرمز نموذجي

يحتوي هذا القسم على عرض توضيحي تجريبي لعينة التعليمات البرمجية التالية لتوضيح كيفية عمل الرمز في تطبيق فعلي. بعد مصادقة التطبيق، سيتم إدراجه ضمن التطبيقات المرتبطة بحسابك في Google. ويحمل التطبيق اسم الإصدار التجريبي لبروتوكول OAuth 2.0 لمحرّر مستندات Google API. وبالمثل، إذا أبطلت إذن الوصول وحدّثت هذه الصفحة، لن يتم إدراج هذا التطبيق بعد ذلك.

يُرجى ملاحظة أن هذا التطبيق يطلب الوصول إلى نطاق https://www.googleapis.com/auth/drive.metadata.readonly. يتم طلب الوصول فقط لتوضيح كيفية بدء تدفق OAuth 2.0 في تطبيق JavaScript. لا يقدم هذا التطبيق أي طلبات واجهة برمجة تطبيقات.

نموذج شفرة جافا سكريبت

وكما هو موضح أعلاه، فإن نموذج الشفرة هذا يخص صفحة (تطبيق) تحمِّل مكتبة عميل Google APIs لجافا سكريبت وتبدأ تدفق OAuth 2.0. تعرض الصفحة إما:

  • زر واحد يسمح للمستخدم بتسجيل الدخول إلى التطبيق. وإذا لم يسبق للمستخدم السماح للتطبيق، سيتم تشغيل مسار OAuth 2.0.
  • زران يسمحان للمستخدم بالخروج من التطبيق أو إبطال الدخول الممنوح مسبقًا للتطبيق. إذا خرجت من التطبيق، فأنت لم تبطل إمكانية الوصول الممنوحة للتطبيق. ستحتاج إلى تسجيل الدخول مرة أخرى قبل أن يتمكن التطبيق من إجراء طلبات أخرى مُصرَّح بها نيابةً عنك، لكن لن تضطر إلى منح حق الوصول مرة أخرى في المرة التالية التي تستخدم فيها التطبيق. ومع ذلك، إذا أبطلت إمكانية الوصول، عليك منح حق الوصول مرة أخرى.

يمكنك أيضًا إلغاء حق الوصول إلى التطبيق من خلال صفحة الأذونات لحسابك على Google. يتم إدراج التطبيق باعتباره الإصدار التجريبي لبروتوكول OAuth 2.0 لمحرِّر مستندات Google API.

<script>
  var GoogleAuth;
  var SCOPE = 'https://www.googleapis.com/auth/drive.metadata.readonly';
  function handleClientLoad() {
    // Load the API's client and auth2 modules.
    // Call the initClient function after the modules load.
    gapi.load('client:auth2', initClient);
  }

  function initClient() {
    // In practice, your app can retrieve one or more discovery documents.
    var discoveryUrl = 'https://www.googleapis.com/discovery/v1/apis/drive/v3/rest';

    // Initialize the gapi.client object, which app uses to make API requests.
    // Get API key and client ID from API Console.
    // 'scope' field specifies space-delimited list of access scopes.
    gapi.client.init({
        'apiKey': 'YOUR_API_KEY',
        'clientId': 'YOUR_CLIENT_ID',
        'discoveryDocs': [discoveryUrl],
        'scope': SCOPE
    }).then(function () {
      GoogleAuth = gapi.auth2.getAuthInstance();

      // Listen for sign-in state changes.
      GoogleAuth.isSignedIn.listen(updateSigninStatus);

      // Handle initial sign-in state. (Determine if user is already signed in.)
      var user = GoogleAuth.currentUser.get();
      setSigninStatus();

      // Call handleAuthClick function when user clicks on
      //      "Sign In/Authorize" button.
      $('#sign-in-or-out-button').click(function() {
        handleAuthClick();
      });
      $('#revoke-access-button').click(function() {
        revokeAccess();
      });
    });
  }

  function handleAuthClick() {
    if (GoogleAuth.isSignedIn.get()) {
      // User is authorized and has clicked "Sign out" button.
      GoogleAuth.signOut();
    } else {
      // User is not signed in. Start Google auth flow.
      GoogleAuth.signIn();
    }
  }

  function revokeAccess() {
    GoogleAuth.disconnect();
  }

  function setSigninStatus() {
    var user = GoogleAuth.currentUser.get();
    var isAuthorized = user.hasGrantedScopes(SCOPE);
    if (isAuthorized) {
      $('#sign-in-or-out-button').html('Sign out');
      $('#revoke-access-button').css('display', 'inline-block');
      $('#auth-status').html('You are currently signed in and have granted ' +
          'access to this app.');
    } else {
      $('#sign-in-or-out-button').html('Sign In/Authorize');
      $('#revoke-access-button').css('display', 'none');
      $('#auth-status').html('You have not authorized this app or you are ' +
          'signed out.');
    }
  }

  function updateSigninStatus() {
    setSigninStatus();
  }
</script>

<button id="sign-in-or-out-button"
        style="margin-left: 25px">Sign In/Authorize</button>
<button id="revoke-access-button"
        style="display: none; margin-left: 25px">Revoke access</button>

<div id="auth-status" style="display: inline; padding-left: 25px"></div><hr>

<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
<script async defer src="https://apis.google.com/js/api.js"
        onload="this.onload=function(){};handleClientLoad()"
        onreadystatechange="if (this.readyState === 'complete') this.onload()">
</script>

نقاط نهاية OAuth 2.0

يوضح نموذج الرمز هذا كيفية إكمال تدفق OAuth 2.0 في JavaScript بدون استخدام "مكتبة عميل Google APIs" للغة JavaScript. هذا الرمز مخصّص لصفحة HTML تعرض زرًا لتجربة طلب بيانات من واجهة برمجة التطبيقات. عند النقر على الزر، يتم التحقق من الرمز لمعرفة ما إذا كانت الصفحة قد خزّنت رمز الدخول لواجهة برمجة التطبيقات في وحدة التخزين المحلية للمتصفح. في هذه الحالة، يتم تنفيذ طلب البيانات من واجهة برمجة التطبيقات. وإلا، سيتم بدء تدفق OAuth 2.0.

بالنسبة إلى تدفق OAuth 2.0، تتبع الصفحة الخطوات التالية:

  1. يتم توجيه المستخدم إلى خادم OAuth 2.0 في Google، والذي يطلب الوصول إلى نطاق https://www.googleapis.com/auth/drive.metadata.readonly.
  2. بعد منح (أو رفض) الوصول إلى نطاق واحد أو أكثر من النطاقات المطلوبة، تتم إعادة توجيه المستخدم إلى الصفحة الأصلية التي تحلّل رمز الدخول من سلسلة معرّف الجزء.
  3. تستخدم الصفحة رمز الدخول المميز لإجراء نموذج لطلب واجهة برمجة التطبيقات.

    يستدعي طلب واجهة برمجة التطبيقات طريقة about.get لواجهة برمجة تطبيقات Drive لاسترداد معلومات حول حساب Google Drive للمستخدم المصرح له.

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

يمكنك إبطال الوصول إلى التطبيق من خلال صفحة الأذونات لحسابك على Google. سيتم إدراج التطبيق كـ إصدار OAuth 2.0 التجريبي لمحرّر مستندات Google API.

لتشغيل هذا الرمز محليًا، يجب ضبط قيم للمتغيّرين YOUR_CLIENT_ID وYOUR_REDIRECT_URI بما يتوافق مع بيانات اعتماد التفويض. يجب ضبط المتغير YOUR_REDIRECT_URI على عنوان URL نفسه الذي يتم عرض الصفحة عليه. يجب أن تتطابق القيمة تطابقًا تامًا مع أحد معرّفات الموارد المنتظمة (URI) المُعتمَدة لإعادة التوجيه لعميل OAuth 2.0، الذي تم ضبطه في API Console Credentials page. وإذا لم تتطابق هذه القيمة مع معرّف الموارد المنتظم (URI) المُعتمَد، ستظهر لك رسالة خطأ redirect_uri_mismatch. ويجب أيضًا أن يكون مشروعك قد فعّل واجهة برمجة التطبيقات المناسبة لهذا الطلب.

<html><head></head><body>
<script>
  var YOUR_CLIENT_ID = 'REPLACE_THIS_VALUE';
  var YOUR_REDIRECT_URI = 'REPLACE_THIS_VALUE';
  var fragmentString = location.hash.substring(1);

  // Parse query string to see if page request is coming from OAuth 2.0 server.
  var params = {};
  var regex = /([^&=]+)=([^&]*)/g, m;
  while (m = regex.exec(fragmentString)) {
    params[decodeURIComponent(m[1])] = decodeURIComponent(m[2]);
  }
  if (Object.keys(params).length > 0) {
    localStorage.setItem('oauth2-test-params', JSON.stringify(params) );
    if (params['state'] && params['state'] == 'try_sample_request') {
      trySampleRequest();
    }
  }

  // If there's an access token, try an API request.
  // Otherwise, start OAuth 2.0 flow.
  function trySampleRequest() {
    var params = JSON.parse(localStorage.getItem('oauth2-test-params'));
    if (params && params['access_token']) {
      var xhr = new XMLHttpRequest();
      xhr.open('GET',
          'https://www.googleapis.com/drive/v3/about?fields=user&' +
          'access_token=' + params['access_token']);
      xhr.onreadystatechange = function (e) {
        if (xhr.readyState === 4 && xhr.status === 200) {
          console.log(xhr.response);
        } else if (xhr.readyState === 4 && xhr.status === 401) {
          // Token invalid, so prompt for user permission.
          oauth2SignIn();
        }
      };
      xhr.send(null);
    } else {
      oauth2SignIn();
    }
  }

  /*
   * Create form to request access token from Google's OAuth 2.0 server.
   */
  function oauth2SignIn() {
    // Google's OAuth 2.0 endpoint for requesting an access token
    var oauth2Endpoint = 'https://accounts.google.com/o/oauth2/v2/auth';

    // Create element to open OAuth 2.0 endpoint in new window.
    var form = document.createElement('form');
    form.setAttribute('method', 'GET'); // Send as a GET request.
    form.setAttribute('action', oauth2Endpoint);

    // Parameters to pass to OAuth 2.0 endpoint.
    var params = {'client_id': YOUR_CLIENT_ID,
                  'redirect_uri': YOUR_REDIRECT_URI,
                  'scope': 'https://www.googleapis.com/auth/drive.metadata.readonly',
                  'state': 'try_sample_request',
                  'include_granted_scopes': 'true',
                  'response_type': 'token'};

    // Add form parameters as hidden input values.
    for (var p in params) {
      var input = document.createElement('input');
      input.setAttribute('type', 'hidden');
      input.setAttribute('name', p);
      input.setAttribute('value', params[p]);
      form.appendChild(input);
    }

    // Add form to page and submit it to open the OAuth 2.0 endpoint.
    document.body.appendChild(form);
    form.submit();
  }
</script>

<button onclick="trySampleRequest();">Try sample request</button>
</body></html>

قواعد التحقق من مصدر JavaScript

تطبِّق Google قواعد التحقّق التالية على مصادر JavaScript، وذلك لمساعدة مطوّري البرامج في الحفاظ على أمان تطبيقاتهم. يجب أن تلتزم أصول JavaScript بهذه القواعد. راجِع القسم RFC 3986 للحصول على تعريف للنطاق والمضيف والمخطّط المذكور أدناه.

قواعد التحقق
المخطط

ويجب أن تستخدم أصول JavaScript نظام HTTPS، وليس HTTP عادي. معرّفات الموارد المنتظمة (URI) للمضيف المحلي (بما في ذلك معرّفات الموارد المنتظمة (URI) لعنوان المضيف المحلي) يتم استثناؤها من هذه القاعدة.

المضيف

لا يمكن للمضيفين أن يكونوا عناوين IP أولية. يتم إعفاء عناوين IP للمضيف المحلي من هذه القاعدة.

النطاق
  • يجب أن تكون نطاقات المستوى الأعلى المضيفة (نطاقات المستوى الأعلى) من قائمة اللاحقات العلنية.
  • لا يمكن أن تكون نطاقات المضيف “googleusercontent.com”.
  • لا يمكن أن تحتوي مصادر JavaScript على نطاقات عناوين URL مختصرة (مثل goo.gl) ما لم يكن التطبيق يمتلك النطاق.
  • معلومات المستخدم

    لا يمكن أن تحتوي أصول JavaScript على المكوّن الفرعي userinfo.

    المسار

    لا يمكن أن تحتوي مصادر JavaScript على مكوّن المسار.

    طلب بحث

    لا يمكن أن تحتوي مصادر JavaScript على مكوّن طلب البحث.

    جزء

    لا يمكن أن تحتوي أصول JavaScript على المكوِّن المجزأ.

    الأحرف لا يمكن أن تحتوي مصادر JavaScript على أحرف معيّنة، بما في ذلك:
    • أحرف البدل ('*')
    • أحرف ASCII غير قابلة للطباعة
    • ترميزات النسبة المئوية غير صالحة (أي ترميز بنسبة مئوية لا يتبع نموذج ترميز عنوان URL لعلامة نسبة مئوية متبوعًا برقمين سداسيين عشريين)
    • أحرف فارغة (حرف NULL مشفر، على سبيل المثال، %00، %C0%80)

    التفويض المتزايد

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

    على سبيل المثال، قد يحتاج التطبيق الذي يتيح للمستخدمين استخدام عيّنات من المقاطع الموسيقية وإنشاء مجموعات ممتزجة إلى عدد قليل جدًا من الموارد في وقت تسجيل الدخول، وقد لا يكون هناك أكثر من اسم الشخص الذي يسجّل الدخول. ومع ذلك، سيتطلب حفظ مزيج أغانٍ مكتمل الوصول إلى Google Drive. سيجد معظم المستخدمين أنّه من الطبيعي أن يُطلب منهم الوصول إلى "Google Drive" عندما يحتاجون إلى التطبيق.

    في هذه الحالة، قد يطلب التطبيق عند تسجيل الدخول النطاقين openid وprofile لتنفيذ تسجيل الدخول الأساسي، ثم يطلب لاحقًا النطاق https://www.googleapis.com/auth/drive.file في وقت الطلب الأول لحفظ مزيج.

    تنطبق القواعد التالية على رمز الدخول الذي تم الحصول عليه من تفويض متزايد:

    • ويمكن استخدام الرمز المميّز للوصول إلى الموارد المقابلة لأي من النطاقات المضمّنة في التفويض الجديد والمجمّع.
    • عند استخدام الرمز المميز لإعادة التحميل للتفويض المجمّع للحصول على رمز الدخول، يمثل رمز الدخول التفويض المُجمَّع ويمكن استخدامه لأي من قيم scope المضمّنة في الاستجابة.
    • يتضمّن التفويض المُجمَّع جميع النطاقات التي منحها المستخدم إلى مشروع واجهة برمجة التطبيقات حتى في حال طلب المنح من برامج مختلفة. على سبيل المثال، إذا منَح مستخدم إمكانية الوصول إلى نطاق باستخدام برنامج سطح المكتب لأحد التطبيقات ثم منح نطاقًا آخر للتطبيق نفسه من خلال برنامج متوافق مع الأجهزة الجوّالة، سيتضمن التفويض المُجمَّع كلا النطاقين.
    • إذا أبطلت رمزًا مميّزًا يمثّل تفويضًا مجمّعًا، سيتم إبطال إمكانية الوصول إلى جميع نطاقات هذا التفويض بالنيابة عن المستخدم المرتبط في الوقت نفسه.

    توضح نماذج الرموز أدناه كيفية إضافة نطاقات إلى رمز دخول حالي. تسمح هذه الطريقة لتطبيقك بتجنّب إدارة عدة رموز دخول.

    مكتبة عميل JavaScript

    لإضافة نطاقات إلى رمز دخول حالي، يمكنك استدعاء طريقة GoogleUser.grant(options). يحدد الكائن options النطاقات الإضافية التي تريد منح حق الوصول إليها.

    // Space-separated list of additional scope(s) you are requesting access to.
    // This code adds read-only access to the user's calendars via the Calendar API.
    var NEW_SCOPES = 'https://www.googleapis.com/auth/calendar.readonly';
    
    // Retrieve the GoogleUser object for the current user.
    var GoogleUser = GoogleAuth.currentUser.get();
    GoogleUser.grant({'scope': NEW_SCOPES});

    نقاط نهاية OAuth 2.0

    لإضافة نطاقات إلى رمز دخول حالي، يمكنك تضمين المعلمة include_granted_scopes في طلبك إلى خادم OAuth 2.0 في Google.

    يوضح مقتطف الشفرة التالي كيفية إجراء ذلك. يفترض المقتطف أنك خزّنت النطاقات التي يكون رمز الدخول المميز صالحًا لها في وحدة التخزين المحلية للمتصفح. (يخزّن الرمز المثال الكامل قائمة بالنطاقات التي يكون رمز الدخول المميز صالحًا لها من خلال ضبط السمة oauth2-test-params.scope في مساحة التخزين المحلية للمتصفّح).

    يقارن المقتطف النطاقات التي يكون رمز الدخول المميز صالحًا للنطاق الذي تريد استخدامه لطلب بحث معين. إذا لم يغطِ رمز الدخول المميز ذلك النطاق، فسيبدأ تدفق OAuth 2.0. في هذه الحالة، تتطابق الدالة oauth2SignIn مع الوظيفة التي تم توفيرها في الخطوة 2 (وهي متوفرة لاحقًا في المثال الكامل).

    var SCOPE = 'https://www.googleapis.com/auth/drive.metadata.readonly';
    var params = JSON.parse(localStorage.getItem('oauth2-test-params'));
    
    var current_scope_granted = false;
    if (params.hasOwnProperty('scope')) {
      var scopes = params['scope'].split(' ');
      for (var s = 0; s < scopes.length; s++) {
        if (SCOPE == scopes[s]) {
          current_scope_granted = true;
        }
      }
    }
    
    if (!current_scope_granted) {
      oauth2SignIn(); // This function is defined elsewhere in this document.
    } else {
      // Since you already have access, you can proceed with the API request.
    }

    إبطال الرمز المميز

    في بعض الحالات، قد يرغب المستخدم في إبطال حق الوصول الممنوح لتطبيق. يمكن للمستخدم إبطال الوصول عن طريق الانتقال إلى إعدادات الحساب. للحصول على مزيد من المعلومات، يُرجى الاطّلاع على قسم دعم المواقع الإلكترونية والتطبيقات التابعة لجهات خارجية التي يمكنها الوصول إلى حسابك لإزالة قسم "الموقع الإلكتروني أو التطبيق".

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

    مكتبة عميل JavaScript

    لإبطال الرمز المميز آليًا، يمكنك استدعاء GoogleAuth.disconnect():

    GoogleAuth.disconnect();

    نقاط نهاية OAuth 2.0

    لإبطال الرمز المميز آليًا، يقدم تطبيقك طلبًا لتنفيذ ما يلي: https://oauth2.googleapis.com/revoke مع تضمين الرمز المميز كمعلمة:

    curl -d -X -POST --header "Content-type:application/x-www-form-urlencoded" \
            https://oauth2.googleapis.com/revoke?token={token}

    قد يكون الرمز المميز عبارة عن رمز دخول أو رمز تحديث. إذا كان الرمز المميز عبارة عن رمز دخول وكان يتضمّن رمزًا مميزًا للتحديث، سيتم إبطال الرمز المميز لإعادة التحميل.

    إذا تمت معالجة الإبطال بنجاح، سيكون رمز حالة HTTP للاستجابة هو 200. بالنسبة إلى حالات الخطأ، يتم عرض رمز حالة HTTP 400 مع رمز خطأ.

    يعرض مقتطف JavaScript التالي طريقة إبطال رمز مميّز في JavaScript بدون استخدام "مكتبة عميل Google APIs" للغة JavaScript. بما أنّ نقطة نهاية OAuth 2.0 من Google لإبطال الرموز المميّزة غير متاحة في ميزة مشاركة الموارد المشتركة المنشأ (CORS)، تنشئ الشفرة نموذجًا وترسل النموذج إلى نقطة النهاية بدلاً من استخدام طريقة XMLHttpRequest() لنشر الطلب.

    function revokeAccess(accessToken) {
      // Google's OAuth 2.0 endpoint for revoking access tokens.
      var revokeTokenEndpoint = 'https://oauth2.googleapis.com/revoke';
    
      // Create <form> element to use to POST data to the OAuth 2.0 endpoint.
      var form = document.createElement('form');
      form.setAttribute('method', 'post');
      form.setAttribute('action', revokeTokenEndpoint);
    
      // Add access token to the form so it is set as value of 'token' parameter.
      // This corresponds to the sample curl request, where the URL is:
      //      https://oauth2.googleapis.com/revoke?token={token}
      var tokenField = document.createElement('input');
      tokenField.setAttribute('type', 'hidden');
      tokenField.setAttribute('name', 'token');
      tokenField.setAttribute('value', accessToken);
      form.appendChild(tokenField);
    
      // Add form to page and submit it to actually revoke the token.
      document.body.appendChild(form);
      form.submit();
    }