دليل نقل التدفق خارج النطاق (OOB)

نظرة عامة

في 16 فبراير 2022، أعلنّا عن خطط لجعل تفاعلات Google OAuth أكثر أمانًا باستخدام مسارات OAuth أكثر أمانًا. يساعدك هذا الدليل في فهم التغييرات والخطوات اللازمة للانتقال بنجاح من OAuth خارج النطاق (OOB) إلى البدائل المتوافقة.

��ذا ال��ج��ا�� هو تدبير وقائي ضد هجمات التصيّد الاحتيالي وانتحال هوية التطبيقات أثناء التفاعلات مع نقاط نهاية التفويض في بروتوكول OAuth 2.0 من Google.

ما هو OOB؟

إنّ OAuth خارج النطاق (OOB)، والذي يُشار إليه أيضًا باسم خيار النسخ واللصق اليدوي، هو مسار قديم تم تطويره لدعم البرامج المثبّتة التي لا تتضمّن معرّف موارد منتظم (URI) لإعادة التوجيه من أجل قبول بيانات الاعتماد بعد موافقة المستخدم على طلب موافقة OAuth. ينطوي تدفق OOB على خطر التصيّد الاحتيالي عن بُعد، ويجب على العملاء الانتقال إلى طريقة بديلة للحماية من هذه الثغرة الأمنية.

سيتم إيقاف مسار OOB نهائيًا لجميع أنواع التطبيقات، أي تطبيقات الويب وAndroid وiOS وUniversal Windows Platform (UWP) وتطبيقات Chrome وأجهزة التلفزيون والأجهزة ذات الإدخال المحدود وتطبيقات الكمبيوتر المكتبي.

التواريخ الرئيسية للامتثال

  • ‫28 فبراير 2022: حظر استخدام OAuth الجديد لتدفق OOB
  • ‫5 سبتمبر 2022: قد تظهر رسالة تحذير موجّهة للمستخدمين بشأن طلبات OAuth غير المتوافقة
  • ‫3 أكتوبر 2022: سيتم إيقاف تدفق OOB نهائيًا لعملاء OAuth الذين تم إنشاؤهم قبل 28 فبراير 2022
  • ‫31 يناير 2023: سيتم حظر جميع العملاء الحاليين (بما في ذلك العملاء المستثنون)

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

هناك خطوتان رئيسيتان لإكمال عملية نقل البيانات:

  1. تحديد ما إذا كنت متأثرًا بهذه المشكلة
  2. ننصحك بالانتقال إلى بديل أكثر أمانًا إذا كنت متأثرًا بهذا التغيير.

تحديد ما إذا كنت متأثرًا

لا ينطبق هذا الإيقاف النهائي إلا على التطبيقات ��ي مرحلة الإنتاج (أي التطبيقات التي تم ضبط حالة نشرها على في مرحلة الإنتاج). ستستمر هذه العملية في العمل مع التطبيقات التي تكون حالة نشرها قيد الاختبار.

راجِع حالة النشر في صفحة الهوية المرئية لبروتوكول OAuth في Google Cloud Console وانتقِل إلى الخطوة التالية إذا كنت تستخدم مسار OOB في مشروع بحالة نشر "قيد الإنتاج".

كيفية تحديد ما إذا كان تطبيقك يستخدم مسار OOB

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

فحص الرمز البرمجي للتطبيق

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

  • redirect_uri=urn:ietf:wg:oauth:2.0:oob
  • redirect_uri=urn:ietf:wg:oauth:2.0:oob:auto
  • redirect_uri=oob

في ما يلي نموذج لطلب تدفق إ��ادة التوجيه خارج النطاق:

https://accounts.google.com/o/oauth2/v2/auth?
response_type=code&
scope=<SCOPES>&
state=<STATE>&
redirect_uri=urn:ietf:wg:oauth:2.0:oob&
client_id=<CLIENT_ID>

فحص طلب الشبكة الصادر

ستختلف طريقة فحص طلبات الشبكة حسب نوع تطبيقك.

أثناء فحص طلبات الشبكة، ابحث عن الطلبات المُرسَلة إلى نقاط نهاية التفويض في Google OAuth وتأكَّد مما إذا كانت المَعلمة redirect_uri تتضمّن أيًا من القيم التالية:

  • redirect_uri=urn:ietf:wg:oauth:2.0:oob
  • redirect_uri=urn:ietf:wg:oauth:2.0:oob:auto
  • redirect_uri=oob

في ما يلي نموذج لطلب تدفق إعادة التوجيه خارج النطاق:

https://accounts.google.com/o/oauth2/v2/auth?
response_type=code&
scope=<SCOPES>&
state=<STATE>&
redirect_uri=urn:ietf:wg:oauth:2.0:oob&
client_id=<CLIENT_ID>

