نظرة عامة
في 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.
- تحديد ما إذا كنت متأثرًا
- الانتقال إلى بديل أكثر أمانًا إذا كنت متأثرًا
تحديد ما إذا كنت متأثرًا
لا ينطبق هذا الإيقاف النهائي إلا على تطبيقات الإنتاج (أي التطبيقات التي تم ضبط حالة النشر فيها على "في مرحلة الإنتاج"). سيستمر مسار النشر في العمل للتطبيقات التي تم ضبط حالة النشر فيها على "في مرحلة الاختبار".
راجِع حالة النشر في صفحة "العلامة التجارية لبروتوكول OAuth " في Google Cloud Console وانتقِل إلى الخطوة التالية إذا كنت تستخدم مسار OOB في مشروع تم ضبط حالة النشر فيه على "في مرحلة الإنتاج".
كيفية تحديد ما إذا كان تطبيقك يستخدم مسار OOB
افحص رمز تطبيقك أو طلب الشبكة الصادر (في حال كان تطبيقك يستخدم مكتبة OAuth) لتحديد ما إذا كان طلب التفويض Google OAuth الذي يرسله تطبيقك يستخدم قيمة معرّف URI لإعادة التوجيه خارج النطاق.
فحص الرمز البرمجي لتطبيقك
redirect_uri تتضمّن أيًا من القيم التالية:
redirect_uri=urn:ietf:wg:oauth:2.0:oobredirect_uri=urn:ietf:wg:oauth:2.0:oob:autoredirect_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>
فحص طلب الشبكة الصادر
- تطبيق الويب - فحص نشاط الشبكة على Chrome
- Android - فحص حركة بيانات الشبكة باستخدام "أداة فحص الشبكة"
-
تطبيقات Chrome
- انتقِل إلى صفحة إضافات Chrome.
- ضع علامة في مربّع الاختيار وضع مطوّر البرامج في أعلى يسار صفحة الإضافة.
- اختَر الإضافة التي تريد مراقبتها.
- انقر على الرابط صفحة الخلفية في قسم فحص طرق العرض في صفحة الإضافة.
- سيظهر نافذة منبثقة أدوات المطوّرين يمكنك فيها مراقبة حركة بيانات الشبكة في علامة التبويب الشبكة
- iOS - تحليل حركة بيانات HTTP باستخدام Instruments
- تطبيقات الكمبيوتر المكتبي - استخدِم أداة التقاط الشبكة المتاحة لنظام التشغيل الذي تم تطوير التطبيق من أجله.
redirect_uri تتضمّن أيًا من القيم التالية:
redirect_uri=urn:ietf:wg:oauth:2.0:oobredirect_uri=urn:ietf:wg:oauth:2.0:oob:autoredirect_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
الوصول من جهة العميل
ListrequestedScopes = 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.ListrequestedScopes = 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 ACCESS_TOKEN)،
أو باستخدام أداة التفويض في برنامج الجلب (GTMFetcherAuthorizationProtocol) مع
مكتبة عميل Google APIs للغة Objective-C من أجل REST.
راجِع دليل الوصول من جهة العميل لمعرفة كيفية الوصول إلى Google APIs من جهة العميل. لمعرفة كيفية الوصول إلى 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 example below 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.
الوصول من جهة الخادم (بدون إنترنت)
- إعداد خادم وتحديد نقطة نهاية متاحة للجميع (معرّف URI لإعادة التوجيه) لتلقّي رمز التفويض
- ضبط معرّف URI لإعادة التوجيه في صفحة "برامج العميل" في Google Cloud Console
تعرض مقتطفة الرمز البرمجي التالية مثالاً على 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 الخاص بالشبكة المحلية (localhost أو 127.0.0.1).