يوضّح هذا المستند كيف تستخدم تطبيقات خادم الويب مكتبات عميل Google API أو نقاط نهاية Google OAuth 2.0 لتنفيذ تفويض OAuth 2.0 من أجل الوصول إلى Google APIs.
يتيح بروتوكول OAuth 2.0 للمستخدمين مشاركة بيانات محدَّدة مع أحد التطبيقات والحفاظ على خصوصية أسماء المستخدمين وكلمات المرور والمعلومات الأخرى. على سبيل المثال، يمكن لأحد التطبيقات استخدام OAuth 2.0 للحصول على إذن من المستخدمين لتخزين الملفات في حساباتهم على Google Drive.
يُستخدَم مسار OAuth 2.0 هذا تحديدًا لتفويض المستخدم. وهي مصمَّمة للتطبيقات التي يمكنها تخزين معلومات سرية والحفاظ على الحالة. يمكن لتطبيق خادم ويب معتمد بشكل صحيح الوصول إلى واجهة برمجة تطبيقات أثناء تفاعل المستخدم مع التطبيق أو بعد أن يغادر المستخدم التطبيق.
تستخدم تطبيقات خادم الويب أيضًا حسابات الخدمة بشكل متكرر لتفويض طلبات واجهة برمجة التطبيقات، خاصةً عند استدعاء واجهات Cloud API للوصول إلى البيانات المستندة إلى المشاريع بدلاً من البيانات الخاصة بالمستخدمين. يمكن لتطبيقات خادم الويب استخدام حسابات الخدمة مع تفويض المستخدم.
مكتبات العملاء
تستخدم الأمثلة الخاصة باللغة الواردة في هذه الصفحة مكتبات عميل Google API لتنفيذ تفويض OAuth 2.0. لتشغيل نماذج الرموز البرمجية، عليك أولاً تثبيت مكتبة البرامج الخاصة بلغة الرمز البرمجي.
عند استخدام مكتبة برامج Google API للتعامل مع مسار OAuth 2.0 في تطبيقك، تنفّذ مكتبة البرامج العديد من الإجراءات التي كان على التطبيق تنفيذها بنفسه. على سبيل المثال، يحدّد هذا الإعداد الحالات التي يمكن فيها للتطبيق استخدام رموز الدخول المخزّنة أو إعادة تحميلها، بالإضافة إلى الحالات التي يجب فيها على التطبيق الحصول على الموافقة مجددًا. تنشئ مكتبة البرامج أيضًا عناوين URL صحيحة لإعادة التوجيه، وتساعد في تنفيذ معالجات إعادة التوجيه التي تستبدل رموز التفويض برموز الدخول المميزة.
تتوفّر مكتبات عملاء Google API للتطبيقات من جهة الخادم باللغات التالية:
المتطلبات الأساسية
تفعيل واجهات برمجة التطبيقات لمشروعك
يجب تفعيل واجهات Google APIs في API Consoleلأي تطبيق يستدعي هذه الواجهات.
لتفعيل واجهة برمجة تطبيقات لمشروعك، اتّبِع الخطوات التالية:
- Open the API Library في Google API Console
- If prompted, select a project, or create a new one.
- تعرض API Library جميع واجهات برمجة التطبيقات المتاحة، ويتم تجميعها حسب فئة المنتج ومدى رواجها. إذا لم يكن واجهة برمجة التطبيقات التي تريد تفعيلها ظاهرة في القائمة، استخدِم البحث للعثور عليها، أو انقر على عرض الكل في مجموعة المنتجات التي تنتمي إليها.
- اختَر واجهة برمجة التطبيقات التي تريد تفعيلها، ثم انقر على الزر تفعيل.
- If prompted, enable billing.
- If prompted, read and accept the API's Terms of Service.
إنشاء بيانات اعتماد التفويض
يجب أن يتضمّن أي تطبيق يستخدم OAuth 2.0 للوصول إلى Google APIs بيانات اعتماد تفويض تحدّد التطبيق لخادم OAuth 2.0 من Google. توضّح الخطوات التالية كيفية إنشاء بيانات اعتماد لمشروعك. يمكن لتطبيقاتك بعد ذلك استخدام بيانات الاعتماد للوصول إلى واجهات برمجة التطبيقات التي فعّلتها لهذا المشروع.
- Go to the Credentials page.
- انقر على إنشاء عميل.
- اختَر نوع التطبيق تطبيق الويب.
- املأ النموذج وانقر على إنشاء. يجب أن تحدّد التطبيقات التي تستخدم لغات وأُطر عمل مثل PHP وJava وPython وRuby و .NET معرّفات موارد منتظمة (URI) لإعادة التوجيه معتمَدة. معرّفات الموارد المنتظمة (URI) لإعادة التوجيه هي نقاط النهاية التي يمكن لخادم OAuth 2.0 إرسال الردود إليها. يجب أن تلتزم نقاط النهاية هذه بقواعد التحقّق من الصحة في Google.
للاختبار، يمكنك تحديد معرّفات URI تشير إلى الجهاز المحلي، مثل
http://localhost:8080
. مع أخذ ذلك في الاعتبار، يُرجى العلم أنّ جميع الأمثلة في هذا المستند تستخدمhttp://localhost:8080
كمعرّف الموارد المنتظم (URI) الخاص بإعادة التوجيه.ننصحك بتصميم نقاط نهاية المصادقة في تطبيقك بطريقة تضمن عدم عرض رموز التفويض لموارد أخرى على الصفحة.
بعد إنشاء بيانات الاعتماد، نزِّل الملف client_secret.json من API Console. احفظ الملف بشكل آمن في مكان لا يمكن لأي تطبيق آخر الوصول إليه.
تحديد نطاقات الوصول
تتيح النطاقات لتطبيقك طلب الوصول إلى الموارد التي يحتاجها فقط، كما تتيح للمستخدمين التحكّم في مقدار الوصول الذي يمنحونه لتطبيقك. وبالتالي، قد تكون هناك علاقة عكسية بين عدد النطاقات المطلوبة واحتمالية الحصول على موافقة المستخدم.
قبل البدء في تنفيذ تفويض OAuth 2.0، ننصحك بتحديد النطاقات التي سيحتاج تطبيقك إلى إذن للوصول إليها.
ننصح أيضًا بأن يطلب تطبيقك الوصول إلى نطاقات التفويض من خلال عملية تفويض متزايد، حيث يطلب تطبيقك الوصول إلى بيانات المستخدم في سياقها. تساعد هذه الممارسة المستخدمين على فهم سبب احتياج تطبيقك إلى الإذن الذي يطلبه.
يحتوي مستند نطاقات واجهة برمجة التطبيقات OAuth 2.0 على قائمة كاملة بالنطاقات التي يمكنك استخدامها للوصول إلى Google APIs.
المتطلبات الخاصة باللغة
لتشغيل أي من نماذج الرموز البرمجية الواردة في هذا المستند، يجب أن يكون لديك حساب على Google، وأن تتمكّن من الوصول إلى الإنترنت، وأن يتوفّر لديك متصفّح ويب. إذا كنت تستخدم إحدى مكتبات برامج واجهة برمجة التطبيقات، يمكنك أيضًا الاطّلاع على المتطلبات الخاصة باللغة أدناه.
PHP
لتشغيل نماذج رمز PHP في هذا المستند، ستحتاج إلى ما يلي:
- الإصدار 8.0 من PHP أو إصدار أحدث مع تثبيت واجهة سطر الأوامر (CLI) وإضافة JSON
- أداة إدارة التبعية Composer
-
مكتبة برامج Google APIs للغة PHP:
composer require google/apiclient:^2.15.0
اطّلِع على مكتبة برامج Google API للغة PHP لمزيد من المعلومات.
Python
لتشغيل نماذج رموز Python البرمجية في هذا المستند، ستحتاج إلى ما يلي:
- الإصدار 3.7 أو الإصدارات الأحدث من Python
- أداة إدارة الحِزم pip
- إصدار 2.0 من Google APIs Client Library للغة Python:
pip install --upgrade google-api-python-client
google-auth
وgoogle-auth-oauthlib
وgoogle-auth-httplib2
لتفويض المستخدم.pip install --upgrade google-auth google-auth-oauthlib google-auth-httplib2
- إطار عمل تطبيقات الويب Flask Python
pip install --upgrade flask
- مكتبة HTTP
requests
pip install --upgrade requests
راجِع ملاحظات الإصدار الخاصة بمكتبة برامج Google API Python إذا لم تتمكّن من ترقية Python ودليل النقل المرتبط بها.
Ruby
لتشغيل نماذج رموز Ruby البرمجية في هذا المستند، ستحتاج إلى ما يلي:
- الإصدار 2.6 من Ruby أو إصدار أحدث
-
مكتبة Google Auth للغة Ruby:
gem install googleauth
-
مكتبات البرامج لواجهات Google API الخاصة بخدمتَي Drive وCalendar:
gem install google-apis-drive_v3 google-apis-calendar_v3
-
إطار عمل تطبيق الويب Sinatra Ruby
gem install sinatra
Node.js
لتنفيذ عيّنات رمز Node.js في هذا المستند، ستحتاج إلى:
- إصدار الصيانة أو الإصدار النشط أو الإصدار الحالي من Node.js
-
عميل Google APIs Node.js:
npm install googleapis crypto express express-session
HTTP/REST
لست بحاجة إلى تثبيت أي مكتبات لتتمكّن من طلب نقاط نهاية OAuth 2.0 مباشرةً.
الحصول على رموز الدخول عبر OAuth 2.0
توضّح الخطوات التالية كيفية تفاعل تطبيقك مع خادم OAuth 2.0 من Google للحصول على موافقة المستخدم على تنفيذ طلب API بالنيابة عنه. يجب أن يحصل تطبيقك على هذه الموافقة قبل أن يتمكّن من تنفيذ طلب Google API يتطلّب إذن المستخدم.
تُلخّص القائمة أدناه هذه الخطوات بسرعة:
- يحدّد تطبيقك الأذونات التي يحتاج إليها.
- يعيد تطبيقك توجيه المستخدم إلى Google مع قائمة الأذونات المطلوبة.
- يقرّر المستخدم ما إذا كان سيمنح تطبيقك الأذونات أم لا.
- يتعرّف تطبيقك على القرار الذي اتخذه المستخدم.
- إذا منح المستخدم الأذونات المطلوبة، يسترد تطبيقك الرموز المميزة اللازمة لتقديم طلبات إلى واجهة برمجة التطبيقات نيابةً عن المستخدم.
الخطوة 1: ضبط مَعلمات التفويض
تتمثّل خطوتك الأولى في إنشاء طلب التفويض. يضبط هذا الطلب مَعلمات تحدّد تطبيقك وتعرّف الأذونات التي سيُطلب من المستخدم منحها لتطبيقك.
- إذا كنت تستخدم مكتبة برامج عميل Google للمصادقة والتفويض باستخدام OAuth 2.0، عليك إنشاء عنصر وتكوينه لتحديد هذه المَعلمات.
- إذا طلبت نقطة نهاية Google OAuth 2.0 مباشرةً، سيتم إنشاء عنوان URL وتحديد المَعلمات في عنوان URL هذا.
تحدّد علامات التبويب أدناه مَعلمات التفويض المتوافقة مع تطبيقات خادم الويب. توضّح الأمثلة الخاصة بكل لغة أيضًا كيفية استخدام مكتبة برامج أو مكتبة تفويض لإعداد عنصر يضبط هذه المَعلمات.
PHP
ينشئ مقتطف الرمز التالي عنصر Google\Client()
، الذي يحدّد المَعلمات في طلب التفويض.
يستخدم هذا العنصر معلومات من ملف client_secret.json لتحديد تطبيقك. (يمكنك الاطّلاع على إنشاء بيانات اعتماد التفويض لمعرفة المزيد عن هذا الملف). يحدّد العنصر أيضًا النطاقات التي يطلب تطبيقك الإذن بالوصول إليها وعنوان URL لنقطة نهاية المصادقة في تطبيقك، والتي ستتعامل مع الردّ من خادم OAuth 2.0 من Google. أخيرًا، يضبط الرمز المَعلمتَين الاختياريتَين access_type
وinclude_granted_scopes
.
على سبيل المثال، يطلب هذا الرمز إذن الوصول إلى البيانات الوصفية الخاصة بمستخدم في Google Drive وأحداث التقويم بدون اتصال بالإنترنت وبإذن القراءة فقط:
use Google\Client; $client = new Client(); // Required, call the setAuthConfig function to load authorization credentials from // client_secret.json file. $client->setAuthConfig('client_secret.json'); // Required, to set the scope value, call the addScope function $client->addScope([Google\Service\Drive::DRIVE_METADATA_READONLY, Google\Service\Calendar::CALENDAR_READONLY]); // Required, call the setRedirectUri function to specify a valid redirect URI for the // provided client_id $client->setRedirectUri('http://' . $_SERVER['HTTP_HOST'] . '/oauth2callback.php'); // Recommended, offline access will give you both an access and refresh token so that // your app can refresh the access token without user interaction. $client->setAccessType('offline'); // Recommended, call the setState function. Using a state value can increase your assurance that // an incoming connection is the result of an authentication request. $client->setState($sample_passthrough_value); // Optional, if your application knows which user is trying to authenticate, it can use this // parameter to provide a hint to the Google Authentication Server. $client->setLoginHint('hint@example.com'); // Optional, call the setPrompt function to set "consent" will prompt the user for consent $client->setPrompt('consent'); // Optional, call the setIncludeGrantedScopes function with true to enable incremental // authorization $client->setIncludeGrantedScopes(true);
Python
يستخدم مقتطف الرمز البرمجي التالي الوحدة google-auth-oauthlib.flow
لإنشاء طلب التفويض.
ينشئ الرمز البرمجي عنصر Flow
، الذي يحدّد تطبيقك باستخدام معلومات من ملف client_secret.json الذي نزّلته بعد إنشاء بيانات اعتماد التفويض. يحدّد هذا العنصر أيضًا النطاقات التي يطلب تطبيقك الإذن بالوصول إليها وعنوان URL لنقطة نهاية المصادقة في تطبيقك، والتي ستتعامل مع الردّ من خادم OAuth 2.0 من Google. أخيرًا، يضبط الرمز المَعلمتَين الاختياريتَين access_type
وinclude_granted_scopes
.
على سبيل المثال، يطلب هذا الرمز إذن الوصول إلى البيانات الوصفية في Google Drive وأحداث التقويم بلا اتصال بالإنترنت وبإذن القراءة فقط:
import google.oauth2.credentials import google_auth_oauthlib.flow # Required, call the from_client_secrets_file method to retrieve the client ID from a # client_secret.json file. The client ID (from that file) and access scopes are required. (You can # also use the from_client_config method, which passes the client configuration as it originally # appeared in a client secrets file but doesn't access the file itself.) flow = google_auth_oauthlib.flow.Flow.from_client_secrets_file('client_secret.json', scopes=['https://www.googleapis.com/auth/drive.metadata.readonly', 'https://www.googleapis.com/auth/calendar.readonly']) # Required, indicate where the API server will redirect the user after the user completes # the authorization flow. The redirect URI is required. The value must exactly # match one of the authorized redirect URIs for the OAuth 2.0 client, which you # configured in the API Console. If this value doesn't match an authorized URI, # you will get a 'redirect_uri_mismatch' error. flow.redirect_uri = 'https://www.example.com/oauth2callback' # Generate URL for request to Google's OAuth 2.0 server. # Use kwargs to set optional request parameters. authorization_url, state = flow.authorization_url( # Recommended, enable offline access so that you can refresh an access token without # re-prompting the user for permission. Recommended for web server apps. access_type='offline', # Optional, enable incremental authorization. Recommended as a best practice. include_granted_scopes='true', # Optional, if your application knows which user is trying to authenticate, it can use this # parameter to provide a hint to the Google Authentication Server. login_hint='hint@example.com', # Optional, set prompt to 'consent' will prompt the user for consent prompt='consent')
Ruby
استخدِم ملف client_secrets.json الذي أنشأته لإعداد عنصر عميل في تطبيقك. عند ضبط عنصر عميل، عليك تحديد النطاقات التي يحتاج تطبيقك إلى الوصول إليها، بالإضافة إلى عنوان URL لنقطة نهاية المصادقة في تطبيقك، والتي ستتعامل مع الردّ من خادم OAuth 2.0.
على سبيل المثال، يطلب هذا الرمز إذن الوصول إلى البيانات الوصفية في Google Drive وأحداث التقويم بلا اتصال بالإنترنت وبإذن القراءة فقط:
require 'googleauth' require 'googleauth/web_user_authorizer' require 'googleauth/stores/redis_token_store' require 'google/apis/drive_v3' require 'google/apis/calendar_v3' # Required, call the from_file method to retrieve the client ID from a # client_secret.json file. client_id = Google::Auth::ClientId.from_file('/path/to/client_secret.json') # Required, scope value # Access scopes for two non-Sign-In scopes: Read-only Drive activity and Google Calendar. scope = ['Google::Apis::DriveV3::AUTH_DRIVE_METADATA_READONLY', 'Google::Apis::CalendarV3::AUTH_CALENDAR_READONLY'] # Required, Authorizers require a storage instance to manage long term persistence of # access and refresh tokens. token_store = Google::Auth::Stores::RedisTokenStore.new(redis: Redis.new) # Required, indicate where the API server will redirect the user after the user completes # the authorization flow. The redirect URI is required. The value must exactly # match one of the authorized redirect URIs for the OAuth 2.0 client, which you # configured in the API Console. If this value doesn't match an authorized URI, # you will get a 'redirect_uri_mismatch' error. callback_uri = '/oauth2callback' # To use OAuth2 authentication, we need access to a CLIENT_ID, CLIENT_SECRET, AND REDIRECT_URI # from the client_secret.json file. To get these credentials for your application, visit # https://console.cloud.google.com/apis/credentials. authorizer = Google::Auth::WebUserAuthorizer.new(client_id, scope, token_store, callback_uri)
يستخدم تطبيقك عنصر العميل لتنفيذ عمليات OAuth 2.0، مثل إنشاء عناوين URL لطلبات التفويض وتطبيق رموز الدخول المميزة على طلبات HTTP.
Node.js
ينشئ مقتطف الرمز التالي عنصر google.auth.OAuth2
، الذي يحدّد المَعلمات في طلب التفويض.
يستخدم هذا العنصر معلومات من ملف client_secret.json لتحديد تطبيقك. لطلب أذونات من مستخدم لاسترداد رمز دخول، عليك إعادة توجيهه إلى صفحة موافقة. لإنشاء عنوان URL لصفحة الموافقة، اتّبِع الخطوات التالية:
const {google} = require('googleapis'); const crypto = require('crypto'); const express = require('express'); const session = require('express-session'); /** * To use OAuth2 authentication, we need access to a CLIENT_ID, CLIENT_SECRET, AND REDIRECT_URI * from the client_secret.json file. To get these credentials for your application, visit * https://console.cloud.google.com/apis/credentials. */ const oauth2Client = new google.auth.OAuth2( YOUR_CLIENT_ID, YOUR_CLIENT_SECRET, YOUR_REDIRECT_URL ); // Access scopes for two non-Sign-In scopes: Read-only Drive activity and Google Calendar. const scopes = [ 'https://www.googleapis.com/auth/drive.metadata.readonly', 'https://www.googleapis.com/auth/calendar.readonly' ]; // Generate a secure random state value. const state = crypto.randomBytes(32).toString('hex'); // Store state in the session req.session.state = state; // Generate a url that asks permissions for the Drive activity and Google Calendar scope const authorizationUrl = oauth2Client.generateAuthUrl({ // 'online' (default) or 'offline' (gets refresh_token) access_type: 'offline', /** Pass in the scopes array defined above. * Alternatively, if only one scope is needed, you can pass a scope URL as a string */ scope: scopes, // Enable incremental authorization. Recommended as a best practice. include_granted_scopes: true, // Include the state parameter to reduce the risk of CSRF attacks. state: state });
ملاحظة مهمة - لا يتم عرض refresh_token
إلا عند إجراء عملية التفويض الأولى. يمكنك الاطّلاع على المزيد من التفاصيل
هنا.
HTTP/REST
تتوفّر نقطة نهاية OAuth 2.0 من Google على https://accounts.google.com/o/oauth2/v2/auth
. لا يمكن الوصول إلى نقطة النهاية هذه إلا عبر HTTPS. يتم رفض اتصالات HTTP العادية.
يتيح خادم التفويض من Google مَعلمات سلسلة طلب البحث التالية لتطبيقات خادم الويب:
المعلمات | |||||||
---|---|---|---|---|---|---|---|
client_id |
مطلوب
معرّف العميل لتطبيقك يمكنك العثور على هذه القيمة في . |
||||||
redirect_uri |
مطلوب
تحدِّد هذه السمة المكان الذي يعيد خادم واجهة برمجة التطبيقات توجيه المستخدم إليه بعد إكماله عملية التفويض. يجب أن تتطابق القيمة تمامًا مع أحد معرّفات الموارد المنتظمة (URI) المسموح بها لإعادة التوجيه الخاصة بعميل OAuth 2.0 الذي أعددته في
الخاص بعميلك. إذا لم تتطابق هذه القيمة مع معرّف الموارد المنتظم (URI) المصرّح به لإعادة التوجيه والمقدَّم يُرجى العِلم أنّه يجب أن يتطابق كل من نظام |
||||||
response_type |
مطلوب
تحدِّد هذه السمة ما إذا كانت نقطة نهاية Google OAuth 2.0 تعرض رمز تفويض. اضبط قيمة المَعلمة على |
||||||
scope |
مطلوب
قائمة مفصولة بمسافات تتضمّن النطاقات التي تحدّد الموارد التي يمكن لتطبيقك الوصول إليها نيابةً عن المستخدم. تُعلم هذه القيم شاشة الموافقة التي تعرضها Google للمستخدم. تتيح النطاقات لتطبيقك طلب الوصول إلى الموارد التي يحتاج إليها فقط، كما تتيح للمستخدمين التحكّم في مقدار الوصول الذي يمنحونه لتطبيقك. وبالتالي، هناك علاقة عكسية بين عدد النطاقات المطلوبة واحتمالية الحصول على موافقة المستخدم. ننصح بأن يطلب تطبيقك الوصول إلى نطاقات التفويض في السياق كلما أمكن ذلك. من خلال طلب الوصول إلى بيانات المستخدمين في سياق استخدام التطبيق، وذلك من خلال الترخيص المتزايد، يمكنك مساعدة المستخدمين على فهم سبب احتياج تطبيقك إلى إذن الوصول الذي يطلبه. |
||||||
access_type |
مقترَح
تشير هذه السمة إلى ما إذا كان بإمكان تطبيقك إعادة تحميل رموز الدخول المميزة عندما لا يكون المستخدم متواجدًا على المتصفّح. قيم المَعلمات الصالحة هي اضبط القيمة على |
||||||
state |
مقترَح
تحدّد هذه السمة أي قيمة سلسلة تستخدمها التطبيقات للحفاظ على الحالة بين طلب التفويض والاستجابة من خادم التفويض.
يعرض الخادم القيمة الدقيقة التي ترسلها كزوج يمكنك استخدام هذه المَعلمة لعدّة أغراض، مثل توجيه المستخدم إلى المرجع الصحيح في تطبيقك، وإرسال أرقام عشوائية، والحدّ من التزوير في الطلبات الواردة من مواقع إلكترونية مختلفة. بما أنّه يمكن تخمين |
||||||
include_granted_scopes |
اختياريّ
تتيح هذه السمة للتطبيقات استخدام المصادقة المتزايدة لطلب الوصول إلى نطاقات إضافية حسب السياق. إذا ضبطت قيمة هذه المَعلمة على |
||||||
enable_granular_consent |
اختياريّ
القيمة التلقائية هي عندما تفعّل Google أذونات تفصيلية لأحد التطبيقات، لن يكون لهذه المَعلمة أي تأثير. |
||||||
login_hint |
اختياريّ
إذا كان تطبيقك يعرف المستخدم الذي يحاول إثبات هويته، يمكنه استخدام هذه المَعلمة لتقديم تلميح إلى خادم مصادقة Google. يستخدم الخادم التلميح لتبسيط عملية تسجيل الدخول، إما عن طريق ملء حقل البريد الإلكتروني مسبقًا في نموذج تسجيل الدخول أو عن طريق اختيار جلسة تسجيل الدخول المتعدد المناسبة. اضبط قيمة المَعلمة على عنوان بريد إلكتروني أو معرّف |
||||||
prompt |
اختياريّ
قائمة حساسة لحالة الأحرف ومفصولة بمسافات تتضمّن الطلبات التي سيتم عرضها للمستخدم في حال عدم تحديد هذه المَعلمة، سيُطلب من المستخدم الإذن بالوصول إلى البيانات في المرة الأولى فقط التي يطلب فيها مشروعك الوصول إليها. يمكنك الاطّلاع على طلب إعادة الموافقة لمزيد من المعلومات. القيم المحتملة هي:
|
الخطوة 2: إعادة التوجيه إلى خادم OAuth 2.0 من Google
إعادة توجيه المستخدم إلى خادم OAuth 2.0 من Google لبدء عملية المصادقة والتفويض يحدث ذلك عادةً عندما يحتاج تطبيقك إلى الوصول إلى بيانات المستخدم لأول مرة. في حالة الموافقة المتزايدة، تحدث هذه الخطوة أيضًا عندما يحتاج تطبيقك لأول مرة إلى الوصول إلى موارد إضافية لا يملك إذن الوصول إليها بعد.
PHP
- إنشاء عنوان URL لطلب الوصول من خادم OAuth 2.0 من Google:
$auth_url = $client->createAuthUrl();
- إعادة توجيه المستخدم إلى
$auth_url
:header('Location: ' . filter_var($auth_url, FILTER_SANITIZE_URL));
Python
يوضّح هذا المثال كيفية إعادة توجيه المستخدم إلى عنوان URL الخاص بالتفويض باستخدام إطار عمل تطبيق الويب Flask:
return flask.redirect(authorization_url)
Ruby
- إنشاء عنوان URL لطلب الوصول من خادم OAuth 2.0 من Google:
auth_uri = authorizer.get_authorization_url(request: request)
- إعادة توجيه المستخدم إلى
auth_uri
Node.js
-
استخدِم عنوان URL الذي تم إنشاؤه
authorizationUrl
من طريقة الخطوة 1generateAuthUrl
لطلب الوصول من خادم OAuth 2.0 التابع لـ Google. -
إعادة توجيه المستخدم إلى
authorizationUrl
res.redirect(authorizationUrl);
HTTP/REST
مثال على إعادة التوجيه إلى خادم التفويض في Google
يظهر أدناه مثال على عنوان URL، مع فواصل أسطر ومسافات لتسهيل القراءة.
https://accounts.google.com/o/oauth2/v2/auth? scope=https%3A//www.googleapis.com/auth/drive.metadata.readonly%20https%3A//www.googleapis.com/auth/calendar.readonly& access_type=offline& include_granted_scopes=true& response_type=code& state=state_parameter_passthrough_value& redirect_uri=https%3A//oauth2.example.com/code& client_id=client_id
بعد إنشاء عنوان URL للطلب، أعِد توجيه المستخدم إليه.
يصادق خادم OAuth 2.0 من Google على المستخدم ويحصل على موافقته ليتمكّن تطبيقك من الوصول إلى النطاقات المطلوبة. يتم إرسال الرد إلى تطبيقك باستخدام عنوان URL لإعادة التوجيه الذي حدّدته.
الخطوة 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 Foundation.
قد يواجه مطوّرو الويب هذا الخطأ عندما يفتح تطبيق Android رابطًا عامًا على الويب في وكيل مستخدم مضمّن، وينتقل المستخدم إلى نقطة نهاية تفويض بروتوكول OAuth 2.0 من Google من موقعك الإلكتروني. على المطوّرين السماح بفتح الروابط العامة في معالج الروابط التلقائي لنظام التشغيل، والذي يتضمّن كلاً من معالجات روابط تطبيقات Android أو تطبيق المتصفّح التلقائي. وتُعد مكتبة علامات التبويب المخصّصة في Android أيضًا خيارًا متاحًا.
iOS
قد يواجه مطوّرو تطبيقات iOS وmacOS هذا الخطأ عند فتح طلبات الحصول على إذن في
WKWebView
.
على المطوّرين بدلاً من ذلك استخدام مكتبات iOS، مثل
Google Sign-In for iOS أو
AppAuth for iOS من OpenID Foundation.
قد يواجه مطوّرو الويب هذا الخطأ عندما يفتح تطبيق على iOS أو macOS رابط ويب عامًا في وكيل مستخدم مضمّن، وينتقِل المستخدم إلى نقطة نهاية تفويض بروتوكول OAuth 2.0 من Google من موقعك الإلكتروني. على المطوّرين السماح بفتح الروابط العامة في معالج الروابط التلقائي لنظام التشغيل، والذي يتضمّن معالجات الروابط العامة أو تطبيق المتصفّح التلقائي. وتُعد مكتبة SFSafariViewController
خيارًا متاحًا أيضًا.
org_internal
إنّ رقم تعريف عميل OAuth في الطلب هو جزء من مشروع يحدّ من الوصول إلى حسابات Google في مؤسسة Google Cloud محدّدة. لمزيد من المعلومات حول خيار الإعداد هذا، راجِع قسم نوع المستخدم في مقالة المساعدة حول إعداد شاشة موافقة OAuth.
invalid_client
سر عميل OAuth غير صحيح. راجِع إعدادات عميل OAuth، بما في ذلك معرّف العميل وسر العميل المستخدَمَين في هذا الطلب.
deleted_client
تم حذف عميل OAuth المستخدَم لتقديم الطلب. يمكن أن تتم عملية الحذف يدويًا أو تلقائيًا في حالة العملاء غير النشطين . يمكن استعادة العملاء المحذوفين في غضون 30 يومًا من الحذف. مزيد من المعلومات
invalid_grant
عند إعادة تحميل رمز دخول أو استخدام التفويض التزايدي، قد تكون صلاحية الرمز المميز قد انتهت أو تم إبطاله. أثبِت هوية المستخدم مرة أخرى واطلب موافقته للحصول على رموز مميزة جديدة. إذا استمر ظهور هذا الخطأ، تأكَّد من إعداد تطبيقك بشكل صحيح ومن استخدام الرموز المميزة والمَعلمات الصحيحة في طلبك. بخلاف ذلك، قد يكون قد تم حذف حساب المستخدم أو إيقافه.
redirect_uri_mismatch
لا يتطابق redirect_uri
الذي تم تمريره في طلب التفويض مع معرّف الموارد المنتظم (URI) لإعادة التوجيه المصرّح به لمعرّف عميل OAuth. راجِع معرّفات الموارد المنتظمة (URI) المعتمَدة لإعادة التوجيه في
.
قد تشير المَعلمة redirect_uri
إلى مسار OAuth خارج النطاق (OOB) الذي تم إيقافه نهائيًا ولم يعُد متاحًا. راجِع دليل نقل البيانات لتعديل عملية الدمج.
invalid_request
حدث خطأ في الطلب الذي قدّمته. قد يرجع ذلك إلى عدة أسباب:
- لم يتم تنسيق الطلب بشكلٍ صحيح
- لم يتضمّن الطلب المَعلمات المطلوبة
- يستخدم الطلب طريقة لا تسمح بها Google لمنح إذن الوصول. التأكّد من أنّ عملية دمج OAuth تستخدم طريقة دمج مقترَحة
الخطوة 4: التعامل مع استجابة خادم OAuth 2.0
يستجيب خادم OAuth 2.0 لطلب الوصول الذي يرسله تطبيقك باستخدام عنوان URL المحدّد في الطلب.
إذا وافق المستخدم على طلب الوصول، سيتضمّن الردّ رمز تفويض. إذا لم يوافق المستخدم على الطلب، سيتضمّن الرد رسالة خطأ. يظهر رمز التفويض أو رسالة الخطأ التي يتم عرضها على خادم الويب في سلسلة طلب البحث، كما هو موضّح أدناه:
استجابة تتضمّن خطأ:
https://oauth2.example.com/auth?error=access_denied
استجابة رمز التفويض:
https://oauth2.example.com/auth?code=4/P7q7W91a-oMsCeLvIaQm6bTrgtp7
نموذج استجابة خادم OAuth 2.0
يمكنك اختبار هذا المسار من خلال النقر على عنوان URL النموذجي التالي الذي يطلب إذنًا بالقراءة فقط لعرض البيانات الوصفية للملفات في Google Drive وإذنًا بالقراءة فقط لعرض أحداث "تقويم Google":
https://accounts.google.com/o/oauth2/v2/auth? scope=https%3A//www.googleapis.com/auth/drive.metadata.readonly%20https%3A//www.googleapis.com/auth/calendar.readonly& access_type=offline& include_granted_scopes=true& response_type=code& state=state_parameter_passthrough_value& redirect_uri=https%3A//oauth2.example.com/code& client_id=client_id
بعد إكمال عملية OAuth 2.0، من المفترض أن تتم إعادة توجيهك إلى
http://localhost/oauth2callback
، ما سيؤدي على الأرجح إلى ظهور الخطأ
404 NOT FOUND
ما لم يكن جهازك المحلي يعرض ملفًا على هذا العنوان. تقدّم الخطوة التالية تفاصيل أكثر حول المعلومات التي يتم عرضها في معرّف الموارد المنتظم (URI) عند إعادة توجيه المستخدم إلى تطبيقك.
الخطوة 5: تبديل رمز التفويض برموز مميّزة لإعادة التحميل والدخول
بعد أن يتلقّى خادم الويب رمز التفويض، يمكنه تبديل رمز التفويض برمز مميّز للوصول.
PHP
لتبديل رمز تفويض برمز دخول، استخدِم طريقة fetchAccessTokenWithAuthCode
:
$access_token = $client->fetchAccessTokenWithAuthCode($_GET['code']);
Python
في صفحة معاودة الاتصال، استخدِم مكتبة google-auth
للتحقّق من ردّ خادم التفويض. بعد ذلك، استخدِم طريقة flow.fetch_token
لتبديل رمز التفويض في تلك الاستجابة برمز دخول:
state = flask.session['state'] flow = google_auth_oauthlib.flow.Flow.from_client_secrets_file( 'client_secret.json', scopes=['https://www.googleapis.com/auth/drive.metadata.readonly'], state=state) flow.redirect_uri = flask.url_for('oauth2callback', _external=True) authorization_response = flask.request.url flow.fetch_token(authorization_response=authorization_response) # Store the credentials in the session. # ACTION ITEM for developers: # Store user's access and refresh tokens in your data store if # incorporating this code into your real app. credentials = flow.credentials flask.session['credentials'] = { 'token': credentials.token, 'refresh_token': credentials.refresh_token, 'token_uri': credentials.token_uri, 'client_id': credentials.client_id, 'client_secret': credentials.client_secret, 'granted_scopes': credentials.granted_scopes}
Ruby
في صفحة معاودة الاتصال، استخدِم مكتبة googleauth
للتحقّق من ردّ خادم التفويض. استخدِم طريقة authorizer.handle_auth_callback_deferred
لحفظ رمز التفويض وإعادة التوجيه إلى عنوان URL الذي طلب التفويض في الأصل. يؤجّل هذا الإجراء تبادل الرمز من خلال تخزين النتائج مؤقتًا في جلسة المستخدم.
target_url = Google::Auth::WebUserAuthorizer.handle_auth_callback_deferred(request) redirect target_url
Node.js
لتبديل رمز تفويض برمز دخول، استخدِم طريقة getToken
:
const url = require('url'); // Receive the callback from Google's OAuth 2.0 server. app.get('/oauth2callback', async (req, res) => { let q = url.parse(req.url, true).query; if (q.error) { // An error response e.g. error=access_denied console.log('Error:' + q.error); } else if (q.state !== req.session.state) { //check state value console.log('State mismatch. Possible CSRF attack'); res.end('State mismatch. Possible CSRF attack'); } else { // Get access and refresh tokens (if access_type is offline) let { tokens } = await oauth2Client.getToken(q.code); oauth2Client.setCredentials(tokens); });
HTTP/REST
لتبديل رمز تفويض برمز دخول، اتّصِل بنقطة النهاية https://oauth2.googleapis.com/token
واضبط المَعلمات التالية:
الحقول | |
---|---|
client_id |
معرّف العميل الذي تم الحصول عليه من |
client_secret |
سر العميل الذي تم الحصول عليه من |
code |
رمز التفويض الذي تم عرضه في الطلب الأوّلي |
grant_type |
وفقًا لما هو محدّد في مواصفات OAuth 2.0، يجب ضبط قيمة هذا الحقل على authorization_code . |
redirect_uri |
أحد معرّفات الموارد المنتظمة (URI) لإعادة التوجيه المُدرَجة في مشروعك في
لـ
client_id المحدّد |
يعرض المقتطف التالي نموذجًا لطلب:
POST /token HTTP/1.1 Host: oauth2.googleapis.com Content-Type: application/x-www-form-urlencoded code=4/P7q7W91a-oMsCeLvIaQm6bTrgtp7& client_id=your_client_id& client_secret=your_client_secret& redirect_uri=https%3A//oauth2.example.com/code& grant_type=authorization_code
تستجيب Google لهذا الطلب من خلال عرض عنصر JSON يحتوي على رمز مميز قصير الأمد للوصول ورمز مميز لإعادة التحميل.
يُرجى العِلم أنّه لا يتم عرض رمز الدخول المميز إلا إذا ضبط تطبيقك المَعلمة access_type
على offline
في الطلب الأوّلي إلى خادم التفويض من Google.
يتضمّن الرد الحقول التالية:
الحقول | |
---|---|
access_token |
الرمز المميز الذي يرسله تطبيقك للموافقة على طلب Google API. |
expires_in |
تمثّل هذه السمة مدة صلاحية رمز الدخول المتبقية بالثواني. |
refresh_token |
رمز مميّز يمكنك استخدامه للحصول على رمز مميّز جديد للوصول تكون رموز إعادة التحميل صالحة إلى أن يبطل المستخدم إذن الوصول أو تنتهي صلاحية رمز إعادة التحميل.
مرة أخرى، لا يظهر هذا الحقل في الردّ إلا إذا ضبطت المَعلمة access_type على القيمة offline في الطلب الأوّلي إلى خادم التفويض من Google.
|
refresh_token_expires_in |
تعرض هذه السمة مدة صلاحية الرمز المميز لإعادة التحميل المتبقية بالثواني. لا يتم ضبط هذه القيمة إلا عندما يمنح المستخدم إذن الوصول المستند إلى الوقت. |
scope |
نطاقات الوصول التي يمنحها access_token معبَّر عنها كقائمة من السلاسل الحساسة لحالة الأحرف والمفصولة بمسافات. |
token_type |
تمثّل هذه السمة نوع الرمز المميّز الذي يتم عرضه. في الوقت الحالي، يتم دائمًا ضبط قيمة هذا الحقل على
Bearer . |
يعرض المقتطف التالي نموذجًا للردّ:
{ "access_token": "1/fFAGRNJru1FTz70BzhT3Zg", "expires_in": 3920, "token_type": "Bearer", "scope": "https://www.googleapis.com/auth/drive.metadata.readonly https://www.googleapis.com/auth/calendar.readonly", "refresh_token": "1//xEoDL4iW3cxlI7yDbSRFYNG01kVKM2C-259HOF2aQbI" }
الأخطاء
عند استبدال رمز التفويض برمز دخول، قد يظهر لك الخطأ التالي بدلاً من الاستجابة المتوقّعة. في ما يلي رموز الأخطاء الشائعة والحلول المقترَحة.
invalid_grant
رمز التفويض المقدَّم غير صالح أو بتنسيق غير صحيح. اطلب رمزًا جديدًا من خلال إعادة تشغيل عملية OAuth لطلب الموافقة من المستخدم مرة أخرى.
الخطوة 6: التحقّق من النطاقات التي منحها المستخدمون
عند طلب أذونات متعددة (نطاقات)، قد لا يمنح المستخدمون تطبيقك إذن الوصول إلى جميعها. يجب أن يتحقّق تطبيقك من النطاقات التي تم منحها فعليًا وأن يتعامل بشكل سليم مع الحالات التي يتم فيها رفض بعض الأذونات، وذلك عادةً عن طريق إيقاف الميزات التي تعتمد على تلك النطاقات المرفوضة.
ومع ذلك، هناك استثناءات. تتجاوز تطبيقات Google Workspace Enterprise التي تتضمّن تفويضًا على مستوى النطاق، أو التطبيقات التي تم وضع علامة موثوق به عليها، شاشة طلب الموافقة على الأذونات التفصيلية. بالنسبة إلى هذه التطبيقات، لن تظهر للمستخدمين شاشة الموافقة على الأذونات التفصيلية. بدلاً من ذلك، سيحصل تطبيقك على جميع النطاقات المطلوبة أو لن يحصل على أي منها.
لمزيد من المعلومات التفصيلية، يُرجى الاطّلاع على كيفية التعامل مع الأذونات الدقيقة.
PHP
للتحقّق من النطاقات التي منحها المستخدم، استخدِم طريقة getGrantedScope()
:
// Space-separated string of granted scopes if it exists, otherwise null. $granted_scopes = $client->getOAuth2Service()->getGrantedScope(); // Determine which scopes user granted and build a dictionary $granted_scopes_dict = [ 'Drive' => str_contains($granted_scopes, Google\Service\Drive::DRIVE_METADATA_READONLY), 'Calendar' => str_contains($granted_scopes, Google\Service\Calendar::CALENDAR_READONLY) ];
Python
يحتوي العنصر credentials
الذي يتم عرضه على السمة granted_scopes
، وهي قائمة بالنطاقات التي منحها المستخدم لتطبيقك.
credentials = flow.credentials flask.session['credentials'] = { 'token': credentials.token, 'refresh_token': credentials.refresh_token, 'token_uri': credentials.token_uri, 'client_id': credentials.client_id, 'client_secret': credentials.client_secret, 'granted_scopes': credentials.granted_scopes}
تتحقّق الدالة التالية من النطاقات التي منحها المستخدم لتطبيقك.
def check_granted_scopes(credentials): features = {} if 'https://www.googleapis.com/auth/drive.metadata.readonly' in credentials['granted_scopes']: features['drive'] = True else: features['drive'] = False if 'https://www.googleapis.com/auth/calendar.readonly' in credentials['granted_scopes']: features['calendar'] = True else: features['calendar'] = False return features
Ruby
عند طلب نطاقات متعددة في الوقت نفسه، تحقَّق من النطاقات التي تم منحها من خلال السمة scope
الخاصة بالكائن credentials
.
# User authorized the request. Now, check which scopes were granted. if credentials.scope.include?(Google::Apis::DriveV3::AUTH_DRIVE_METADATA_READONLY) # User authorized read-only Drive activity permission. # Calling the APIs, etc else # User didn't authorize read-only Drive activity permission. # Update UX and application accordingly end # Check if user authorized Calendar read permission. if credentials.scope.include?(Google::Apis::CalendarV3::AUTH_CALENDAR_READONLY) # User authorized Calendar read permission. # Calling the APIs, etc. else # User didn't authorize Calendar read permission. # Update UX and application accordingly end
Node.js
عند طلب نطاقات متعددة في الوقت نفسه، تحقَّق من النطاقات التي تم منحها من خلال السمة scope
الخاصة بالكائن tokens
.
// User authorized the request. Now, check which scopes were granted. if (tokens.scope.includes('https://www.googleapis.com/auth/drive.metadata.readonly')) { // User authorized read-only Drive activity permission. // Calling the APIs, etc. } else { // User didn't authorize read-only Drive activity permission. // Update UX and application accordingly } // Check if user authorized Calendar read permission. if (tokens.scope.includes('https://www.googleapis.com/auth/calendar.readonly')) { // User authorized Calendar read permission. // Calling the APIs, etc. } else { // User didn't authorize Calendar read permission. // Update UX and application accordingly }
HTTP/REST
للتحقّق مما إذا كان المستخدم قد منح تطبيقك إذن الوصول إلى نطاق معيّن،
افحص الحقل scope
في ردّ رمز الدخول. نطاقات الوصول التي يمنحها الرمز access_token، ويتم التعبير عنها كقائمة من السلاسل الحساسة لحالة الأحرف والمفصولة بمسافات
على سبيل المثال، يشير نموذج استجابة رمز الدخول التالي إلى أنّ المستخدم قد منح تطبيقك إذن الوصول إلى نشاط Drive وأحداث التقويم للقراءة فقط:
{ "access_token": "1/fFAGRNJru1FTz70BzhT3Zg", "expires_in": 3920, "token_type": "Bearer", "scope": "https://www.googleapis.com/auth/drive.metadata.readonly https://www.googleapis.com/auth/calendar.readonly", "refresh_token": "1//xEoDL4iW3cxlI7yDbSRFYNG01kVKM2C-259HOF2aQbI" }
طلب بيانات من Google APIs
PHP
استخدِم رمز الدخول لطلب بيانات من واجهات Google APIs من خلال إكمال الخطوات التالية:
- إذا كنت بحاجة إلى تطبيق رمز مميّز للوصول على عنصر
Google\Client
جديد، مثلاً إذا خزّنت رمز الوصول المميّز في جلسة مستخدم، استخدِم طريقةsetAccessToken
:$client->setAccessToken($access_token);
- أنشئ عنصر خدمة لواجهة برمجة التطبيقات التي تريد طلبها. يمكنك إنشاء عنصر خدمة من خلال توفير عنصر
Google\Client
معتمد إلى الدالة الإنشائية لواجهة برمجة التطبيقات التي تريد طلب بيانات منها. على سبيل المثال، لاستدعاء Drive API، اتّبِع الخطوات التالية:$drive = new Google\Service\Drive($client);
- إرسال طلبات إلى خدمة واجهة برمجة التطبيقات باستخدام
الواجهة التي يوفّرها عنصر الخدمة
على سبيل المثال، لإدراج الملفات في حساب Google Drive الخاص بالمستخدم الذي تمّت المصادقة عليه:
$files = $drive->files->listFiles(array());
Python
بعد الحصول على رمز دخول، يمكن لتطبيقك استخدام هذا الرمز لتفويض طلبات واجهة برمجة التطبيقات نيابةً عن حساب مستخدم أو حساب خدمة معيّن. استخدِم بيانات اعتماد التفويض الخاصة بالمستخدم لإنشاء عنصر خدمة لواجهة برمجة التطبيقات التي تريد طلب بيانات منها، ثم استخدِم هذا العنصر لتقديم طلبات بيانات معتمَدة من واجهة برمجة التطبيقات.
- أنشئ عنصر خدمة لواجهة برمجة التطبيقات التي تريد طلبها. يمكنك إنشاء عنصر خدمة من خلال استدعاء طريقة
build
في مكتبةgoogleapiclient.discovery
مع اسم واجهة برمجة التطبيقات وإصدارها وبيانات اعتماد المستخدم: على سبيل المثال، لاستدعاء الإصدار 3 من Drive API:from googleapiclient.discovery import build drive = build('drive', 'v2', credentials=credentials)
- إرسال طلبات إلى خدمة واجهة برمجة التطبيقات باستخدام
الواجهة التي يوفّرها عنصر الخدمة
على سبيل المثال، لإدراج الملفات في حساب Google Drive الخاص بالمستخدم الذي تمّت المصادقة عليه:
files = drive.files().list().execute()
Ruby
بعد الحصول على رمز دخول، يمكن لتطبيقك استخدام هذا الرمز لتقديم طلبات إلى واجهة برمجة التطبيقات نيابةً عن حساب مستخدم أو حساب خدمة معيّن. استخدِم بيانات اعتماد التفويض الخاصة بالمستخدم لإنشاء عنصر خدمة لواجهة برمجة التطبيقات التي تريد طلب بيانات منها، ثم استخدِم هذا العنصر لتقديم طلبات بيانات معتمَدة من واجهة برمجة التطبيقات.
- أنشئ عنصر خدمة لواجهة برمجة التطبيقات التي تريد طلبها.
على سبيل المثال، لاستدعاء الإصدار 3 من Drive API:
drive = Google::Apis::DriveV3::DriveService.new
- اضبط بيانات الاعتماد على الخدمة:
drive.authorization = credentials
- إرسال طلبات إلى خدمة واجهة برمجة التطبيقات باستخدام
الواجهة
التي يوفّرها عنصر الخدمة
على سبيل المثال، لإدراج الملفات في حساب Google Drive الخاص بالمستخدم الذي تمّت المصادقة عليه:
files = drive.list_files
بدلاً من ذلك، يمكن تقديم التفويض على أساس كل طريقة على حدة من خلال توفير المَعلمة options
لطريقة ما:
files = drive.list_files(options: { authorization: credentials })
Node.js
بعد الحصول على رمز مميّز للوصول وضبطه على العنصر OAuth2
، استخدِم العنصر
لطلب بيانات من Google APIs. يمكن لتطبيقك استخدام هذا الرمز لتفويض طلبات واجهة برمجة التطبيقات نيابةً عن حساب مستخدم أو حساب خدمة معيّن. أنشئ عنصر خدمة لواجهة برمجة التطبيقات التي تريد طلبها.
على سبيل المثال، يستخدم الرمز التالي Google Drive API لإدراج أسماء الملفات في حساب المستخدم على Drive.
const { google } = require('googleapis'); // 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) => { if (err1) return console.log('The API returned an error: ' + err1); const files = res1.data.files; if (files.length) { console.log('Files:'); files.map((file) => { console.log(`${file.name} (${file.id})`); }); } else { console.log('No files found.'); } });
HTTP/REST
بعد أن يحصل تطبيقك على رمز مميز للوصول، يمكنك استخدام الرمز المميز لإجراء طلبات إلى إحدى واجهات برمجة التطبيقات من Google نيابةً عن حساب مستخدم معيّن إذا تم منح نطاقات الوصول التي تتطلّبها واجهة برمجة التطبيقات. لإجراء ذلك، يجب تضمين رمز الدخول في طلب إلى واجهة برمجة التطبيقات من خلال تضمين مَعلمة طلب بحث access_token
أو قيمة Bearer
في عنوان HTTP Authorization
. عند الإمكان، من الأفضل استخدام عنوان HTTP لأنّ سلاسل طلب البحث تكون عادةً مرئية في سجلات الخادم. في معظم الحالات، يمكنك استخدام مكتبة برامج العميل لإعداد طلباتك إلى واجهات Google API (على سبيل المثال، عند طلب Drive Files API).
يمكنك تجربة جميع واجهات Google APIs والاطّلاع على نطاقاتها في مساحة بروتوكول 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
مثال كامل
يطبع المثال التالي قائمة بالملفات بتنسيق JSON في Google Drive الخاص بالمستخدم بعد أن يصادق المستخدم على التطبيق ويمنحه الموافقة على الوصول إلى البيانات الوصفية الخاصة به في Drive.
PHP
لتشغيل هذا المثال:
- في API Console، أضِف عنوان URL الخاص بالجهاز المحلي إلى قائمة عناوين URL لإعادة التوجيه، مثلاً، أضِف
http://localhost:8080
. - أنشئ دليلاً جديدًا وانتقِل إليه. على سبيل المثال:
mkdir ~/php-oauth2-example cd ~/php-oauth2-example
- ثبِّت مكتبة برامج Google API للغة PHP باستخدام Composer:
composer require google/apiclient:^2.15.0
- أنشئ الملفَين
index.php
وoauth2callback.php
بالمحتوى التالي. - شغِّل المثال باستخدام خادم الويب المدمج للاختبار في PHP:
php -S localhost:8080 ~/php-oauth2-example
index.php
<?php require_once __DIR__.'/vendor/autoload.php'; session_start(); $client = new Google\Client(); $client->setAuthConfig('client_secret.json'); // User granted permission as an access token is in the session. if (isset($_SESSION['access_token']) && $_SESSION['access_token']) { $client->setAccessToken($_SESSION['access_token']); // Check if user granted Drive permission if ($_SESSION['granted_scopes_dict']['Drive']) { echo "Drive feature is enabled."; echo "</br>"; $drive = new Drive($client); $files = array(); $response = $drive->files->listFiles(array()); foreach ($response->files as $file) { echo "File: " . $file->name . " (" . $file->id . ")"; echo "</br>"; } } else { echo "Drive feature is NOT enabled."; echo "</br>"; } // Check if user granted Calendar permission if ($_SESSION['granted_scopes_dict']['Calendar']) { echo "Calendar feature is enabled."; echo "</br>"; } else { echo "Calendar feature is NOT enabled."; echo "</br>"; } } else { // Redirect users to outh2call.php which redirects users to Google OAuth 2.0 $redirect_uri = 'http://' . $_SERVER['HTTP_HOST'] . '/oauth2callback.php'; header('Location: ' . filter_var($redirect_uri, FILTER_SANITIZE_URL)); } ?>
oauth2callback.php
<?php require_once __DIR__.'/vendor/autoload.php'; session_start(); $client = new Google\Client(); // Required, call the setAuthConfig function to load authorization credentials from // client_secret.json file. $client->setAuthConfigFile('client_secret.json'); $client->setRedirectUri('http://' . $_SERVER['HTTP_HOST']. $_SERVER['PHP_SELF']); // Required, to set the scope value, call the addScope function. $client->addScope([Google\Service\Drive::DRIVE_METADATA_READONLY, Google\Service\Calendar::CALENDAR_READONLY]); // Enable incremental authorization. Recommended as a best practice. $client->setIncludeGrantedScopes(true); // Recommended, offline access will give you both an access and refresh token so that // your app can refresh the access token without user interaction. $client->setAccessType("offline"); // Generate a URL for authorization as it doesn't contain code and error if (!isset($_GET['code']) && !isset($_GET['error'])) { // Generate and set state value $state = bin2hex(random_bytes(16)); $client->setState($state); $_SESSION['state'] = $state; // Generate a url that asks permissions. $auth_url = $client->createAuthUrl(); header('Location: ' . filter_var($auth_url, FILTER_SANITIZE_URL)); } // User authorized the request and authorization code is returned to exchange access and // refresh tokens. if (isset($_GET['code'])) { // Check the state value if (!isset($_GET['state']) || $_GET['state'] !== $_SESSION['state']) { die('State mismatch. Possible CSRF attack.'); } // Get access and refresh tokens (if access_type is offline) $token = $client->fetchAccessTokenWithAuthCode($_GET['code']); /** Save access and refresh token to the session variables. * ACTION ITEM: In a production app, you likely want to save the * refresh token in a secure persistent storage instead. */ $_SESSION['access_token'] = $token; $_SESSION['refresh_token'] = $client->getRefreshToken(); // Space-separated string of granted scopes if it exists, otherwise null. $granted_scopes = $client->getOAuth2Service()->getGrantedScope(); // Determine which scopes user granted and build a dictionary $granted_scopes_dict = [ 'Drive' => str_contains($granted_scopes, Google\Service\Drive::DRIVE_METADATA_READONLY), 'Calendar' => str_contains($granted_scopes, Google\Service\Calendar::CALENDAR_READONLY) ]; $_SESSION['granted_scopes_dict'] = $granted_scopes_dict; $redirect_uri = 'http://' . $_SERVER['HTTP_HOST'] . '/'; header('Location: ' . filter_var($redirect_uri, FILTER_SANITIZE_URL)); } // An error response e.g. error=access_denied if (isset($_GET['error'])) { echo "Error: ". $_GET['error']; } ?>
Python
يستخدم هذا المثال إطار عمل Flask. ويشغّل تطبيق ويب على http://localhost:8080
يتيح لك اختبار مسار OAuth 2.0. إذا انتقلت إلى عنوان URL هذا، من المفترض أن تظهر لك خمسة روابط:
- طلب بيانات من Drive API: يشير هذا الرابط إلى صفحة تحاول تنفيذ نموذج لطلب بيانات من واجهة برمجة التطبيقات إذا منح المستخدمون الإذن بذلك. يبدأ مسار التفويض إذا لزم الأمر. في حال نجاح ذلك، ستعرض الصفحة استجابة واجهة برمجة التطبيقات.
- صفحة تجريبية لطلب بيانات من Calendar API: يشير هذا الرابط إلى صفحة تجريبية تحاول تنفيذ طلب بيانات نموذجي من Calendar API إذا منح المستخدمون الإذن بذلك. إذا لزم الأمر، يبدأ مسار التفويض. في حال نجاح ذلك، ستعرض الصفحة استجابة واجهة برمجة التطبيقات.
- اختبار مسار المصادقة مباشرةً: يشير هذا الرابط إلى صفحة تحاول توجيه المستخدم خلال مسار المصادقة. يطلب التطبيق الإذن بتقديم طلبات إلى واجهة برمجة التطبيقات نيابةً عن المستخدم.
- إبطال بيانات الاعتماد الحالية: يشير هذا الرابط إلى صفحة تبطل الأذونات التي سبق أن منحها المستخدم للتطبيق.
- محو بيانات اعتماد جلسة Flask: يؤدي هذا الرابط إلى محو بيانات اعتماد التفويض المخزّنة في جلسة Flask. يتيح لك ذلك معرفة ما سيحدث إذا حاول مستخدم سبق له منح الإذن لتطبيقك تنفيذ طلب واجهة برمجة تطبيقات في جلسة جديدة. تتيح لك هذه الأداة أيضًا الاطّلاع على استجابة واجهة برمجة التطبيقات التي سيحصل عليها تطبيقك إذا ألغى المستخدم الأذونات الممنوحة لتطبيقك، وحاول تطبيقك مع ذلك تفويض طلب باستخدام رمز دخول تم إبطاله.
# -*- coding: utf-8 -*- import os import flask import requests import google.oauth2.credentials import google_auth_oauthlib.flow import googleapiclient.discovery # This variable specifies the name of a file that contains the OAuth 2.0 # information for this application, including its client_id and client_secret. CLIENT_SECRETS_FILE = "client_secret.json" # The OAuth 2.0 access scope allows for access to the # authenticated user's account and requires requests to use an SSL connection. SCOPES = ['https://www.googleapis.com/auth/drive.metadata.readonly', 'https://www.googleapis.com/auth/calendar.readonly'] API_SERVICE_NAME = 'drive' API_VERSION = 'v2' app = flask.Flask(__name__) # Note: A secret key is included in the sample so that it works. # If you use this code in your application, replace this with a truly secret # key. See https://flask.palletsprojects.com/quickstart/#sessions. app.secret_key = 'REPLACE ME - this value is here as a placeholder.' @app.route('/') def index(): return print_index_table() @app.route('/drive') def drive_api_request(): if 'credentials' not in flask.session: return flask.redirect('authorize') features = flask.session['features'] if features['drive']: # Load credentials from the session. credentials = google.oauth2.credentials.Credentials( **flask.session['credentials']) drive = googleapiclient.discovery.build( API_SERVICE_NAME, API_VERSION, credentials=credentials) files = drive.files().list().execute() # Save credentials back to session in case access token was refreshed. # ACTION ITEM: In a production app, you likely want to save these # credentials in a persistent database instead. flask.session['credentials'] = credentials_to_dict(credentials) return flask.jsonify(**files) else: # User didn't authorize read-only Drive activity permission. # Update UX and application accordingly return '<p>Drive feature is not enabled.</p>' @app.route('/calendar') def calendar_api_request(): if 'credentials' not in flask.session: return flask.redirect('authorize') features = flask.session['features'] if features['calendar']: # User authorized Calendar read permission. # Calling the APIs, etc. return ('<p>User granted the Google Calendar read permission. '+ 'This sample code does not include code to call Calendar</p>') else: # User didn't authorize Calendar read permission. # Update UX and application accordingly return '<p>Calendar feature is not enabled.</p>' @app.route('/authorize') def authorize(): # Create flow instance to manage the OAuth 2.0 Authorization Grant Flow steps. flow = google_auth_oauthlib.flow.Flow.from_client_secrets_file( CLIENT_SECRETS_FILE, scopes=SCOPES) # The URI created here must exactly match one of the authorized redirect URIs # for the OAuth 2.0 client, which you configured in the API Console. If this # value doesn't match an authorized URI, you will get a 'redirect_uri_mismatch' # error. flow.redirect_uri = flask.url_for('oauth2callback', _external=True) authorization_url, state = flow.authorization_url( # Enable offline access so that you can refresh an access token without # re-prompting the user for permission. Recommended for web server apps. access_type='offline', # Enable incremental authorization. Recommended as a best practice. include_granted_scopes='true') # Store the state so the callback can verify the auth server response. flask.session['state'] = state return flask.redirect(authorization_url) @app.route('/oauth2callback') def oauth2callback(): # Specify the state when creating the flow in the callback so that it can # verified in the authorization server response. state = flask.session['state'] flow = google_auth_oauthlib.flow.Flow.from_client_secrets_file( CLIENT_SECRETS_FILE, scopes=SCOPES, state=state) flow.redirect_uri = flask.url_for('oauth2callback', _external=True) # Use the authorization server's response to fetch the OAuth 2.0 tokens. authorization_response = flask.request.url flow.fetch_token(authorization_response=authorization_response) # Store credentials in the session. # ACTION ITEM: In a production app, you likely want to save these # credentials in a persistent database instead. credentials = flow.credentials credentials = credentials_to_dict(credentials) flask.session['credentials'] = credentials # Check which scopes user granted features = check_granted_scopes(credentials) flask.session['features'] = features return flask.redirect('/') @app.route('/revoke') def revoke(): if 'credentials' not in flask.session: return ('You need to <a href="/authorize">authorize</a> before ' + 'testing the code to revoke credentials.') credentials = google.oauth2.credentials.Credentials( **flask.session['credentials']) revoke = requests.post('https://oauth2.googleapis.com/revoke', params={'token': credentials.token}, headers = {'content-type': 'application/x-www-form-urlencoded'}) status_code = getattr(revoke, 'status_code') if status_code == 200: return('Credentials successfully revoked.' + print_index_table()) else: return('An error occurred.' + print_index_table()) @app.route('/clear') def clear_credentials(): if 'credentials' in flask.session: del flask.session['credentials'] return ('Credentials have been cleared.<br><br>' + print_index_table()) def credentials_to_dict(credentials): return {'token': credentials.token, 'refresh_token': credentials.refresh_token, 'token_uri': credentials.token_uri, 'client_id': credentials.client_id, 'client_secret': credentials.client_secret, 'granted_scopes': credentials.granted_scopes} def check_granted_scopes(credentials): features = {} if 'https://www.googleapis.com/auth/drive.metadata.readonly' in credentials['granted_scopes']: features['drive'] = True else: features['drive'] = False if 'https://www.googleapis.com/auth/calendar.readonly' in credentials['granted_scopes']: features['calendar'] = True else: features['calendar'] = False return features def print_index_table(): return ('<table>' + '<tr><td><a href="/test">Test an API request</a></td>' + '<td>Submit an API request and see a formatted JSON response. ' + ' Go through the authorization flow if there are no stored ' + ' credentials for the user.</td></tr>' + '<tr><td><a href="/authorize">Test the auth flow directly</a></td>' + '<td>Go directly to the authorization flow. If there are stored ' + ' credentials, you still might not be prompted to reauthorize ' + ' the application.</td></tr>' + '<tr><td><a href="/revoke">Revoke current credentials</a></td>' + '<td>Revoke the access token associated with the current user ' + ' session. After revoking credentials, if you go to the test ' + ' page, you should see an <code>invalid_grant</code> error.' + '</td></tr>' + '<tr><td><a href="/clear">Clear Flask session credentials</a></td>' + '<td>Clear the access token currently stored in the user session. ' + ' After clearing the token, if you <a href="/test">test the ' + ' API request</a> again, you should go back to the auth flow.' + '</td></tr></table>') if __name__ == '__main__': # When running locally, disable OAuthlib's HTTPs verification. # ACTION ITEM for developers: # When running in production *do not* leave this option enabled. os.environ['OAUTHLIB_INSECURE_TRANSPORT'] = '1' # This disables the requested scopes and granted scopes check. # If users only grant partial request, the warning would not be thrown. os.environ['OAUTHLIB_RELAX_TOKEN_SCOPE'] = '1' # Specify a hostname and port that are set as a valid redirect URI # for your API project in the Google API Console. app.run('localhost', 8080, debug=True)
Ruby
يستخدم هذا المثال إطار عمل Sinatra.
require 'googleauth' require 'googleauth/web_user_authorizer' require 'googleauth/stores/redis_token_store' require 'google/apis/drive_v3' require 'google/apis/calendar_v3' require 'sinatra' configure do enable :sessions # Required, call the from_file method to retrieve the client ID from a # client_secret.json file. set :client_id, Google::Auth::ClientId.from_file('/path/to/client_secret.json') # Required, scope value # Access scopes for two non-Sign-In scopes: Read-only Drive activity and Google Calendar. scope = ['Google::Apis::DriveV3::AUTH_DRIVE_METADATA_READONLY', 'Google::Apis::CalendarV3::AUTH_CALENDAR_READONLY'] # Required, Authorizers require a storage instance to manage long term persistence of # access and refresh tokens. set :token_store, Google::Auth::Stores::RedisTokenStore.new(redis: Redis.new) # Required, indicate where the API server will redirect the user after the user completes # the authorization flow. The redirect URI is required. The value must exactly # match one of the authorized redirect URIs for the OAuth 2.0 client, which you # configured in the API Console. If this value doesn't match an authorized URI, # you will get a 'redirect_uri_mismatch' error. set :callback_uri, '/oauth2callback' # To use OAuth2 authentication, we need access to a CLIENT_ID, CLIENT_SECRET, AND REDIRECT_URI # from the client_secret.json file. To get these credentials for your application, visit # https://console.cloud.google.com/apis/credentials. set :authorizer, Google::Auth::WebUserAuthorizer.new(settings.client_id, settings.scope, settings.token_store, callback_uri: settings.callback_uri) end get '/' do # NOTE: Assumes the user is already authenticated to the app user_id = request.session['user_id'] # Fetch stored credentials for the user from the given request session. # nil if none present credentials = settings.authorizer.get_credentials(user_id, request) if credentials.nil? # Generate a url that asks the user to authorize requested scope(s). # Then, redirect user to the url. redirect settings.authorizer.get_authorization_url(request: request) end # User authorized the request. Now, check which scopes were granted. if credentials.scope.include?(Google::Apis::DriveV3::AUTH_DRIVE_METADATA_READONLY) # User authorized read-only Drive activity permission. # Example of using Google Drive API to list filenames in user's Drive. drive = Google::Apis::DriveV3::DriveService.new files = drive.list_files(options: { authorization: credentials }) "<pre>#{JSON.pretty_generate(files.to_h)}</pre>" else # User didn't authorize read-only Drive activity permission. # Update UX and application accordingly end # Check if user authorized Calendar read permission. if credentials.scope.include?(Google::Apis::CalendarV3::AUTH_CALENDAR_READONLY) # User authorized Calendar read permission. # Calling the APIs, etc. else # User didn't authorize Calendar read permission. # Update UX and application accordingly end end # Receive the callback from Google's OAuth 2.0 server. get '/oauth2callback' do # Handle the result of the oauth callback. Defers the exchange of the code by # temporarily stashing the results in the user's session. target_url = Google::Auth::WebUserAuthorizer.handle_auth_callback_deferred(request) redirect target_url end
Node.js
لتشغيل هذا المثال:
-
في API Console، أضِف عنوان URL الخاص بالجهاز المحلي إلى قائمة عناوين URL لإعادة التوجيه. على سبيل المثال، أضِف
http://localhost
. - تأكَّد من تثبيت إصدار LTS للصيانة أو إصدار LTS نشط أو الإصدار الحالي من Node.js.
-
أنشئ دليلاً جديدًا وانتقِل إليه. على سبيل المثال:
mkdir ~/nodejs-oauth2-example cd ~/nodejs-oauth2-example
-
ثبِّت
مكتبة برامج Google API Client
لنظام التشغيل Node.js باستخدام npm:
npm install googleapis
-
أنشئ الملفات
main.js
التي تتضمّن المحتوى التالي. -
شغِّل المثال:
node .\main.js
main.js
const http = require('http'); const https = require('https'); const url = require('url'); const { google } = require('googleapis'); const crypto = require('crypto'); const express = require('express'); const session = require('express-session'); /** * To use OAuth2 authentication, we need access to a CLIENT_ID, CLIENT_SECRET, AND REDIRECT_URI. * To get these credentials for your application, visit * https://console.cloud.google.com/apis/credentials. */ const oauth2Client = new google.auth.OAuth2( YOUR_CLIENT_ID, YOUR_CLIENT_SECRET, YOUR_REDIRECT_URL ); // Access scopes for two non-Sign-In scopes: Read-only Drive activity and Google Calendar. const scopes = [ 'https://www.googleapis.com/auth/drive.metadata.readonly', 'https://www.googleapis.com/auth/calendar.readonly' ]; /* Global variable that stores user credential in this code example. * ACTION ITEM for developers: * Store user's refresh token in your data store if * incorporating this code into your real app. * For more information on handling refresh tokens, * see https://github.com/googleapis/google-api-nodejs-client#handling-refresh-tokens */ let userCredential = null; async function main() { const app = express(); app.use(session({ secret: 'your_secure_secret_key', // Replace with a strong secret resave: false, saveUninitialized: false, })); // Example on redirecting user to Google's OAuth 2.0 server. app.get('/', async (req, res) => { // Generate a secure random state value. const state = crypto.randomBytes(32).toString('hex'); // Store state in the session req.session.state = state; // Generate a url that asks permissions for the Drive activity and Google Calendar scope const authorizationUrl = oauth2Client.generateAuthUrl({ // 'online' (default) or 'offline' (gets refresh_token) access_type: 'offline', /** Pass in the scopes array defined above. * Alternatively, if only one scope is needed, you can pass a scope URL as a string */ scope: scopes, // Enable incremental authorization. Recommended as a best practice. include_granted_scopes: true, // Include the state parameter to reduce the risk of CSRF attacks. state: state }); res.redirect(authorizationUrl); }); // Receive the callback from Google's OAuth 2.0 server. app.get('/oauth2callback', async (req, res) => { // Handle the OAuth 2.0 server response let q = url.parse(req.url, true).query; if (q.error) { // An error response e.g. error=access_denied console.log('Error:' + q.error); } else if (q.state !== req.session.state) { //check state value console.log('State mismatch. Possible CSRF attack'); res.end('State mismatch. Possible CSRF attack'); } else { // Get access and refresh tokens (if access_type is offline) let { tokens } = await oauth2Client.getToken(q.code); oauth2Client.setCredentials(tokens); /** Save credential to the global variable in case access token was refreshed. * ACTION ITEM: In a production app, you likely want to save the refresh token * in a secure persistent database instead. */ userCredential = tokens; // User authorized the request. Now, check which scopes were granted. if (tokens.scope.includes('https://www.googleapis.com/auth/drive.metadata.readonly')) { // User authorized read-only Drive activity permission. // 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) => { if (err1) return console.log('The API returned an error: ' + err1); const files = res1.data.files; if (files.length) { console.log('Files:'); files.map((file) => { console.log(`${file.name} (${file.id})`); }); } else { console.log('No files found.'); } }); } else { // User didn't authorize read-only Drive activity permission. // Update UX and application accordingly } // Check if user authorized Calendar read permission. if (tokens.scope.includes('https://www.googleapis.com/auth/calendar.readonly')) { // User authorized Calendar read permission. // Calling the APIs, etc. } else { // User didn't authorize Calendar read permission. // Update UX and application accordingly } } }); // Example on revoking a token app.get('/revoke', async (req, res) => { // Build the string for the POST request let postData = "token=" + userCredential.access_token; // Options for POST request to Google's OAuth 2.0 server to revoke a token let postOptions = { host: 'oauth2.googleapis.com', port: '443', path: '/revoke', method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded', 'Content-Length': Buffer.byteLength(postData) } }; // Set up the request const postReq = https.request(postOptions, function (res) { res.setEncoding('utf8'); res.on('data', d => { console.log('Response: ' + d); }); }); postReq.on('error', error => { console.log(error) }); // Post the request with data postReq.write(postData); postReq.end(); }); const server = http.createServer(app); server.listen(8080); } main().catch(console.error);
HTTP/REST
يستخدم مثال Python هذا إطار عمل Flask ومكتبة Requests لتوضيح مسار الويب الخاص ببروتوكول OAuth 2.0. ننصحك باستخدام Google API Client Library للغة Python لتنفيذ هذا الإجراء. (يستخدم المثال في علامة التبويب Python مكتبة البرامج).
import json import flask import requests app = flask.Flask(__name__) # To get these credentials (CLIENT_ID CLIENT_SECRET) and for your application, visit # https://console.cloud.google.com/apis/credentials. CLIENT_ID = '123456789.apps.googleusercontent.com' CLIENT_SECRET = 'abc123' # Read from a file or environmental variable in a real app # Access scopes for two non-Sign-In scopes: Read-only Drive activity and Google Calendar. SCOPE = 'https://www.googleapis.com/auth/drive.metadata.readonly https://www.googleapis.com/auth/calendar.readonly' # Indicate where the API server will redirect the user after the user completes # the authorization flow. The redirect URI is required. The value must exactly # match one of the authorized redirect URIs for the OAuth 2.0 client, which you # configured in the API Console. If this value doesn't match an authorized URI, # you will get a 'redirect_uri_mismatch' error. REDIRECT_URI = 'http://example.com/oauth2callback' @app.route('/') def index(): if 'credentials' not in flask.session: return flask.redirect(flask.url_for('oauth2callback')) credentials = json.loads(flask.session['credentials']) if credentials['expires_in'] <= 0: return flask.redirect(flask.url_for('oauth2callback')) else: # User authorized the request. Now, check which scopes were granted. if 'https://www.googleapis.com/auth/drive.metadata.readonly' in credentials['scope']: # User authorized read-only Drive activity permission. # Example of using Google Drive API to list filenames in user's Drive. headers = {'Authorization': 'Bearer {}'.format(credentials['access_token'])} req_uri = 'https://www.googleapis.com/drive/v2/files' r = requests.get(req_uri, headers=headers).text else: # User didn't authorize read-only Drive activity permission. # Update UX and application accordingly r = 'User did not authorize Drive permission.' # Check if user authorized Calendar read permission. if 'https://www.googleapis.com/auth/calendar.readonly' in credentials['scope']: # User authorized Calendar read permission. # Calling the APIs, etc. r += 'User authorized Calendar permission.' else: # User didn't authorize Calendar read permission. # Update UX and application accordingly r += 'User did not authorize Calendar permission.' return r @app.route('/oauth2callback') def oauth2callback(): if 'code' not in flask.request.args: state = str(uuid.uuid4()) flask.session['state'] = state # Generate a url that asks permissions for the Drive activity # and Google Calendar scope. Then, redirect user to the url. auth_uri = ('https://accounts.google.com/o/oauth2/v2/auth?response_type=code' '&client_id={}&redirect_uri={}&scope={}&state={}').format(CLIENT_ID, REDIRECT_URI, SCOPE, state) return flask.redirect(auth_uri) else: if 'state' not in flask.request.args or flask.request.args['state'] != flask.session['state']: return 'State mismatch. Possible CSRF attack.', 400 auth_code = flask.request.args.get('code') data = {'code': auth_code, 'client_id': CLIENT_ID, 'client_secret': CLIENT_SECRET, 'redirect_uri': REDIRECT_URI, 'grant_type': 'authorization_code'} # Exchange authorization code for access and refresh tokens (if access_type is offline) r = requests.post('https://oauth2.googleapis.com/token', data=data) flask.session['credentials'] = r.text return flask.redirect(flask.url_for('index')) if __name__ == '__main__': import uuid app.secret_key = str(uuid.uuid4()) app.debug = False app.run()
قواعد التحقّق من صحة معرّف الموارد المنتظم (URI) الخاص بإعادة التوجيه
تطبِّق Google قواعد التحقّق التالية على عناوين URI لإعادة التوجيه لمساعدة المطوّرين في الحفاظ على أمان تطبيقاتهم. يجب أن تلتزم معرّفات الموارد الموحّدة لإعادة التوجيه بالقواعد التالية. راجِع القسم 3 من RFC 3986 للتعرّف على تعريفات النطاق والمضيف والمسار والاستعلام والمخطط وuserinfo المذكورة أدناه.
قواعد التحقّق من الصحة | |
---|---|
المخطط |
يجب أن تستخدم معرّفات الموارد المنتظمة (URI) لإعادة التوجيه مخطط HTTPS، وليس HTTP العادي. يُستثنى من هذه القاعدة معرّفات الموارد المنتظمة (URI) الخاصة بالمضيف المحلي (بما في ذلك معرّفات الموارد المنتظمة (URI) الخاصة بعنوان IP الخاص بالمضيف المحلي). |
المضيف |
لا يمكن أن تكون المضيفات عناوين IP أولية. يتم استثناء عناوين IP الخاصة بالمضيف المحلي من هذه القاعدة. |
النطاق |
“googleusercontent.com” .goo.gl ) ما لم يكن التطبيق يملك النطاق. بالإضافة إلى ذلك، إذا اختار تطبيق يملك نطاقًا مختصرًا إعادة التوجيه إلى هذا النطاق، يجب أن يحتوي معرّف الموارد المنتظم لإعادة التوجيه على “/google-callback/” في مساره أو ينتهي بـ “/google-callback” . |
Userinfo |
لا يمكن أن تحتوي معرّفات الموارد المنتظمة لإعادة التوجيه على المكوّن الفرعي userinfo. |
المسار |
يجب ألا تحتوي معرّفات URI لإعادة التوجيه على ثغرة path traversal (تُعرف أيضًا باسم directory backtracking)،
والتي يمثّلها الرمز |
طلب بحث |
لا يمكن أن تحتوي معرّفات الموارد المنتظمة (URI) لإعادة التوجيه على عمليات إعادة توجيه مفتوحة. |
الجزء |
لا يمكن أن تحتوي معرّفات URI لإعادة التوجيه على مكوّن الجزء. |
الشخصيات |
لا يمكن أن تحتوي معرّفات URI لإعادة التوجيه على أحرف معيّنة، بما في ذلك:
|
تفويض تدريجي
في بروتوكول OAuth 2.0، يطلب تطبيقك الحصول على إذن بالوصول إلى الموارد التي يتم تحديدها من خلال النطاقات. يُعدّ طلب الحصول على إذن بالوصول إلى الموارد في الوقت الذي تحتاجها فيه من أفضل ممارسات تجربة المستخدم. ولتفعيل هذه الممارسة، يتيح خادم التفويض من Google التفويض التدريجي. تتيح لك هذه الميزة طلب النطاقات حسب الحاجة، وإذا منح المستخدم الإذن بالنطاق الجديد، سيتم عرض رمز تفويض يمكن استبداله برمز مميز يتضمّن جميع النطاقات التي منحها المستخدم للمشروع.
على سبيل المثال، قد يحتاج تطبيق يتيح للمستخدمين الاستماع إلى عيّنات من المقاطع الموسيقية وإنشاء مزيج منها إلى عدد قليل جدًا من الموارد عند تسجيل الدخول، ربما لا يحتاج إلى أكثر من اسم المستخدم الذي يسجّل الدخول. ومع ذلك، يتطلّب حفظ أغنية معدَّلة مكتملة الوصول إلى حساب Google Drive. سيبدو الأمر طبيعيًا لمعظم المستخدمين إذا طُلب منهم منح التطبيق إذن الوصول إلى Google Drive فقط عندما يحتاج التطبيق إلى ذلك.
في هذه الحالة، قد يطلب التطبيق النطاقَين openid
وprofile
عند تسجيل الدخول لإجراء عملية تسجيل الدخول الأساسية، ثم يطلب النطاق https://www.googleapis.com/auth/drive.file
لاحقًا عند إجراء الطلب الأول لحفظ أغنية مختلطة.
لتنفيذ التفويض التدريجي، عليك إكمال المسار العادي لطلب رمز مميز للوصول، ولكن تأكَّد من أنّ طلب التفويض يتضمّن النطاقات التي تم منحها سابقًا. تتيح هذه الطريقة لتطبيقك تجنُّب الحاجة إلى إدارة رموز وصول متعددة.
تنطبق القواعد التالية على رمز الدخول الذي تم الحصول عليه من تفويض تدريجي:
- يمكن استخدام الرمز المميز للوصول إلى الموارد التي تتوافق مع أي من النطاقات المضمّنة في التفويض الجديد المدمج.
- عند استخدام الرمز المميز لإعادة التحميل للحصول على رمز دخول من خلال التفويض المجمّع، يمثّل رمز الدخول التفويض المجمّع ويمكن استخدامه لأي من قيم
scope
المضمّنة في الرد. - يتضمّن التفويض المجمّع جميع النطاقات التي منحها المستخدم لمشروع واجهة برمجة التطبيقات، حتى إذا تم طلب منحها من برامج عملاء مختلفة. على سبيل المثال، إذا منح مستخدم إذن الوصول إلى نطاق واحد باستخدام برنامج تطبيق على الكمبيوتر المكتبي، ثم منح نطاقًا آخر للتطبيق نفسه من خلال برنامج تطبيق على الجهاز الجوّال، سيشمل التفويض المجمّع كلا النطاقين.
- في حال إبطال رمز مميّز يمثّل تفويضًا مجمّعًا، سيتم إبطال إذن الوصول إلى جميع نطاقات هذا التفويض نيابةً عن المستخدم المرتبط به في الوقت نفسه.
تستخدم جميع نماذج الرموز الخاصة باللغة في الخطوة 1: ضبط مَعلمات التفويض وعيّنة عنوان URL لإعادة التوجيه HTTP/REST في الخطوة 2: إعادة التوجيه إلى خادم OAuth 2.0 من Google التفويض التزايدي. توضّح نماذج الرموز البرمجية أدناه أيضًا الرمز الذي عليك إضافته لاستخدام التفويض المتزايد.
PHP
$client->setIncludeGrantedScopes(true);
Python
في Python، اضبط وسيط الكلمة الرئيسية include_granted_scopes
على true
للتأكّد من أنّ طلب التفويض يتضمّن النطاقات التي تم منحها سابقًا. من المحتمل جدًا ألا تكون
include_granted_scopes
هي وسيط الكلمة الرئيسية الوحيد الذي تحدّده، كما
هو موضّح في المثال أدناه.
authorization_url, state = flow.authorization_url( # Enable offline access so that you can refresh an access token without # re-prompting the user for permission. Recommended for web server apps. access_type='offline', # Enable incremental authorization. Recommended as a best practice. include_granted_scopes='true')
Ruby
auth_client.update!( :additional_parameters => {"include_granted_scopes" => "true"} )
Node.js
const authorizationUrl = oauth2Client.generateAuthUrl({ // 'online' (default) or 'offline' (gets refresh_token) access_type: 'offline', /** Pass in the scopes array defined above. * Alternatively, if only one scope is needed, you can pass a scope URL as a string */ scope: scopes, // Enable incremental authorization. Recommended as a best practice. include_granted_scopes: true });
HTTP/REST
GET https://accounts.google.com/o/oauth2/v2/auth? client_id=your_client_id& response_type=code& state=state_parameter_passthrough_value& scope=https%3A//www.googleapis.com/auth/drive.metadata.readonly%20https%3A//www.googleapis.com/auth/calendar.readonly& redirect_uri=https%3A//oauth2.example.com/code& prompt=consent& include_granted_scopes=true
إعادة تحميل رمز الدخول (الوصول بدون اتصال بالإنترنت)
تنتهي صلاحية رموز الدخول بشكل دوري وتصبح بيانات اعتماد غير صالحة لطلب بيانات من واجهة برمجة التطبيقات ذات الصلة. يمكنك إعادة تحميل رمز الدخول بدون مطالبة المستخدم بالحصول على إذن (حتى عندما لا يكون المستخدم متوفّرًا) إذا طلبت الوصول بلا إنترنت إلى النطاقات المرتبطة بالرمز.
- في حال استخدام إحدى مكتبات عميل Google API، يعيد كائن العميل تحديث رمز الدخول حسب الحاجة طالما أنّك ضبطت هذا الكائن على إمكانية الوصول بلا إنترنت.
- إذا كنت لا تستخدم مكتبة برامج للعملاء، عليك ضبط مَعلمة طلب البحث
access_type
HTTP علىoffline
عند إعادة توجيه المستخدم إلى خادم OAuth 2.0 من Google. في هذه الحالة، يعرض خادم التفويض من Google رمزًا مميزًا لإعادة التحميل عند تبديل رمز التفويض برمز دخول. بعد ذلك، إذا انتهت صلاحية رمز الدخول (أو في أي وقت آخر)، يمكنك استخدام رمز مميّز لإعادة التحميل للحصول على رمز دخول جديد.
يُعدّ طلب الوصول بلا إنترنت شرطًا أساسيًا لأي تطبيق يحتاج إلى الوصول إلى واجهة Google API عندما لا يكون المستخدم متوفّرًا. على سبيل المثال، يجب أن يتمكّن تطبيق يقدّم خدمات احتياطية أو ينفّذ إجراءات في أوقات محدّدة مسبقًا من إعادة تحميل رمز الدخول عندما لا يكون المستخدم متواجدًا. يُطلق على النمط التلقائي للوصول اسم online
.
تحصل تطبيقات الويب من جهة الخادم والتطبيقات المثبَّتة والأجهزة على رموز مميزة لإعادة التحميل أثناء عملية التفويض. لا تُستخدم رموز التحديث عادةً في تطبيقات الويب التي تعمل من جهة العميل (JavaScript).
PHP
إذا كان تطبيقك يحتاج إلى الوصول إلى إحدى واجهات Google API بدون اتصال بالإنترنت، اضبط نوع الوصول إلى عميل واجهة برمجة التطبيقات على offline
:
$client->setAccessType("offline");
بعد أن يمنح المستخدم إذن الوصول بلا إنترنت إلى النطاقات المطلوبة، يمكنك مواصلة استخدام برنامج واجهة برمجة التطبيقات للوصول إلى Google APIs بالنيابة عن المستخدم عندما يكون غير متصل بالإنترنت. سيُعيد عنصر العميل تحميل رمز الدخول المميز حسب الحاجة.
Python
في لغة Python، اضبط وسيطة الكلمة الرئيسية access_type
على offline
لضمان إمكانية إعادة تحميل رمز الدخول بدون الحاجة إلى إعادة طلب الإذن من المستخدم. من المحتمل جدًا ألا تكون access_type
هي وسيطة الكلمة الرئيسية الوحيدة التي تحدّدها، كما هو موضّح في المثال أدناه.
authorization_url, state = flow.authorization_url( # Enable offline access so that you can refresh an access token without # re-prompting the user for permission. Recommended for web server apps. access_type='offline', # Enable incremental authorization. Recommended as a best practice. include_granted_scopes='true')
بعد أن يمنح المستخدم إذن الوصول بلا إنترنت إلى النطاقات المطلوبة، يمكنك مواصلة استخدام برنامج واجهة برمجة التطبيقات للوصول إلى Google APIs بالنيابة عن المستخدم عندما يكون غير متصل بالإنترنت. سيُعيد عنصر العميل تحميل رمز الدخول المميز حسب الحاجة.
Ruby
إذا كان تطبيقك يحتاج إلى الوصول إلى إحدى واجهات Google API بدون اتصال بالإنترنت، اضبط نوع الوصول إلى عميل واجهة برمجة التطبيقات على offline
:
auth_client.update!( :additional_parameters => {"access_type" => "offline"} )
بعد أن يمنح المستخدم إذن الوصول بلا إنترنت إلى النطاقات المطلوبة، يمكنك مواصلة استخدام برنامج واجهة برمجة التطبيقات للوصول إلى Google APIs بالنيابة عن المستخدم عندما يكون غير متصل بالإنترنت. سيُعيد عنصر العميل تحميل رمز الدخول المميز حسب الحاجة.
Node.js
إذا كان تطبيقك يحتاج إلى الوصول إلى إحدى واجهات Google API بدون اتصال بالإنترنت، اضبط نوع الوصول إلى عميل واجهة برمجة التطبيقات على offline
:
const authorizationUrl = oauth2Client.generateAuthUrl({ // 'online' (default) or 'offline' (gets refresh_token) access_type: 'offline', /** Pass in the scopes array defined above. * Alternatively, if only one scope is needed, you can pass a scope URL as a string */ scope: scopes, // Enable incremental authorization. Recommended as a best practice. include_granted_scopes: true });
بعد أن يمنح المستخدم إذن الوصول بلا إنترنت إلى النطاقات المطلوبة، يمكنك مواصلة استخدام برنامج واجهة برمجة التطبيقات للوصول إلى Google APIs بالنيابة عن المستخدم عندما يكون غير متصل بالإنترنت. سيُعيد عنصر العميل تحميل رمز الدخول المميز حسب الحاجة.
تنتهي صلاحية رموز الدخول. ستستخدم هذه المكتبة تلقائيًا رمزًا مميزًا لإعادة التحميل من أجل الحصول على رمز مميز جديد للوصول إذا كان على وشك انتهاء صلاحيته. للتأكّد من تخزين أحدث الرموز المميّزة دائمًا، يمكنك استخدام حدث الرموز المميّزة:
oauth2Client.on('tokens', (tokens) => { if (tokens.refresh_token) { // store the refresh_token in your secure persistent database console.log(tokens.refresh_token); } console.log(tokens.access_token); });
لا يحدث حدث الرموز المميزة هذا إلا في عملية التفويض الأولى، ويجب أن تكون قد ضبطت قيمة access_type
على offline
عند استدعاء طريقة generateAuthUrl
لتلقّي الرمز المميز لإعادة التحميل. إذا سبق لك منح تطبيقك الأذونات المطلوبة بدون ضبط القيود المناسبة لتلقّي رمز مميّز لإعادة التحميل، عليك إعادة تفويض التطبيق لتلقّي رمز مميّز جديد لإعادة التحميل.
لضبط refresh_token
في وقت لاحق، يمكنك استخدام طريقة setCredentials
:
oauth2Client.setCredentials({ refresh_token: `STORED_REFRESH_TOKEN` });
بعد حصول العميل على رمز مميز لإعادة التحميل، سيتم الحصول على رموز الدخول وإعادة تحميلها تلقائيًا في الاتصال التالي بواجهة برمجة التطبيقات.
HTTP/REST
لتحديث رمز الدخول، يرسل تطبيقك طلب HTTPS POST
إلى خادم التفويض في Google (https://oauth2.googleapis.com/token
) يتضمّن المَعلمات التالية:
الحقول | |
---|---|
client_id |
معرّف العميل الذي تم الحصول عليه من API Console. |
client_secret |
سرّ العميل الذي تم الحصول عليه من API Console. |
grant_type |
كما هو محدّد في
مواصفات OAuth 2.0،
يجب ضبط قيمة هذا الحقل على refresh_token . |
refresh_token |
الرمز المميز لإعادة التحميل الذي تم عرضه من عملية تبديل رمز التفويض |
يعرض المقتطف التالي نموذجًا لطلب:
POST /token HTTP/1.1 Host: oauth2.googleapis.com Content-Type: application/x-www-form-urlencoded client_id=your_client_id& client_secret=your_client_secret& refresh_token=refresh_token& grant_type=refresh_token
ما دام المستخدم لم يبطل إذن الوصول الممنوح للتطبيق، سيعرض خادم الرموز المميزة عنصر JSON يتضمّن رمزًا مميزًا جديدًا للوصول. يعرض المقتطف التالي نموذجًا لردّ:
{ "access_token": "1/fFAGRNJru1FTz70BzhT3Zg", "expires_in": 3920, "scope": "https://www.googleapis.com/auth/drive.metadata.readonly https://www.googleapis.com/auth/calendar.readonly", "token_type": "Bearer" }
يُرجى العِلم أنّ هناك حدودًا لعدد رموز التحديث التي سيتم إصدارها، وهي حدّ واحد لكل مجموعة من العملاء والمستخدمين، وحدّ آخر لكل مستخدم على مستوى جميع العملاء. عليك حفظ رموز إعادة التحميل في مساحة تخزين طويلة الأمد ومواصلة استخدامها طالما أنّها تظل صالحة. إذا كان تطبيقك يطلب عددًا كبيرًا جدًا من رموز التحديث، قد يواجه هذه الحدود، وفي هذه الحالة سيتوقف عمل رموز التحديث الأقدم.
إبطال رمز مميّز
في بعض الحالات، قد يرغب المستخدم في إبطال إذن الوصول الذي تم منحه لتطبيق. يمكن للمستخدم إبطال إذن الوصول من خلال الانتقال إلى إعدادات الحساب. للحصول على مزيد من المعلومات، يمكنك الاطّلاع على قسم إزالة إمكانية وصول موقع إلكتروني أو تطبيق في مستند الدعم "المواقع الإلكترونية والتطبيقات الخارجية التي يمكنها الوصول إلى حسابك".
من الممكن أيضًا أن يلغي تطبيق إذن الوصول الذي تم منحه له بشكل آلي. ويكون الإبطال آليًا مهمًا في الحالات التي يلغي فيها المستخدم اشتراكه أو يزيل تطبيقًا أو تتغير فيها بشكل كبير موارد واجهة برمجة التطبيقات التي يتطلبها التطبيق. بعبارة أخرى، يمكن أن يتضمّن جزء من عملية الإزالة طلبًا من خلال واجهة برمجة التطبيقات لضمان إزالة الأذونات التي تم منحها للتطبيق سابقًا.
PHP
لإبطال رمز مميّز آليًا، استخدِم الأمر revokeToken()
:
$client->revokeToken();
Python
لإبطال رمز مميّز آليًا، أرسِل طلبًا إلى
https://oauth2.googleapis.com/revoke
يتضمّن الرمز المميّز كمَعلمة ويضبط عنوان
Content-Type
على النحو التالي:
requests.post('https://oauth2.googleapis.com/revoke', params={'token': credentials.token}, headers = {'content-type': 'application/x-www-form-urlencoded'})
Ruby
لإبطال رمز مميز آليًا، أرسِل طلب HTTP إلى نقطة النهاية oauth2.revoke
:
uri = URI('https://oauth2.googleapis.com/revoke') response = Net::HTTP.post_form(uri, 'token' => auth_client.access_token)
يمكن أن يكون الرمز المميز رمز دخول أو رمز إعادة تحميل. إذا كان الرمز المميز هو رمز دخول وكان يتضمّن رمزًا مميزًا لإعادة التحميل، سيتم أيضًا إبطال رمز إعادة التحميل.
في حال تمت معالجة الإلغاء بنجاح، سيكون رمز الحالة للاستجابة هو 200
. في حال حدوث خطأ، يتم عرض رمز الحالة 400
مع رمز الخطأ.
Node.js
لإبطال رمز مميّز آليًا، أرسِل طلب HTTPS POST إلى نقطة النهاية /revoke
:
const https = require('https'); // Build the string for the POST request let postData = "token=" + userCredential.access_token; // Options for POST request to Google's OAuth 2.0 server to revoke a token let postOptions = { host: 'oauth2.googleapis.com', port: '443', path: '/revoke', method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded', 'Content-Length': Buffer.byteLength(postData) } }; // Set up the request const postReq = https.request(postOptions, function (res) { res.setEncoding('utf8'); res.on('data', d => { console.log('Response: ' + d); }); }); postReq.on('error', error => { console.log(error) }); // Post the request with data postReq.write(postData); postReq.end();
يمكن أن تكون مَعلمة الرمز المميز رمز دخول أو رمز مميز لإعادة التحميل. إذا كان الرمز المميز هو رمز دخول وكان يتضمّن رمزًا مميزًا لإعادة التحميل، سيتم أيضًا إبطال رمز إعادة التحميل.
في حال تمت معالجة الإلغاء بنجاح، سيكون رمز الحالة للاستجابة هو 200
. في حال حدوث خطأ، يتم عرض رمز الحالة 400
مع رمز الخطأ.
HTTP/REST
لإبطال رمز مميّز آليًا، يرسل تطبيقك طلبًا إلى
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
مع رمز خطأ.
الوصول المستند إلى الوقت
يسمح الوصول المستند إلى الوقت للمستخدم بمنح تطبيقك الإذن بالوصول إلى بياناته لمدة محدودة لإكمال إجراء معيّن. تتوفّر إمكانية الوصول المستند إلى الوقت في منتجات Google محدّدة أثناء مسار الموافقة، ما يمنح المستخدمين خيار منح إذن الوصول لمدة محدودة. ومن الأمثلة على ذلك Data Portability API التي تتيح نقل البيانات لمرة واحدة.
عندما يمنح المستخدم تطبيقك إذن الوصول المستند إلى الوقت، ستنتهي صلاحية رمز إعادة التحميل بعد المدة المحدّدة. يُرجى العِلم أنّه قد يتم إبطال رموز التحديث قبل الموعد المحدّد في ظروف معيّنة، ويمكنك الاطّلاع على هذه الحالات للحصول على التفاصيل. يمثّل الحقل refresh_token_expires_in
الذي تم عرضه في استجابة تبديل رمز التفويض الوقت المتبقي حتى تنتهي صلاحية رمز التحديث في هذه الحالات.
تفعيل ميزة "الحماية العابرة للحساب"
من الخطوات الإضافية التي يجب اتّخاذها لحماية حسابات المستخدمين تنفيذ ميزة "الحماية على مستوى الحسابات" من خلال الاستفادة من خدمة "الحماية على مستوى الحسابات" من 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
يمكنك الاطّلاع على صفحة حماية حسابات المستخدمين باستخدام ميزة "الحماية العابرة للحساب" للحصول على مزيد من المعلومات حول كيفية تنفيذ ميزة "الحماية العابرة للحساب" والقائمة الكاملة بالأحداث المتاحة.