نقل البيانات إلى بديل آمن

عملاء تطبيقات الجوّال (Android وiOS)

إذا تبيّن لك أنّ تطبيقك يستخدم مسار OOB مع نوع تطبيق OAuth لنظام التشغيل Android أو iOS، عليك الانتقال إلى استخدام حِزم تطوير البرامج (SDK) المقترَحة (Android وiOS).

تساعدك حزمة SDK في الوصول إلى Google APIs وتتعامل مع جميع الطلبات إلى نقاط نهاية تفويض OAuth 2.0 من Google.

توفّر روابط المستندات التالية معلومات حول كيفية ��ستخدام حِزم تطوير البرامج (SDK) المقترَحة ل��وصول إلى Google APIs ��د��ن ��ستخدام معرّف موارد منتظم (URI) لإعادة التوجيه خارج النطاق.

الوصول إلى Google APIs على Android

الوصول من جهة العميل

يوضّح المثال التالي كيفية الوصول إلى Google APIs من جهة العميل على أجهزة Android باستخدام مكتبة Google Identity Services Android المقترَحة.

List<Scopes> requestedScopes = Arrays.asList(DriveScopes.DRIVE_APPDATA);
AuthorizationRequest authorizationRequest =
    AuthorizationRequest.builder()
        .setRequestedScopes(requestedScopes)
        .build();
Identity.getAuthorizationClient(activity)
    .authorize(authorizationRequest)
    .addOnSuccessListener(
        authorizationResult -> {
          if (authorizationResult.hasResolution()) {
            // Access needs to be granted by the user
            PendingIntent pendingIntent =
                authorizationResult.getPendingIntent();
            try {
              startIntentSenderForResult(
                  pendingIntent.getIntentSender(),
                  REQUEST_AUTHORIZE, null, 0, 0, 0, null);
            } catch (IntentSender.SendIntentException e) {
              Log.e(
                  TAG,
                  "Couldn't start Authorization UI: "
                      + e.getLocalizedMessage());
            }
          } else {
            // Access already granted, continue with user action
            saveToDriveAppFolder(authorizationResult);
          }
        })
    .addOnFailureListener(e -> Log.e(TAG, "Failed to authorize", e));

مرِّر authorizationResult إلى الطريقة المحدّدة لحفظ المحتوى في مجلد Drive الخاص بالمستخدم. يحتوي authorizationResult على طريقة getAccessToken() التي تُنتج رمز الدخول.

الوصول من جهة الخادم (بلا إنترنت)

يوضّح المثال التالي كيفية الوصول إلى Google APIs من جهة الخادم على أجهزة Android.

List<Scopes> requestedScopes = Arrays.asList(DriveScopes.DRIVE_APPDATA);
AuthorizationRequest authorizationRequest =
    AuthorizationRequest.builder()
        .requestOfflineAccess(webClientId)
        .setRequestedScopes(requestedScopes)
        .build();
Identity.getAuthorizationClient(activity)
    .authorize(authorizationRequest)
    .addOnSuccessListener(
        authorizationResult -> {
          if (authorizationResult.hasResolution()) {
            // Access needs to be granted by the user
            PendingIntent pendingIntent =
                authorizationResult.getPendingIntent();
            try {
              startIntentSenderForResult(
                  pendingIntent.getIntentSender(),
                  REQUEST_AUTHORIZE, null, 0, 0, 0, null);
            } catch (IntentSender.SendIntentException e) {
              Log.e(
                  TAG,
                  "Couldn't start Authorization UI: "
                      + e.getLocalizedMessage());
            }
          } else {
            String authCode =
                authorizationResult.getServerAuthCode();
          }
        })
    .addOnFailureListener(e -> Log.e(TAG, "Failed to authorize", e));

يحتوي authorizationResult على طريقة getServerAuthCode() التي تعرض رمز التفويض الذي يمكنك إرساله إلى الخلفية للحصول على رمز مميز للدخول ورمز مميز لإعادة التحميل.

الوصول إلى Google APIs في تطبيق iOS

الوصول من جهة العميل

يوضّح المثال التالي كيفية الوصول إلى Google APIs من جهة العميل على أجهزة iOS.

user.authentication.do { authentication, error in
  guard error == nil else { return }
  guard let authentication = authentication else { return }
  
  // Get the access token to attach it to a REST or gRPC request.
  let accessToken = authentication.accessToken
  
  // Or, get an object that conforms to GTMFetcherAuthorizationProtocol for
  // use with GTMAppAuth and the Google APIs client library.
  let authorizer = authentication.fetcherAuthorizer()
}

