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

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

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

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

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

نظرة عامة

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

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

أخيرًا، يمكن لتطبيقك استخدام الرمز المميّز للوصول إلى واجهات برمجة تطبيقات Google.

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

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

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

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

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

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

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

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

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

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

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

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

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

Java

بعد الحصول على عنوان البريد الإلكتروني للعميل والمفتاح الخاص من ، استخدِم مكتبة برامج 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 باستخدام حساب الخدمة.

Python

بعد الحصول على عنوان البريد الإلكتروني للعميل والمفتاح الخاص من ، استخدِم مكتبة عميل 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')

استخدِم عنصر Credentials لطلب بيانات من Google APIs في تطبيقك.

HTTP/REST

بعد الحصول على معرّف العميل والمفتاح الخاص من ، يجب أن يُكمل تطبيقك الخطوات التالية:

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

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

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

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

يستخدم تطبيق الخادم تنسيق JWT لطلب رمز مميّز من "خادم مصادقة Google"، ثم يستخدم الرمز المميّز للاتّصال بنقطة نهاية واجهة برمجة تطبيقات Google. لا يشارك
                 أي مستخدم نهائي.

يصف الجزء المتبقّي من هذا القسم تفاصيل إنشاء ملف 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. يجب إدخال الخوارزمية والتنسيق، ولا يحتوي كل حقل سوى على قيمة واحدة. مع طرح خوارزميات وتنسيقات إضافية، سيتغيّر هذا العنوان وفقًا لذلك. رقم تعريف المفتاح اختياري، وإذا تم تحديد رقم تعريف مفتاح غير صحيح، ستحاول Google Cloud Platform جميع المفاتيح المرتبطة بحساب الخدمة للتحقّق من الرمز المميّز ورفضه في حال عدم العثور على مفتاح صالح. تحتفظ 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 بالتوقيت العالمي المنسق، في 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 الآمن. في ما يلي مثال على تمثيل 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 على الويب (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) باستخدام المفتاح الخاص الذي تم الحصول عليه من . سيكون الناتج صفيفًا من البايتات.

بعد ذلك، يجب ترميز التوقيع باستخدام 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 موقَّع، يمكن للتطبيق استخدامه لطلب الحصول على رمز مميَّز للوصول. طلب الرمز المميّز للوصول هذا هو طلب POST بروتوكول HTTPS، والنص هو عنوان 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

Java

استخدِم عنصر GoogleCredential للاتّصال بـ Google APIs من خلال إكمال الخطوات التالية:

  1. أنشئ عنصر خدمة لواجهة برمجة التطبيقات التي تريد الاتصال بها باستخدام عنصر GoogleCredential. على سبيل المثال:
    SQLAdmin sqladmin =
        new SQLAdmin.Builder(httpTransport, JSON_FACTORY, credential).build();
  2. يمكنك إرسال طلبات إلى خدمة واجهة برمجة التطبيقات باستخدام الواجهة التي يوفّرها عنصر الخدمة. على سبيل المثال، لعرض مثيلات قواعد بيانات Cloud SQL في مشروع exciting-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 في مشروع exciting-example-123 ، اتّبِع الخطوات التالية:
    response = sqladmin.instances().list(project='exciting-example-123').execute()

HTTP/REST

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

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

أمثلة على طلبات HTTP GET

قد يبدو طلب البيانات من نقطة نهاية drive.files (Drive Files API) باستخدام عنوان 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

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

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

رموز خطأ رمز JSON المميّز على الويب

حقل 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 غير مفعَّل.

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

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

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

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

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

إذا كانت واجهة برمجة التطبيقات التي تريد الاتصال بها تحتوي على تعريف خدمة منشور في مستودع Google APIs على GitHub، يمكنك إجراء طلبات بيانات مفوَّضة من واجهة برمجة التطبيقات باستخدام ملف 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

تنفيذ ميزة "الحماية العابرة للحساب"

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

في ما يلي بعض الأمثلة على أنواع الأحداث التي ترسلها خدمة "الحماية بين الحسابات" من Google إلى تطبيقك:

  • https://schemas.openid.net/secevent/risc/event-type/sessions-revoked
  • https://schemas.openid.net/secevent/oauth/event-type/token-revoked
  • https://schemas.openid.net/secevent/risc/event-type/account-disabled

اطّلِع على صفحة "حماية حسابات المستخدمين من خلال ميزة "الحماية العابرة للحساب" للحصول على مزيد من المعلومات عن كيفية تنفيذ ميزة "الحماية العابرة للحساب" والاطّلاع على القائمة الكاملة للأحداث المتاحة.