استخدام OAuth 2.0 لخادم في تطبيقات الخادم

يتوافق نظام OAuth 2.0 من Google مع التفاعلات من خادم إلى خادم، مثل التفاعلات بين تطبيق ويب وخدمة Google. لتنفيذ هذا السيناريو، يجب استخدام حساب خدمة، وهو حساب ينتمي إلى تطبيقك بدلاً من حساب مستخدم فردي. يستدعي تطبيقك واجهات Google APIs نيابةً عن حساب الخدمة، لذا لا يشارك المستخدمون بشكل مباشر في ذلك. ويُطلق على هذا السيناريو أحيانًا اسم "بروتوكول OAuth الثنائي" أو "2LO". (يشير المصطلح ذو الصلة "بروتوكول OAuth الثلاثي" إلى السيناريوهات التي يستدعي فيها تطبيقك واجهات Google APIs نيابةً عن المستخدمين، والتي تتطلّب أحيانًا موافقة المستخدم.)

عادةً ما يستخدم التطبيق حساب خدمة عندما يستخدم التطبيق واجهات Google APIs للعمل باستخدام بياناته الخاصة بدلاً من بيانات المستخدم. على سبيل المثال، قد يستخدم تطبيق يستخدم Google Cloud Datastore للاحتفاظ بالبيانات حساب خدمة لمصادقة طلبات البيانات من Google Cloud Datastore API.

ويمكن لمشرفي نطاقات Google Workspace أيضًا منح حسابات الخدمة تفويضًا على مستوى النطاق للوصول إلى بيانات المستخدمين نيابةً عن المستخدمين في النطاق.

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

نظرة عامة

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

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

وأخيرًا، يمكن لتطبيقك استخدام رمز الدخول لاستدعاء واجهات Google APIs.

إنشاء حساب خدمة

تشتمل بيانات اعتماد حساب الخدمة على عنوان بريد إلكتروني فريد تم إنشاؤه ويتضمّن على الأقل زوجًا من المفاتيح العامة/الخاصة. في حال تفعيل التفويض على مستوى النطاق، سيكون معرِّف العميل أيضًا جزءًا من بيانات اعتماد حساب الخدمة.

إذا تم تشغيل تطبيقك على Google App Engine، يتم إعداد حساب خدمة تلقائيًا عند إنشاء مشروعك.

إذا كان تطبيقك يعمل على Google Compute Engine، يتم أيضًا إعداد حساب خدمة تلقائيًا عند إنشاء مشروعك، ولكن عليك تحديد النطاقات التي يحتاج تطبيقك إلى الوصول إليها عند إنشاء مثيل Google Compute Engine. لمزيد من المعلومات، راجِع تحضير مثيل لاستخدام حسابات الخدمة.

إذا لم يتم تشغيل طلبك على Google App Engine أو Google Compute Engine، يجب الحصول على بيانات الاعتماد هذه في Google API Console. لإنشاء بيانات اعتماد حساب الخدمة، أو لعرض بيانات الاعتماد العلنية التي سبق أن أنشأتها، عليك اتّباع الخطوات التالية:

أولاً ، قم بإنشاء حساب خدمة:

  1. افتح Service accounts page.
  2. If prompted, select a project, or create a new one.
  3. انقر فوق إنشاء حساب الخدمة .
  4. ضمن تفاصيل حساب الخدمة ، اكتب اسمًا ومعرفًا ووصفًا لحساب الخدمة ، ثم انقر فوق إنشاء ومتابعة .
  5. اختياري: ضمن منح حق الوصول إلى حساب الخدمة هذا للمشروع ، حدد أدوار IAM لمنح حساب الخدمة.
  6. انقر فوق متابعة .
  7. اختياري: ضمن منح المستخدمين حق الوصول إلى حساب الخدمة هذا ، أضف المستخدمين أو المجموعات المسموح لها باستخدام حساب الخدمة وإدارته.
  8. انقر فوق تم .

بعد ذلك ، قم بإنشاء مفتاح حساب الخدمة:

  1. انقر فوق عنوان البريد الإلكتروني لحساب الخدمة الذي أنشأته.
  2. انقر فوق علامة التبويب المفاتيح .
  3. في القائمة المنسدلة إضافة مفتاح ، حدد إنشاء مفتاح جديد .
  4. انقر فوق إنشاء .