استخدِم رمز الدخول لطلب واجهة برمجة التطبيقات، إما من خلال تضمين رمز الدخول في عنوان طلب REST أو gRPC (Authorization: Bearer <var>ACCESS_TOKEN</var>)، أو باستخدام أداة التفويض (GTMFetcherAuthorizationProtocol) مع مكتبة عملاء Google APIs للغة Objective-C لـ REST.

راجِع دليل الوصول من جهة العميل لمعرفة كيفية الوصول إلى Google APIs من جهة العميل.

الوصول من جهة الخادم (بلا إنترنت)

يوضّح المثال التالي كيفية الوصول إلى Google APIs من جهة الخادم لإتاحة استخدام عميل iOS.

GIDSignIn.sharedInstance.signIn(
    with: signInConfig, presenting: self
) { user, error in
  guard error == nil else { return }
  guard let user = user else { return }
  
  // request a one-time authorization code that your server exchanges for
  // an access token and refresh token
  let authCode = user.serverAuthCode
}

راجِع دليل الوصول من جهة الخادم لمعرفة كيفية الوصول إلى Google APIs من جهة الخادم.

برنامج لتطبيق Chrome

إذا تبيّن لك أنّ تطبيقك يستخدم مسار OOB على برنامج تطبيق Chrome، عليك الانتقال إلى استخدام Chrome Identity API.

يوضّح المثال التالي كيفية الحصول على جميع جهات اتصال المستخدم بدون استخدام معرّف موارد منتظم (URI) لإعادة التوجيه خارج النطاق.

window.onload = function() {
  document.querySelector('button').addEventListener('click', function() {

  
  // retrieve access token
  chrome.identity.getAuthToken({interactive: true}, function(token) {
  
  // ..........


  // the following example shows how to use a retrieved access token with an
  // appropriate scope to call the Google People API contactGroups.get endpoint

  fetch(
    'https://people.googleapis.com/v1/contactGroups/all'
        + '?maxMembers=20&key=API_KEY',
    init)
    .then((response) => response.json())
    .then(function(data) {
      console.log(data)
    });
   });
 });
};

يُرجى مراجعة دليل Chrome Identity API لمزيد من المعلومات حول كيفية الوصول إلى المستخدمين المصادق عليهم وطلب نقاط نهاية Google باستخدام Chrome Identity API.

تطبيق الويب

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

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

الوصول من جهة الخادم (بلا إنترنت)

يتطلّب وضع الوصول من جهة الخادم (بلا إنترنت) تنفيذ ما يلي :

يعرض مقتطف الرمز التالي مثالاً على NodeJS لاستخدام Google Drive API لإدراج ملفات Google Drive الخاصة بالمستخدم على جهة الخادم بدون استخدام معرّف موارد منتظم (URI) لإعادة التوجيه خارج النطاق.

async function main() {
  const server = http.createServer(async function (req, res) {

  if (req.url.startsWith('/oauth2callback')) {
    let q = url.parse(req.url, true).query;

    if (q.error) {
      console.log('Error:' + q.error);
    } else {
      
      // Get access and refresh tokens (if access_type is offline)
      let { tokens } = await oauth2Client.getToken(q.code);
      oauth2Client.setCredentials(tokens);

      // Example of using Google Drive API to list filenames in user's Drive.
      const drive = google.drive('v3');
      drive.files.list({
        auth: oauth2Client,
        pageSize: 10,
        fields: 'nextPageToken, files(id, name)',
      }, (err1, res1) => {
        // TODO(developer): Handle response / error.
      });
    }
  }
}

راجِع دليل تطبيقات الويب من جهة الخادم للتعرّف على كيفية الوصول إلى Google APIs من جهة الخادم.

الوصول من جهة العميل

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


// initTokenClient() initializes a new token client with your
// web app's client ID and the scope you need access to

const client = google.accounts.oauth2.initTokenClient({
  client_id: 'YOUR_GOOGLE_CLIENT_ID',
  scope: 'https://www.googleapis.com/auth/calendar.readonly',
  
  // callback function to handle the token response
  callback: (tokenResponse) => {
    if (tokenResponse && tokenResponse.access_token) { 
      gapi.client.setApiKey('YOUR_API_KEY');
      gapi.client.load('calendar', 'v3', listUpcomingEvents);
    }
  },
});

function listUpcomingEvents() {
  gapi.client.calendar.events.list(...);
}

راجِع دليل تطبيق الويب من جهة العميل حول كيفية الوصول إلى Google APIs من جهة العميل.

برنامج الكمبيوتر المكتبي

إذا تبيّن لك أنّ تطبيقك يستخدم مسار OOB على برنامج كمبيوتر مكتبي، عليك الانتقال إلى استخدام مسار عنوان IP‏ Loopback (الاسترجاع) (localhost أو 127.0.0.1).