يتم إنشاء زوج المفاتيح العام / الخاص الجديد وتنزيله على جهازك ؛ إنه بمثابة النسخة الوحيدة من المفتاح الخاص. أنت مسؤول عن تخزينه بشكل آمن. إذا فقدت زوج المفاتيح هذا ، فستحتاج إلى إنشاء زوج جديد.

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

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

تفويض تفويض على مستوى النطاق لحساب الخدمة

باستخدام حساب Google Workspace، يمكن لمشرف Workspace في المؤسسة تفويض تطبيق للوصول إلى بيانات مستخدمي Workspace نيابةً عن المستخدمين في نطاق Google Workspace. على سبيل المثال، قد يستخدم تطبيق يستخدم Google Calendar API لإضافة أحداث إلى تقاويم جميع المستخدمين في نطاق Google Workspace حساب خدمة للوصول إلى Google Calendar API بالنيابة عن المستخدمين. يُشار أحيانًا إلى تفويض حساب خدمة بالوصول إلى البيانات نيابةً عن المستخدمين في نطاق باسم "تفويض التفويض على مستوى النطاق" لحساب خدمة.

لتفويض صلاحية على مستوى النطاق لحساب خدمة، على المشرف المتميّز لنطاق Google Workspace إكمال الخطوات التالية:

  1. من وحدة تحكُّم المشرف في نطاقك على Google Workspace، انتقِل إلى القائمة الرئيسية > الأمان > التحكُّم بالوصول والبيانات > عناصر تحكُّم واجهة برمجة التطبيقات.
  2. في لوحة التفويض على مستوى النطاق، اختَر إدارة التفويض على مستوى النطاق.
  3. انقر على إضافة جديد.
  4. في حقل معرّف العميل، أدخِل معرّف العميل لحساب الخدمة. يمكنك العثور على معرِّف العميل لحساب الخدمة في Service accounts page.
  5. في الحقل نطاقات OAuth (المفصولة بفواصل)، أدخِل قائمة النطاقات التي يجب منح تطبيقك إذن الوصول إليها. على سبيل المثال، إذا كان تطبيقك يحتاج إلى الوصول الكامل على مستوى النطاق إلى واجهة برمجة تطبيقات Google Drive وواجهة برمجة تطبيقات "تقويم Google"، أدخِل: https://www.googleapis.com/auth/drive, https://www.googleapis.com/auth/calendar.
  6. انقر على تفويض.

يمكن لتطبيقك الآن إجراء طلبات بيانات من واجهة برمجة التطبيقات كمستخدمين في نطاق Workspace (من أجل "انتحال هوية" المستخدمين). وعندما تستعد لإجراء طلبات البيانات المفوَّضة من واجهة برمجة التطبيقات هذه، عليك تحديد المستخدم بشكل صريح لانتحال هويته.

جارٍ التحضير لإجراء طلب بيانات مفوَّض من واجهة برمجة التطبيقات.

Java

بعد الحصول على عنوان البريد الإلكتروني للعميل والمفتاح الخاص من API Console، استخدِم مكتبة برامج Google APIs للغة Java لإنشاء عنصر GoogleCredential من بيانات اعتماد حساب الخدمة والنطاقات التي يحتاج تطبيقك إلى الوصول إليها. مثال:

import com.google.api.client.googleapis.auth.oauth2.GoogleCredential;
import com.google.api.services.sqladmin.SQLAdminScopes;

// ...

GoogleCredential credential = GoogleCredential.fromStream(new FileInputStream("MyProject-1234.json"))
    .createScoped(Collections.singleton(SQLAdminScopes.SQLSERVICE_ADMIN));

إذا كنت تطوّر تطبيقًا على Google Cloud Platform، يمكنك استخدام بيانات الاعتماد التلقائية للتطبيق بدلاً من ذلك، ما يؤدي إلى تبسيط العملية.

تفويض التفويض على مستوى النطاق

إذا كنت قد فوَّضت الوصول على مستوى النطاق إلى حساب الخدمة وأردت انتحال هوية حساب مستخدم، حدِّد عنوان البريد الإلكتروني لحساب المستخدم باستخدام طريقة createDelegated في العنصر GoogleCredential. على سبيل المثال:

GoogleCredential credential = GoogleCredential.fromStream(new FileInputStream("MyProject-1234.json"))
    .createScoped(Collections.singleton(SQLAdminScopes.SQLSERVICE_ADMIN))
    .createDelegated("workspace-user@example.com");

يستخدم الرمز أعلاه الكائن GoogleCredential لاستدعاء طريقة createDelegated() الخاصة به. يجب أن تكون وسيطة الطريقة createDelegated() مستخدمًا ينتمي إلى حسابك على Workspace. سيستخدم رمز الطلب المستخدَم بيانات الاعتماد هذه لطلب بيانات من Google APIs باستخدام حساب الخدمة.

Python

بعد الحصول على عنوان البريد الإلكتروني للعميل والمفتاح الخاص من API Console، يمكنك استخدام مكتبة برامج Google APIs للغة Python لإكمال الخطوات التالية:

  1. يمكنك إنشاء عنصر Credentials من بيانات اعتماد حساب الخدمة والنطاقات التي يحتاج تطبيقك إلى الوصول إليها. مثلاً:
    from google.oauth2 import service_account
    
    SCOPES = ['https://www.googleapis.com/auth/sqlservice.admin']
    SERVICE_ACCOUNT_FILE = '/path/to/service.json'
    
    credentials = service_account.Credentials.from_service_account_file(
            SERVICE_ACCOUNT_FILE, scopes=SCOPES)

    إذا كنت تطوّر تطبيقًا على Google Cloud Platform، يمكنك استخدام بيانات الاعتماد التلقائية للتطبيق بدلاً من ذلك، ما يؤدي إلى تبسيط العملية.

  2. تفويض التفويض على مستوى النطاق

    إذا كنت قد فوَّضت الوصول على مستوى النطاق إلى حساب الخدمة وأردت انتحال هوية حساب مستخدم، استخدِم طريقة with_subject في عنصر ServiceAccountCredentials حالي. مثال:

    delegated_credentials = credentials.with_subject('user@example.org')

استخدم كائن "بيانات الاعتماد" لاستدعاء Google APIs في تطبيقك.

HTTP/REST

بعد الحصول على معرِّف العميل والمفتاح الخاص من API Console، على تطبيقك إكمال الخطوات التالية:

  1. أنشِئ رمز JSON المميّز للويب (JWT، يُنطق "jot") والذي يتضمّن عنوانًا ومجموعة مطالبات وتوقيعًا.
  2. اطلب رمز الدخول من خادم تفويض OAuth 2.0 من Google.
  3. يمكنك معالجة استجابة JSON التي يعرضها خادم التفويض.

توضح الأقسام التالية كيفية إكمال هذه الخطوات.

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

عند انتهاء صلاحية رمز الدخول، ينشئ تطبيقك رمز JWT آخر ويوقّعه ويطلب رمز دخول آخر.

يستخدم تطبيق الخادم JWT لطلب رمز مميّز من خادم تفويض Google، ثم يستخدم الرمز المميّز لطلب نقطة نهاية Google API. ولا يتضمّن أي مستخدم نهائي.

يصف الجزء المتبقي من هذا القسم تفاصيل إنشاء JWT، وتوقيع JWT، وتشكيل طلب رمز الدخول، والتعامل مع الردّ.

إنشاء JWT

يتكوّن JWT من ثلاثة أجزاء: عنوان ومجموعة مطالبات وتوقيع. العنوان ومجموعة المطالبات هما كائنات JSON. يتم ربط عناصر JSON هذه بشكل تسلسلي بوحدات بايت من النوع UTF-8، ثم يتم ترميزها باستخدام ترميز Base64url. ويوفر هذا الترميز مرونة في التعامل مع تغييرات الترميز بسبب عمليات الترميز المتكرّرة. يتم ربط العنوان ومجموعة المطالبات والتوقيع مع حرف النقطة (.).

يتكون JWT على النحو التالي:

{Base64url encoded header}.{Base64url encoded claim set}.{Base64url encoded signature}

السلسلة الأساسية للتوقيع هي كما يلي:

{Base64url encoded header}.{Base64url encoded claim set}
إنشاء عنوان JWT

يتكوّن العنوان من ثلاثة حقول تشير إلى خوارزمية التوقيع وصيغة التأكيد و[معرّف المفتاح لمفتاح حساب الخدمة](https://cloud.google.com/iam/docs/reference/rest/v1/projects.serviceAccounts.keys) الذي تم استخدامه لتوقيع JWT. الخوارزمية والتنسيق إلزاميان، وكل حقل له قيمة واحدة فقط. ومع طرح خوارزميات وتنسيقات إضافية، سيتغيّر هذا العنوان وفقًا لذلك. يكون رقم تعريف المفتاح اختياريًا، وإذا تم تحديد رقم تعريف مفتاح غير صحيح، ستجرّب خدمة GCP جميع المفاتيح المرتبطة بحساب الخدمة للتحقّق من الرمز المميّز ورفض الرمز المميّز في حال عدم العثور على مفتاح صالح. وتحتفظ Google بالحق في رفض الرموز المميّزة التي تتضمّن أرقام تعريف مفاتيح غير صحيحة في المستقبل.

تعتمد حسابات الخدمة على خوارزمية RSA SHA-256 وتنسيق الرمز المميز JWT. ونتيجةً لذلك، يكون تمثيل JSON للعنوان على النحو التالي:

{"alg":"RS256","typ":"JWT", "kid":"370ab79b4513eb9bad7c9bd16a95cb76b5b2a56a"}

في ما يلي تمثيل Base64url لذلك:

          eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsICJraWQiOiIzNzBhYjc5YjQ1MTNlYjliYWQ3YzliZDE2YTk1Y2I3NmI1YjJhNTZhIn0=
إنشاء مجموعة مطالبة JWT

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

المطالبات المطلوبة

تظهر أدناه المطالبات المطلوبة في مجموعة مطالبات JWT. وقد تظهر بأي ترتيب في مجموعة المطالبات.

الاسم الوصف
iss عنوان البريد الإلكتروني لحساب الخدمة.
scope قائمة بالأذونات التي يطلبها التطبيق مع الفصل بينها بمسافات.
aud تمثّل هذه السمة واصفًا للهدف المرجوّ من التأكيد. عند تقديم طلب رمز الدخول، تكون هذه القيمة دائمًا https://oauth2.googleapis.com/token.
exp تمثّل هذه السمة وقت انتهاء صلاحية التأكيد، الذي تم تحديده بالثواني منذ الساعة 00:00:00 بالتوقيت العالمي المنسّق، في 1 كانون الثاني (يناير) 1970. وتستغرق هذه القيمة ساعة واحدة كحد أقصى بعد تاريخ الإصدار.
iat وقت إصدار التأكيد، والذي تم تحديده بالثواني منذ الساعة 00:00:00 بالتوقيت العالمي المنسق (UTC)، في 1 كانون الثاني (يناير) 1970.

يظهر أدناه تمثيل JSON للحقول المطلوبة في مجموعة مطالبات JWT:

{
  "iss": "761326798069-r5mljlln1rd4lrbhg75efgigp36m78j5@developer.gserviceaccount.com",
  "scope": "https://www.googleapis.com/auth/devstorage.read_only",
  "aud": "https://oauth2.googleapis.com/token",
  "exp": 1328554385,
  "iat": 1328550785
}
مطالبات إضافية

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

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

الاسم الوصف
sub تمثّل هذه السمة عنوان البريد الإلكتروني للمستخدم الذي يطلب التطبيق الوصول المفوَّض إليه.

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

في ما يلي مثال على مجموعة مطالبات JWT التي تتضمّن الحقل sub:

{
  "iss": "761326798069-r5mljlln1rd4lrbhg75efgigp36m78j5@developer.gserviceaccount.com",
  "sub": "some.user@example.com",
  "scope": "https://www.googleapis.com/auth/prediction",
  "aud": "https://oauth2.googleapis.com/token",
  "exp": 1328554385,
  "iat": 1328550785
}
ترميز مجموعة مطالبات JWT

وكما هو الحال في عنوان JWT، يجب أن تكون مجموعة مطالبات JWT مرتبطة بشكل تسلسلي بالترميز UTF-8 وBase64url-safe. في ما يلي مثال على تمثيل JSON لمجموعة مطالبات JWT:

{
  "iss": "761326798069-r5mljlln1rd4lrbhg75efgigp36m78j5@developer.gserviceaccount.com",
  "scope": "https://www.googleapis.com/auth/prediction",
  "aud": "https://oauth2.googleapis.com/token",
  "exp": 1328554385,
  "iat": 1328550785
}
جارٍ حساب التوقيع

JSON Web Signature (JWS) هو المواصفات التي توجِّه آليات إنشاء التوقيع لـ JWT. مدخل التوقيع هو صفيف البايت للمحتوى التالي:

{Base64url encoded header}.{Base64url encoded claim set}

يجب استخدام خوارزمية التوقيع في عنوان JWT عند احتساب التوقيع. خوارزمية التوقيع الوحيدة المتوافقة مع خادم تفويض OAuth 2.0 من Google هي خوارزمية RSA التي تستخدم خوارزمية التجزئة SHA-256. ويتم التعبير عنه على النحو التالي: RS256 في الحقل alg في عنوان JWT.

وقِّع تمثيل UTF-8 للإدخال باستخدام SHA256withRSA (المعروفة أيضًا باسم RSASSA-PKCS1-V1_5-SIGN مع دالة التجزئة SHA-256) باستخدام المفتاح الخاص الذي تم الحصول عليه من Google API Console. ستكون المخرجات صفيفة بايت.

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

{Base64url encoded header}.
{Base64url encoded claim set}.
{Base64url encoded signature}

في ما يلي مثال على JWT قبل ترميز Base64url:

{"alg":"RS256","typ":"JWT"}.
{
"iss":"761326798069-r5mljlln1rd4lrbhg75efgigp36m78j5@developer.gserviceaccount.com",
"scope":"https://www.googleapis.com/auth/prediction",
"aud":"https://oauth2.googleapis.com/token",
"exp":1328554385,
"iat":1328550785
}.
[signature bytes]

في ما يلي مثال على نموذج JWT تم توقيعه وهو جاهز للإرسال:

eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiI3NjEzMjY3OTgwNjktcjVtbGpsbG4xcmQ0bHJiaGc3NWVmZ2lncDM2bTc4ajVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJzY29wZSI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL2F1dGgvcHJlZGljdGlvbiIsImF1ZCI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL29hdXRoMi92NC90b2tlbiIsImV4cCI6MTMyODU1NDM4NSwiaWF0IjoxMzI4NTUwNzg1fQ.UFUt59SUM2_AW4cRU8Y0BYVQsNTo4n7AFsNrqOpYiICDu37vVt-tw38UKzjmUKtcRsLLjrR3gFW3dNDMx_pL9DVjgVHDdYirtrCekUHOYoa1CMR66nxep5q5cBQ4y4u2kIgSvChCTc9pmLLNoIem-ruCecAJYgI9Ks7pTnW1gkOKs0x3YpiLpzplVHAkkHztaXiJdtpBcY1OXyo6jTQCa3Lk2Q3va1dPkh_d--GU2M5flgd8xNBPYw4vxyt0mP59XZlHMpztZt0soSgObf7G3GXArreF_6tpbFsS3z2t5zkEiHuWJXpzcYr5zWTRPDEHsejeBSG8EgpLDce2380ROQ

تقديم طلب رمز الدخول

بعد إنشاء رمز JWT الموقَّع، يمكن للتطبيق استخدامه لطلب رمز دخول. طلب رمز الدخول هذا هو طلب HTTPS POST، والنص الأساسي بترميز URL. في ما يلي عنوان URL:

https://oauth2.googleapis.com/token

المَعلمات التالية مطلوبة في طلب HTTPS POST:

الاسم الوصف
grant_type استخدِم السلسلة التالية، مع ترميز عنوان URL عند الضرورة: urn:ietf:params:oauth:grant-type:jwt-bearer
assertion رمز JWT، بما في ذلك التوقيع

في ما يلي نسخة أولية من طلب HTTPS POST المستخدَم في طلب رمز دخول:

POST /token HTTP/1.1
Host: oauth2.googleapis.com
Content-Type: application/x-www-form-urlencoded

grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Ajwt-bearer&assertion=eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiI3NjEzMjY3OTgwNjktcjVtbGpsbG4xcmQ0bHJiaGc3NWVmZ2lncDM2bTc4ajVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJzY29wZSI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL2F1dGgvcHJlZGljdGlvbiIsImF1ZCI6Imh0dHBzOi8vYWNjb3VudHMuZ29vZ2xlLmNvbS9vL29hdXRoMi90b2tlbiIsImV4cCI6MTMyODU3MzM4MSwiaWF0IjoxMzI4NTY5NzgxfQ.ixOUGehweEVX_UKXv5BbbwVEdcz6AYS-6uQV6fGorGKrHf3LIJnyREw9evE-gs2bmMaQI5_UbabvI4k-mQE4kBqtmSpTzxYBL1TCd7Kv5nTZoUC1CmwmWCFqT9RE6D7XSgPUh_jF1qskLa2w0rxMSjwruNKbysgRNctZPln7cqQ

في ما يلي الطلب نفسه باستخدام "curl":

curl -d 'grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Ajwt-bearer&assertion=eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiI3NjEzMjY3OTgwNjktcjVtbGpsbG4xcmQ0bHJiaGc3NWVmZ2lncDM2bTc4ajVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJzY29wZSI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL2F1dGgvcHJlZGljdGlvbiIsImF1ZCI6Imh0dHBzOi8vYWNjb3VudHMuZ29vZ2xlLmNvbS9vL29hdXRoMi90b2tlbiIsImV4cCI6MTMyODU3MzM4MSwiaWF0IjoxMzI4NTY5NzgxfQ.RZVpzWygMLuL-n3GwjW1_yhQhrqDacyvaXkuf8HcJl8EtXYjGjMaW5oiM5cgAaIorrqgYlp4DPF_GuncFqg9uDZrx7pMmCZ_yHfxhSCXru3gbXrZvAIicNQZMFxrEEn4REVuq7DjkTMyCMGCY1dpMa8aWfTQFt3Eh7smLchaZsU
' https://oauth2.googleapis.com/token

التعامل مع الردّ

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

{
  "access_token": "1/8xbJqaOZXSUZbHLl5EOtu1pxz3fmmetKx9W8CV4t79M",
  "scope": "https://www.googleapis.com/auth/prediction"
  "token_type": "Bearer",
  "expires_in": 3600
}

يمكن إعادة استخدام رموز الدخول خلال فترة المدة التي تحدّدها قيمة expires_in.

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

Java

استخدِم الكائن GoogleCredential لطلب البيانات من Google APIs من خلال إكمال الخطوات التالية:

  1. أنشِئ عنصر خدمة لواجهة برمجة التطبيقات التي تريد طلبها باستخدام العنصر GoogleCredential. مثلاً:
    SQLAdmin sqladmin =
        new SQLAdmin.Builder(httpTransport, JSON_FACTORY, credential).build();
  2. يمكنك تقديم طلبات إلى خدمة واجهة برمجة التطبيقات باستخدام الواجهة التي يوفّرها كائن الخدمة. على سبيل المثال، لإدراج مثيلات قواعد بيانات Cloud SQL في مشروع The thrill-example-123 :
    SQLAdmin.Instances.List instances =
        sqladmin.instances().list("exciting-example-123").execute();

Python

استخدِم العنصر Credentials المعتمَد لاستدعاء واجهات Google APIs من خلال إكمال الخطوات التالية:

  1. أنشئ عنصر خدمة لواجهة برمجة التطبيقات التي تريد طلبها. يمكنك إنشاء كائن خدمة من خلال استدعاء الدالة build باسم واجهة برمجة التطبيقات وإصدارها وكائن Credentials المعتمَد. على سبيل المثال، لطلب الإصدار 1beta3 من Cloud SQL Administration API:
    import googleapiclient.discovery
    
    sqladmin = googleapiclient.discovery.build('sqladmin', 'v1beta3', credentials=credentials)
  2. يمكنك تقديم طلبات إلى خدمة واجهة برمجة التطبيقات باستخدام الواجهة التي يوفّرها كائن الخدمة. على سبيل المثال، لإدراج مثيلات قواعد بيانات Cloud SQL في مشروع The thrill-example-123 :
    response = sqladmin.instances().list(project='exciting-example-123').execute()

HTTP/REST

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

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

أمثلة على HTTP GET

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

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

عند انتهاء صلاحية رموز الدخول

تنتهي صلاحية رموز الدخول الصادرة عن خادم تفويض OAuth 2.0 من Google بعد انتهاء المدة التي تحدّدها القيمة expires_in. عند انتهاء صلاحية رمز الدخول، من المفترض أن ينشئ التطبيق رمز دخول JWT آخر ويوقِّعه ويطلب رمز دخول آخر.

رموز خطأ JWT

حقل واحد (error) حقل واحد (error_description) المعنى كيفية الحل
unauthorized_client Unauthorized client or scope in request. إذا كنت تحاول استخدام التفويض على مستوى النطاق، يكون حساب الخدمة غير مخوّل في "وحدة تحكّم المشرف" لنطاق المستخدم.

تأكَّد من أنّ حساب الخدمة مفوَّض في صفحة التفويض على مستوى النطاق في "وحدة تحكُّم المشرف" للمستخدم في طلب (حقل) sub.

يستغرق الأمر عادةً بضع دقائق، ولكن قد يستغرق نشر التفويض لجميع المستخدمين في حسابك على Google مدة تصل إلى 24 ساعة.

unauthorized_client Client is unauthorized to retrieve access tokens using this method, or client not authorized for any of the scopes requested. تم تفويض حساب الخدمة باستخدام عنوان البريد الإلكتروني للعميل بدلاً من معرّف العميل (الرقمي) في "وحدة تحكّم المشرف". في صفحة التفويض على مستوى النطاق في "وحدة تحكّم المشرف"، أزِل العميل وأعِد إضافته باستخدام المعرّف الرقمي.
access_denied (أي قيمة) إذا كنت تستخدم التفويض على مستوى النطاق، يعني ذلك أنّ نطاقًا واحدًا أو أكثر من النطاقات المطلوبة غير مفوَّض في "وحدة تحكّم المشرف".

تأكَّد من أنّ حساب الخدمة مفوَّض في صفحة التفويض على مستوى النطاق في "وحدة تحكُّم المشرف" للمستخدم في المطالبة (الحقل) sub، وأنّه يتضمّن جميع النطاقات التي تطلبها في طلب scope الخاص بـ JWT.

يستغرق الأمر عادةً بضع دقائق، ولكن قد يستغرق نشر التفويض لجميع المستخدمين في حسابك على Google مدة تصل إلى 24 ساعة.

admin_policy_enforced (أي قيمة) يتعذّر على حساب Google تفويض نطاق أو أكثر تم طلبه بسبب سياسات مشرف Google Workspace.

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

invalid_client (أي قيمة)

برنامج OAuth أو رمز JWT غير صالح أو تم إعداده بشكل غير صحيح.

راجِع وصف الخطأ للحصول على التفاصيل.

تأكَّد من أنّ رمز JWT صالح وأنّه يحتوي على مطالبات صحيحة.

تأكَّد من ضبط حساب الخدمة وبرنامج OAuth بشكلٍ صحيح ومن أنّك تستخدم عنوان البريد الإلكتروني الصحيح.

تحقَّق من أنّ رمز JWT صحيح وتم إصداره لمعرّف العميل في الطلب.

invalid_grant Not a valid email. المستخدم غير موجود. تحقّق من صحة عنوان البريد الإلكتروني في مطالبة sub (الحقل).
invalid_grant

Invalid JWT: Token must be a short-lived token (60 minutes) and in a reasonable timeframe. Check your 'iat' and 'exp' values and use a clock with skew to account for clock differences between systems.

يعني ذلك عادةً أنّ وقت النظام المحلي غير صحيح. قد يحدث ذلك أيضًا إذا كانت قيمة exp بعد أكثر من 65 دقيقة في المستقبل من قيمة iat، أو إذا كانت قيمة exp أقل من قيمة iat.

تأكَّد من صحة الساعة في النظام التي يتم فيها إنشاء رمز JWT. إذا لزم الأمر، يمكنك مزامنة وقتك مع Google NTP.

invalid_grant Invalid JWT Signature.

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

بدلاً من ذلك، قد يتم ترميز تأكيد JWT بشكل غير صحيح، ويجب أن يكون بترميز Base64، بدون سطور جديدة أو علامات تساوي المساحة المتروكة.

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

جرِّب استخدام مكتبة OAuth توفِّرها Google للتأكُّد من إنشاء JWT بشكل صحيح.

invalid_scope Invalid OAuth scope or ID token audience provided. لم يتم طلب أي نطاقات (قائمة فارغة بالنطاقات)، أو أنّ أحد النطاقات المطلوبة غير متوفّر (أي أنّه غير صالح).

احرص على تعبئة المطالبة scope (الحقل) الخاصة بـ JWT، وقارِن النطاقات التي تتضمّنها تلك المطالبة بالنطاقات الموثَّقة لواجهات برمجة التطبيقات التي تريد استخدامها، لضمان عدم حدوث أخطاء أو أخطاء إملائية.

يُرجى العلم أنّه يجب فصل قائمة النطاقات في المطالبة scope بمسافات، وليس بفواصل.

disabled_client The OAuth client was disabled. المفتاح المستخدم للتوقيع على تأكيد JWT غير مفعّل.

انتقِل إلى Google API Console، وضمن إدارة الهوية وإمكانية الوصول والمشرف > حسابات الخدمة، فعِّل حساب الخدمة الذي يحتوي على "رقم تعريف المفتاح" المُستخدَم لتوقيع التأكيد.

org_internal This client is restricted to users within its organization. يشكّل معرّف عميل OAuth في الطلب جزءًا من مشروع يحدّ من إمكانية الوصول إلى حسابات Google في مؤسسة Google Cloud معيّنة.

استخدِم حساب خدمة من المؤسسة للمصادقة. تأكَّد من إعدادات نوع المستخدم لتطبيق OAuth.

الملحق: تفويض حساب الخدمة بدون بروتوكول OAuth

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

إذا كانت واجهة برمجة التطبيقات التي تريد طلبها تتضمّن تعريف خدمة منشورًا في مستودع GitHub لواجهات Google APIs، يمكنك إجراء طلبات بيانات معتمَدة من واجهة برمجة التطبيقات باستخدام JWT بدلاً من رمز الدخول. ولإجراء ذلك، يُرجى اتّباع الخطوات التالية:

  1. أنشِئ حساب خدمة كما هو موضَّح أعلاه. وتأكّد من الاحتفاظ بملف JSON الذي تحصل عليه عند إنشاء الحساب.
  2. باستخدام أي مكتبة JWT عادية، مثل المكتبة المتوفّرة على jwt.io، يمكنك إنشاء JWT بعنوان وحمولة مثل المثال التالي:
    {
      "alg": "RS256",
      "typ": "JWT",
      "kid": "abcdef1234567890"
    }
    .
    {
      "iss": "123456-compute@developer.gserviceaccount.com",
      "sub": "123456-compute@developer.gserviceaccount.com",
      "aud": "https://firestore.googleapis.com/",
      "iat": 1511900000,
      "exp": 1511903600
    }
    • بالنسبة إلى الحقل kid في العنوان، حدِّد رقم تعريف المفتاح الخاص لحساب الخدمة. يمكنك العثور على هذه القيمة في الحقل private_key_id ضمن ملف JSON لحساب الخدمة.
    • في الحقلَين iss وsub، حدِّد عنوان البريد الإلكتروني لحساب الخدمة. يمكنك العثور على هذه القيمة في الحقل client_email ضمن ملف JSON لحساب الخدمة.
    • بالنسبة إلى الحقل aud، حدِّد نقطة نهاية واجهة برمجة التطبيقات. مثلاً: https://SERVICE.googleapis.com/.
    • بالنسبة إلى الحقل iat، حدِّد وقت Unix الحالي، وبالنسبة إلى الحقل exp، حدِّد الوقت بعد 3600 ثانية بالضبط، والذي ستنتهي فيه صلاحية JWT.

وقِّع على JWT باستخدام RSA-256 باستخدام المفتاح الخاص المتوفّر في ملف JSON لحساب الخدمة.

مثال:

Java

باستخدام google-api-java-client وjava-jwt:

GoogleCredential credential =
        GoogleCredential.fromStream(new FileInputStream("MyProject-1234.json"));
PrivateKey privateKey = credential.getServiceAccountPrivateKey();
String privateKeyId = credential.getServiceAccountPrivateKeyId();

long now = System.currentTimeMillis();

try {
    Algorithm algorithm = Algorithm.RSA256(null, privateKey);
    String signedJwt = JWT.create()
        .withKeyId(privateKeyId)
        .withIssuer("123456-compute@developer.gserviceaccount.com")
        .withSubject("123456-compute@developer.gserviceaccount.com")
        .withAudience("https://firestore.googleapis.com/")
        .withIssuedAt(new Date(now))
        .withExpiresAt(new Date(now + 3600 * 1000L))
        .sign(algorithm);
} catch ...

Python

باستخدام PyJWT:

iat = time.time()
exp = iat + 3600
payload = {'iss': '123456-compute@developer.gserviceaccount.com',
           'sub': '123456-compute@developer.gserviceaccount.com',
           'aud': 'https://firestore.googleapis.com/',
           'iat': iat,
           'exp': exp}
additional_headers = {'kid': PRIVATE_KEY_ID_FROM_JSON}
signed_jwt = jwt.encode(payload, PRIVATE_KEY_FROM_JSON, headers=additional_headers,
                       algorithm='RS256')
  1. استدعِ واجهة برمجة التطبيقات، باستخدام رمز JWT الموقَّع على أنه الرمز المميز للحامل:
    GET /v1/projects/abc/databases/123/indexes HTTP/1.1
    Authorization: Bearer SIGNED_JWT
    Host: firestore.googleapis.com