يشرح هذا المستند كيف تستخدم تطبيقات خادم الويب مكتبات عميل Google API أو نقاط نهاية OAuth 2.0 من Google لتنفيذ تفويض OAuth 2.0 للوصول إلى YouTube Data API.
يتيح بروتوكول OAuth 2.0 للمستخدمين مشاركة بيانات محدّدة مع أحد التطبيقات مع الحفاظ على خصوصية أسماء المستخدمين وكلمات المرور والمعلومات الأخرى. على سبيل المثال، يمكن لتطبيق استخدام OAuth 2.0 للحصول على إذن باسترداد بيانات قناة على YouTube.
تم إعداد مسار OAuth 2.0 هذا تحديدًا لتفويض المستخدم. وهي مصممة للتطبيقات التي يمكنها تخزين المعلومات السرية والحفاظ على حالتها. يمكن لتطبيق خادم الويب المعتمد بشكل صحيح الوصول إلى واجهة برمجة التطبيقات أثناء تفاعل المستخدم مع التطبيق أو بعد مغادرته للتطبيق.
تستخدم تطبيقات خادم الويب أيضًا حسابات الخدمة للسماح بطلبات البيانات من واجهة برمجة التطبيقات، خاصةً عند استدعاء Cloud APIs للوصول إلى البيانات المستندة إلى المشروع بدلاً من البيانات الخاصة بالمستخدم. يمكن أن تستخدم تطبيقات خادم الويب حسابات الخدمة إلى جانب تفويض المستخدم.
لا تتيح YouTube Live Streaming API مسار حساب الخدمة. وبما أنّه لا تتوفّر طريقة لربط حساب خدمة بحساب على YouTube، ستؤدي محاولات منح الإذن في الطلبات في هذا المسار إلى عرض خطأ NoLinkedYouTubeAccount
.
مكتبات العملاء
تستخدم الأمثلة الخاصة باللغة في هذه الصفحة مكتبات عميل 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.
- استخدِم صفحة "المكتبة" للعثور على YouTube Data API وتفعيلها. ابحث عن أي واجهات برمجة تطبيقات أخرى سيستخدمها تطبيقك وفعّلها أيضًا.
إنشاء بيانات اعتماد التفويض
يجب أن يكون لدى أي تطبيق يستخدم OAuth 2.0 للوصول إلى واجهات Google APIs بيانات اعتماد تفويض تحدِّد التطبيق إلى خادم OAuth 2.0 من Google. توضّح الخطوات التالية كيفية إنشاء بيانات اعتماد لمشروعك. ويمكن لتطبيقاتك بعد ذلك استخدام بيانات الاعتماد للوصول إلى واجهات برمجة التطبيقات التي فعّلتها لهذا المشروع.
- Go to the Credentials page.
- انقر على إنشاء بيانات الاعتماد > معرِّف عميل OAuth.
- اختَر نوع تطبيق تطبيق الويب.
- املأ النموذج وانقر على إنشاء. إذا كانت التطبيقات تستخدم لغات وأُطر عمل، مثل 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، ننصحك بتحديد النطاقات التي سيحتاج تطبيقك إلى إذن للوصول إليها.
نقترح أيضًا أن يطلب تطبيقك الوصول إلى نطاقات الأذونات من خلال عملية تفويض متزايد يطلب فيها تطبيقك الوصول إلى بيانات المستخدمين في السياق. وتساعد أفضل الممارسات هذه المستخدمين في فهم سبب احتياج تطبيقك للوصول الذي يطلبه بسهولة أكبر.
يستخدم الإصدار الثالث من YouTube Data API النطاقات التالية:
المناظير | |
---|---|
https://www.googleapis.com/auth/youtube | إدارة حسابك في YouTube |
https://www.googleapis.com/auth/youtube.channel-memberships.creator | الاطّلاع على قائمة بأعضاء القناة النشطين حاليًا ومستواهم الحالي وتاريخ انضمامهم |
https://www.googleapis.com/auth/youtube.force-ssl | الاطّلاع على فيديوهاتك على YouTube وتقييماتها وتعليقاتها وترجماتها وكذلك تعديلها وحذفها نهائيًا |
https://www.googleapis.com/auth/youtube.readonly | عرض حسابك في YouTube |
https://www.googleapis.com/auth/youtube.upload | إدارة فيديوهات YouTube |
https://www.googleapis.com/auth/youtubepartner | عرض وإدارة أصولك والمحتوى المرتبط بها على YouTube |
https://www.googleapis.com/auth/youtubepartner-channel-audit | عرض معلومات خاصة عن قناتك على YouTube ذات صلة أثناء عملية تدقيق شريك YouTube |
يحتوي مستند نطاقات OAuth 2.0 API على قائمة كاملة بالنطاقات التي قد تستخدمها للوصول إلى واجهات Google APIs.
المتطلبات الخاصة بكل لغة
لتشغيل أي من عينات الرموز في هذا المستند، ستحتاج إلى حساب Google، والوصول إلى الإنترنت، ومتصفّح ويب. إذا كنت تستخدم إحدى مكتبات برامج واجهة برمجة التطبيقات، يمكنك أيضًا الاطّلاع أدناه على المتطلبات الخاصة باللغات.
PHP
لتشغيل نماذج كود PHP في هذا المستند، ستحتاج إلى:
- الإصدار 5.6 من PHP أو الإصدارات الأحدث مع تثبيت واجهة سطر الأوامر (CLI) وإضافة JSON.
- أداة إدارة الاعتمادية في المؤلف
-
مكتبة برامج Google APIs للغة PHP:
composer require google/apiclient:^2.10
Python
لتشغيل عيّنات التعليمات البرمجية للغة بايثون في هذا المستند، ستحتاج إلى:
- Python 2.6 أو أحدث
- أداة إدارة حزم pip
- مكتبة برامج Google APIs للغة 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
Ruby
لتشغيل نماذج برمجة Ruby في هذا المستند، ستحتاج إلى:
- Ruby 2.6 أو أكبر
-
مكتبة مصادقة Google للغة Ruby:
gem install googleauth
-
إطار عمل تطبيق الويب Sinatra Ruby.
gem install sinatra
Node.js
لتشغيل نماذج التعليمات البرمجية Node.js في هذا المستند، ستحتاج إلى:
- قناة الدعم الطويل الأمد (LTS) أو قناة الدعم الطويل الأمد (LTS) النشطة أو الإصدار الحالي من Node.js.
-
عميل Node.js من Google APIs:
npm install googleapis crypto express express-session
HTTP/REST
لا تحتاج إلى تثبيت أي مكتبات لتتمكن من استدعاء نقاط نهاية OAuth 2.0 مباشرةً.
الحصول على رموز الدخول عبر OAuth 2.0
توضِّح الخطوات التالية كيفية تفاعل تطبيقك مع خادم OAuth 2.0 من Google للحصول على موافقة المستخدم لتنفيذ طلب واجهة برمجة التطبيقات نيابةً عنه. يجب أن يحصل تطبيقك على تلك الموافقة ليتمكّن من تنفيذ طلب 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
الاختياريتَين.
على سبيل المثال، لطلب الوصول بلا إنترنت إلى بيانات مستخدم على YouTube، اتّبِع الخطوات التالية:
$client = new Google\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_YouTube::YOUTUBE_FORCE_SSL); // 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
الاختياريتَين.
على سبيل المثال، لطلب الوصول بلا إنترنت إلى بيانات مستخدم على YouTube، اتّبِع الخطوات التالية:
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/youtube.force-ssl']) # 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.
على سبيل المثال، لطلب الوصول بلا إنترنت إلى بيانات مستخدم على YouTube، اتّبِع الخطوات التالية:
require 'google/apis/youtube_v3' require "googleauth" require 'googleauth/stores/redis_token_store' client_id = Google::Auth::ClientId.from_file('/path/to/client_secret.json') scope = 'https://www.googleapis.com/auth/youtube.force-ssl' token_store = Google::Auth::Stores::RedisTokenStore.new(redis: Redis.new) authorizer = Google::Auth::WebUserAuthorizer.new(client_id, scope, token_store, '/oauth2callback')
يستخدم تطبيقك كائن العميل لتنفيذ عمليات 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 read-only Drive activity. const scopes = [ 'https://www.googleapis.com/auth/drive.metadata.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 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 |
مطلوب
معرِّف العميل لتطبيقك. يمكنك العثور على هذه القيمة في Credentials page API Console. |
||||||||||||||||
redirect_uri |
مطلوب
تحدِّد هذه السياسة الموضع الذي يعيد فيه خادم واجهة برمجة التطبيقات توجيه المستخدم بعد أن يكمل المستخدم
مسار التفويض. يجب أن تتطابق القيمة بشكل تام مع أحد معرّفات الموارد المنتظمة (URI) المعتمَدة لإعادة التوجيه
لعميل OAuth 2.0، الذي ضبطته في
API Console
Credentials pageفي جهاز العميل. إذا لم تتطابق هذه القيمة مع معرّف الموارد المنتظم (URI) المعتمَد لإعادة التوجيه لعنوان يُرجى العلم أنّه يجب أن تتطابق جميع عناصر المخطَّط |
||||||||||||||||
response_type |
مطلوب
تحدِّد هذه السياسة ما إذا كانت نقطة نهاية Google OAuth 2.0 تعرض رمز تفويض. اضبط قيمة المَعلمة على |
||||||||||||||||
scope |
مطلوب
تمثّل هذه السمة قائمة بالنطاقات مع الفصل بينها بمسافات تحدّد الموارد التي يمكن لتطبيقك الوصول إليها نيابةً عن المستخدم. تحدِّد هذه القيم شاشة الموافقة التي تعرضها Google للمستخدم. تتيح "النطاقات" لتطبيقك أن يطلب إذن الوصول إلى الموارد التي يحتاج إليها فقط مع السماح أيضًا للمستخدمين بالتحكّم في مقدار أذونات الوصول التي يمنحونها لتطبيقك. وبالتالي، هناك علاقة عكسية بين عدد النطاقات المطلوبة واحتمالية الحصول على موافقة المستخدم. يستخدم الإصدار الثالث من YouTube Data API النطاقات التالية:
يوفّر مستند نطاقات واجهة برمجة التطبيقات OAuth 2.0 قائمة كاملة بالنطاقات التي قد تستخدمها للوصول إلى واجهات برمجة تطبيقات Google. ننصحك بأن يطلب تطبيقك الوصول إلى نطاقات التفويض في السياق المناسب كلما أمكن ذلك. من خلال طلب الوصول إلى بيانات المستخدمين في السياق، من خلال الإذن المتزايد، أنت تساعد المستخدمين في فهم سبب احتياج تطبيقك إلى الوصول الذي يطلبه. |
||||||||||||||||
access_type |
سمة مقترَحة
يشير هذا الحقل إلى ما إذا كان بإمكان تطبيقك إعادة تحميل رموز الدخول عندما لا يكون المستخدم متاحًا
في المتصفّح. قيم المَعلمات الصالحة هي اضبط القيمة على |
||||||||||||||||
state |
سمة مقترَحة
تحدِّد هذه السياسة أي قيمة سلسلة يستخدمها تطبيقك للحفاظ على الحالة بين
طلب التفويض واستجابة خادم التفويض.
يعرض الخادم القيمة نفسها التي ترسلها كزوج يمكنك استخدام هذه المَعلمة لعدة أغراض، مثل توجيه المستخدم إلى
المورد الصحيح في تطبيقك، وإرسال رقم Nonces، والحدّ من تزييف الطلبات من مواقع إلكترونية متعددة. بما أنّه يمكن تخمين |
||||||||||||||||
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(login_hint: user_id, request: request)
- إعادة توجيه المستخدِم إلى "
auth_uri
"
Node.js
-
يمكنك استخدام عنوان URL الذي تم إنشاؤه
authorizationUrl
من طريقة الخطوة 1generateAuthUrl
لطلب الوصول من خادم OAuth 2.0 في Google. -
إعادة توجيه المستخدِم إلى "
authorizationUrl
"res.redirect(authorizationUrl);
HTTP/REST
Sample redirect to Google's authorization server
An example URL is shown below, with line breaks and spaces for readability. The URL requests
access to a scope that permits access to retrieve the user's YouTube data. It uses incremental
authorization (include_granted_scopes=true
) to ensure that the new access token
covers any scopes to which the user previously granted the application access. Several other
parameters are also set in the example.
https://accounts.google.com/o/oauth2/v2/auth? scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fyoutube.force-ssl& access_type=offline& include_granted_scopes=true& response_type=code& state=state_parameter_passthrough_value& redirect_uri=http%3A%2F%2Flocalhost%2Foauth2callback& 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 for Android من مؤسسة OpenID.
قد يظهر هذا الخطأ لمطوِّري الويب عندما يفتح تطبيق Android رابط ويب عامًا في وكيل مستخدم مضمّن وينتقل المستخدم إلى نقطة نهاية تفويض OAuth 2.0 من Google من موقعك الإلكتروني. على المطوّرين أن يسمحوا بفتح الروابط العامة في معالج الروابط التلقائي لنظام التشغيل، والذي يتضمّن معالِجات روابط تطبيقات Android أو تطبيق المتصفّح التلقائي. وتُعد مكتبة علامات تبويب Android المخصّصة خيارًا متاحًا أيضًا.
iOS
قد يظهر هذا الخطأ لمطوِّري تطبيقات iOS وmacOS عند فتح طلبات التفويض في WKWebView
.
وبدلاً من ذلك، على المطوّرين استخدام مكتبات iOS مثل
تسجيل الدخول بحساب Google على أجهزة iOS أو
AppAuth for iOS من OpenID Foundation.
قد يظهر هذا الخطأ لمطوِّري الويب عندما يفتح تطبيق iOS أو macOS رابط ويب عامًا في وكيل مستخدم مضمّن وينتقل المستخدم إلى نقطة نهاية تفويض OAuth 2.0 من Google من موقعك الإلكتروني. على المطوّرين أن يسمحوا بفتح الروابط العامة في معالج الروابط التلقائي لنظام التشغيل، والذي يتضمّن معالجات الروابط العامة أو تطبيق المتصفّح التلقائي، مع العِلم بأنّ مكتبة SFSafariViewController
هي أيضًا خيار متاح.
org_internal
يمثّل معرِّف عميل OAuth في الطلب جزءًا من مشروع يحدّ من إمكانية الوصول إلى حسابات Google في مؤسسة معيّنة على Google Cloud. لمزيد من المعلومات حول خيار الإعداد هذا، يمكنك الاطّلاع على القسم نوع المستخدم في مقالة المساعدة "إعداد شاشة طلب الموافقة المتعلقة ببروتوكول OAuth".
invalid_client
سر عميل OAuth غير صحيح. راجِع إعدادات عميل OAuth، بما في ذلك معرِّف العميل والرمز السري المُستخدَم في هذا الطلب.
invalid_grant
عند إعادة تحميل رمز الدخول أو استخدام تفويض متزايد، قد تكون صلاحية الرمز المميّز قد انتهت أو تم إبطاله. عليك المصادقة على المستخدم مرة أخرى وطلب موافقة المستخدم للحصول على رموز مميّزة جديدة. إذا استمر ظهور هذا الخطأ، تأكَّد من ضبط تطبيقك بشكل صحيح وأنّك تستخدم الرموز المميّزة والمعلَمات الصحيحة في طلبك. بخلاف ذلك، ربما تم حذف حساب المستخدم أو إيقافه.
redirect_uri_mismatch
لا يتطابق redirect_uri
الذي تم تمريره في طلب التفويض مع معرِّف الموارد المنتظم (URI) المعتمَد لإعادة التوجيه لمعرِّف عميل OAuth. يمكنك مراجعة معرّفات الموارد المنتظمة (URI) المعتمَدة لإعادة التوجيه في
Google API Console Credentials page.
قد تشير مَعلمة 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:
https://accounts.google.com/o/oauth2/v2/auth? scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fyoutube.force-ssl& access_type=offline& include_granted_scopes=true& response_type=code& state=state_parameter_passthrough_value& redirect_uri=http%3A%2F%2Flocalhost%2Foauth2callback& client_id=client_id
بعد إكمال مسار OAuth 2.0، من المفترَض أن تتم إعادة توجيهك إلى
http://localhost/oauth2callback
، ما سيؤدي على الأرجح إلى ظهور
الخطأ 404 NOT FOUND
ما لم يعرض جهازك المحلي ملفًا على هذا العنوان. توفّر الخطوة التالية مزيدًا من التفاصيل حول المعلومات التي يتم عرضها في معرّف الموارد المنتظم (URI) عندما تتم إعادة توجيه المستخدم إلى تطبيقك مرة أخرى.
الخطوة 5: استبدال رمز التفويض لإعادة التحميل ورموز الدخول
بعد أن يتلقّى خادم الويب رمز التفويض، يمكنه استبدال رمز التفويض برمز وصول.
PHP
لاستبدال رمز تفويض برمز دخول، استخدِم الطريقة authenticate
:
$client->authenticate($_GET['code']);
يمكنك استرداد رمز الدخول باستخدام الطريقة getAccessToken
:
$access_token = $client->getAccessToken();
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/youtube.force-ssl'], 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, 'scopes': credentials.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 |
معرّف العميل الذي تم الحصول عليه من API Console Credentials page. |
client_secret |
سر العميل الذي تم الحصول عليه من API Console Credentials page. |
code |
رمز التفويض الذي تم عرضه من الطلب الأولي. |
grant_type |
كما هو موضح في مواصفات
OAuth 2.0، يجب ضبط قيمة هذا الحقل على authorization_code . |
redirect_uri |
أحد معرّفات الموارد المنتظمة (URI) الخاصة بإعادة التوجيه والمدرجة في مشروعك ضمن
API Console
Credentials page الخاص بـ
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. |
expires_in |
العمر المتبقي لرمز الدخول بالثواني. |
refresh_token |
هو رمز مميّز يمكنك استخدامه للحصول على رمز دخول جديد. تظل الرموز المميّزة لإعادة التحميل صالحة إلى أن
يبطل المستخدم إذن الوصول إليها.
مرة أخرى، لا يتوفّر هذا الحقل في هذه الاستجابة إلا إذا ضبطت المعلمة access_type
على offline في الطلب الأولي إلى خادم تفويض Google.
|
scope |
تمثّل هذه السمة نطاقات الوصول الممنوحة من خلال access_token كقائمة من السلاسل الحسّاسة لحالة الأحرف والمفصولة بمسافات. |
token_type |
نوع الرمز المميّز الذي تم عرضه. في الوقت الحالي، يتم ضبط قيمة هذا الحقل دائمًا على
Bearer . |
يعرض المقتطف التالي نموذجًا للرد:
{ "access_token": "1/fFAGRNJru1FTz70BzhT3Zg", "expires_in": 3920, "token_type": "Bearer", "scope": "https://www.googleapis.com/auth/youtube.force-ssl", "refresh_token": "1//xEoDL4iW3cxlI7yDbSRFYNG01kVKM2C-259HOF2aQbI" }
الأخطاء
عند استبدال رمز التفويض برمز مميّز للدخول، قد يظهر لك الخطأ التالي بدلاً من الاستجابة المتوقعة. وفي ما يلي رموز الأخطاء الشائعة والحلول المقترَحة.
invalid_grant
رمز التفويض المُقدَّم غير صالح أو بتنسيق غير صحيح. اطلب رمزًا جديدًا من خلال إعادة بدء عملية OAuth لطلب الموافقة من المستخدم مرة أخرى.
الاتصال بـ Google APIs
PHP
استخدم رمز الدخول لاستدعاء Google APIs من خلال إكمال الخطوات التالية:
- إذا كنت بحاجة إلى تطبيق رمز دخول على عنصر
Google\Client
جديد، على سبيل المثال، في حال تخزين رمز الدخول في جلسة مستخدم، استخدِم طريقةsetAccessToken
:$client->setAccessToken($access_token);
- أنشِئ عنصر خدمة لواجهة برمجة التطبيقات التي تريد طلبها. يمكنك إنشاء عنصر خدمة من خلال تقديم عنصر
Google\Client
معتمد إلى الدالة الإنشائية لواجهة برمجة التطبيقات التي تريد طلبها. على سبيل المثال، لطلب بيانات YouTube Data API:$youtube = new Google_Service_YouTube($client);
- أرسِل طلبات إلى خدمة واجهة برمجة التطبيقات باستخدام الواجهة التي يوفّرها عنصر الخدمة.
على سبيل المثال، لاستخدام YouTube Data API لاسترداد قائمة بأحداث البث المباشر لقناة المستخدم الذي تمت المصادقة عليه:
$broadcasts = $youtube->liveBroadcasts->listLiveBroadcasts('id,snippet', [ 'mine' => true ]);
Python
بعد الحصول على رمز الدخول، يمكن لتطبيقك استخدام ذلك الرمز المميّز للسماح بطلبات البيانات من واجهة برمجة التطبيقات نيابةً عن حساب مستخدم أو حساب خدمة محدّد. استخدِم بيانات اعتماد التفويض الخاصة بالمستخدم لإنشاء عنصر خدمة لواجهة برمجة التطبيقات التي تريد طلبها، ثم استخدِم هذا العنصر لتقديم طلبات معتمَدة من واجهة برمجة التطبيقات.
- أنشِئ عنصر خدمة لواجهة برمجة التطبيقات التي تريد طلبها. يمكنك إنشاء عنصر خدمة من خلال استدعاء طريقة
build
في مكتبةgoogleapiclient.discovery
مع اسم واجهة برمجة التطبيقات وإصدارها وبيانات اعتماد المستخدم: على سبيل المثال، لطلب الإصدار 3 من YouTube Data API:from googleapiclient.discovery import build youtube = build('youtube', 'v3', credentials=credentials)
- أرسِل طلبات إلى خدمة واجهة برمجة التطبيقات باستخدام الواجهة التي يوفّرها عنصر الخدمة.
على سبيل المثال، لاستخدام YouTube Data API لاسترداد قائمة بأحداث البث المباشر لقناة المستخدم الذي تمت المصادقة عليه:
broadcasts = youtube.liveBroadcasts().list(part='id,snippet', mine=True).execute()
Ruby
بعد الحصول على رمز الدخول، يمكن لتطبيقك استخدام ذلك الرمز المميّز لإرسال طلبات واجهة برمجة التطبيقات نيابةً عن حساب مستخدم معيّن أو حساب خدمة معيّن. استخدِم بيانات اعتماد التفويض الخاصة بالمستخدم لإنشاء عنصر خدمة لواجهة برمجة التطبيقات التي تريد طلبها، ثم استخدِم هذا العنصر لتقديم طلبات معتمَدة من واجهة برمجة التطبيقات.
- أنشِئ عنصر خدمة لواجهة برمجة التطبيقات التي تريد طلبها.
على سبيل المثال، لطلب الإصدار 3 من YouTube Data API:
youtube = Google::Apis::YoutubeV3::YouTubeService.new
- اضبط بيانات الاعتماد في الخدمة:
youtube.authorization = credentials
- أرسِل طلبات إلى خدمة واجهة برمجة التطبيقات باستخدام الواجهة التي يوفّرها عنصر الخدمة.
على سبيل المثال، لاستخدام YouTube Data API لاسترداد قائمة بأحداث البث المباشر لقناة المستخدم الذي تمت المصادقة عليه:
broadcasts = youtube.list_liveBroadcasts('id,snippet', mine: true)
بدلاً من ذلك، يمكن توفير التفويض على أساس كل طريقة من خلال توفير المَعلمة options
إلى إحدى الطرق التالية:
broadcasts = youtube.list_liveBroadcasts('id,snippet', mine: true)
Node.js
بعد الحصول على رمز الدخول وضبطه على الكائن OAuth2
، استخدِم الكائن لاستدعاء Google APIs. يمكن لتطبيقك استخدام هذا الرمز المميّز للسماح بطلبات البيانات من واجهة برمجة التطبيقات نيابةً عن
حساب مستخدم معيّن أو حساب خدمة معيّن. أنشِئ عنصر خدمة لواجهة برمجة التطبيقات التي تريد طلبها.
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 APIs (على سبيل المثال، عند
طلب بيانات من YouTube Live Streaming API).
تجدر الإشارة إلى أنّ YouTube Live Streaming API لا تتيح تدفق حساب الخدمة. وبما أنّه لا تتوفّر طريقة لربط حساب الخدمة بحساب على YouTube، ستؤدي محاولات منح الإذن في الطلبات خلال هذا الإجراء إلى ظهور خطأ NoLinkedYouTubeAccount
.
يمكنك تجربة جميع واجهات Google APIs وعرض نطاقاتها في ملعب OAuth 2.0.
أمثلة على الحصول على HTTP
قد يبدو طلب نقطة نهاية
liveBroadcasts.list
(واجهة YouTube Live Streaming API) باستخدام عنوان HTTP Authorization: Bearer
على النحو التالي. ملاحظة: يجب تحديد رمز الدخول الخاص بك:
GET /youtube/v3/liveBroadcasts?part=id%2Csnippet&mine=true HTTP/1.1 Host: www.googleapis.com Authorization: Bearer access_token
في ما يلي طلب لواجهة برمجة التطبيقات نفسها للمستخدم الذي تمت مصادقته باستخدام معلَمة سلسلة طلب البحث access_token
:
GET https://www.googleapis.com/youtube/v3/liveBroadcasts?access_token=access_token&part=id%2Csnippet&mine=true
أمثلة على curl
يمكنك اختبار هذه الأوامر باستخدام تطبيق سطر الأوامر curl
. إليك مثال يستخدم خيار عنوان HTTP (خيار مفضَّل):
curl -H "Authorization: Bearer access_token" https://www.googleapis.com/youtube/v3/liveBroadcasts?part=id%2Csnippet&mine=true
أو بدلاً من ذلك، خيار مَعلمة سلسلة طلب البحث:
curl https://www.googleapis.com/youtube/v3/liveBroadcasts?access_token=access_token&part=id%2Csnippet&mine=true
المثال الكامل
في ما يلي مثال يطبع كائنًا بتنسيق JSON يعرض عمليات بث مباشر لقناة المستخدم الذي تمت المصادقة عليه على YouTube بعد أن يسمح المستخدم باسترداد هذه البيانات.
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.10
- أنشئ الملفين
index.php
وoauth2callback.php
باستخدام المحتوى أدناه. - شغّل المثال باستخدام خادم ويب تم تكوينه لعرض لغة PHP. إذا كنت تستخدم PHP 5.6 أو إصدارًا أحدث، يمكنك استخدام خادم الويب التجريبي المدمج في لغة 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_secrets.json'); $client->addScope(Google_Service_YouTube::YOUTUBE_FORCE_SSL); if (isset($_SESSION['access_token']) && $_SESSION['access_token']) { $client->setAccessToken($_SESSION['access_token']); $youtube = new Google_Service_YouTube($client); $broadcasts = $youtube->liveBroadcasts->listLiveBroadcasts('id,snippet', [ 'mine' => true ]); echo json_encode($broadcasts); } else { $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(); $client->setAuthConfigFile('client_secrets.json'); $client->setRedirectUri('http://' . $_SERVER['HTTP_HOST'] . '/oauth2callback.php'); $client->addScope(Google_Service_YouTube::YOUTUBE_FORCE_SSL); if (! isset($_GET['code'])) { // Generate and set state value $state = bin2hex(random_bytes(16)); $client->setState($state); $_SESSION['state'] = $state; $auth_url = $client->createAuthUrl(); header('Location: ' . filter_var($auth_url, FILTER_SANITIZE_URL)); } else { // Check the state value if (!isset($_GET['state']) || $_GET['state'] !== $_SESSION['state']) { die('State mismatch. Possible CSRF attack.'); } $client->authenticate($_GET['code']); $_SESSION['access_token'] = $client->getAccessToken(); $redirect_uri = 'http://' . $_SERVER['HTTP_HOST'] . '/'; header('Location: ' . filter_var($redirect_uri, FILTER_SANITIZE_URL)); }
Python
يستخدم هذا المثال إطار العمل Flask. ويشغِّل تطبيق ويب على http://localhost:8080
يتيح لك اختبار مسار OAuth 2.0. إذا انتقلت إلى عنوان URL هذا، من المفترض أن تظهر لك أربعة روابط:
- اختبار طلب بيانات من واجهة برمجة التطبيقات: يشير هذا الرابط إلى صفحة تحاول تنفيذ نموذج طلب بيانات من واجهة برمجة التطبيقات. عند اللزوم، سيتم بدء تدفق التفويض. في حال إتمام الإجراء، ستعرض الصفحة الردّ من واجهة برمجة التطبيقات.
- اختبار مسار المصادقة مباشرةً: يشير هذا الرابط إلى صفحة تحاول إرسال المستخدم من خلال مسار التفويض. يطلب التطبيق إذنًا لإرسال طلبات واجهة برمجة التطبيقات المعتمَدة نيابةً عن المستخدم.
- إبطال بيانات الاعتماد الحالية: يشير هذا الرابط إلى صفحة تم إبطال الأذونات التي منحها المستخدم للتطبيق من قبل.
- بيانات اعتماد جلسة 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" # This OAuth 2.0 access scope allows for full read/write access to the # authenticated user's account and requires requests to use an SSL connection. SCOPES = ['https://www.googleapis.com/auth/youtube.force-ssl'] API_SERVICE_NAME = 'youtube' API_VERSION = 'v3' 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('/test') def test_api_request(): if 'credentials' not in flask.session: return flask.redirect('authorize') # Load credentials from the session. credentials = google.oauth2.credentials.Credentials( **flask.session['credentials']) youtube = googleapiclient.discovery.build( API_SERVICE_NAME, API_VERSION, credentials=credentials) broadcasts = youtube.liveBroadcasts().list(part='id,snippet', mine=True).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(**broadcasts) @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 flask.session['credentials'] = credentials_to_dict(credentials) return flask.redirect(flask.url_for('test_api_request')) @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, 'scopes': credentials.scopes} 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' # 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 'google/apis/youtube_v3' require 'sinatra' require 'googleauth' require 'googleauth/stores/redis_token_store' configure do enable :sessions set :client_id, Google::Auth::ClientId.from_file('/path/to/client_secret.json') set :scope, Google::Apis::DriveV3::AUTH_DRIVE_METADATA_READONLY set :token_store, Google::Auth::Stores::RedisTokenStore.new(redis: Redis.new) set :authorizer, Google::Auth::WebUserAuthorizer.new(settings.client_id, settings.scope, settings.token_store, '/oauth2callback') end get '/' do user_id = settings.client_id.id credentials = settings.authorizer.get_credentials(user_id, request) if credentials.nil? redirect settings.authorizer.get_authorization_url(login_hint: user_id, request: request) end youtube = Google::Apis::YoutubeV3::YouTubeService.new broadcasts = youtube.list_liveBroadcasts('id,snippet', mine: true) "<pre>#{JSON.pretty_generate(broadcasts.to_h)}</pre>" end get '/oauth2callback' do 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
-
Install the
Google API Client
Library
for Node.js using 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 read-only Drive activity. const scopes = [ 'https://www.googleapis.com/auth/drive.metadata.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 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; // 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.'); } }); } }); // 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(80); } main().catch(console.error);
HTTP/REST
يستخدم مثال Python هذا إطار عمل Flask ومكتبة الطلبات لتوضيح مسار الويب OAuth 2.0. ننصحك باستخدام مكتبة برامج Google API للغة Python في هذا المسار. (يستخدم المثال في علامة التبويب Python مكتبة البرامج.)
import json import flask import requests app = flask.Flask(__name__) CLIENT_ID = '123456789.apps.googleusercontent.com' CLIENT_SECRET = 'abc123' # Read from a file or environmental variable in a real app SCOPE = 'https://www.googleapis.com/auth/youtube.force-ssl' 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: headers = {'Authorization': 'Bearer {}'.format(credentials['access_token'])} req_uri = 'https://youtube.googleapis.com/youtube/v3/liveBroadcasts' r = requests.get(req_uri, headers=headers) return r.text @app.route('/oauth2callback') def oauth2callback(): if 'code' not in flask.request.args: state = str(uuid.uuid4()) flask.session['state'] = state 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'} 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) لمساعدة المطوّرين في الحفاظ على أمان تطبيقاتهم. يجب أن تتقيّد معرفات الموارد المنتظمة (URI) لإعادة التوجيه بهذه القواعد. راجِع الفقرة 3 من معيار RFC 3986 للاطّلاع على تعريف النطاق والمضيف والمسار وطلب البحث والمخطط ومعلومات المستخدم أدناه.
قواعد التحقّق من الصحة | |
---|---|
المخطط |
يجب أن تستخدم معرّفات الموارد المنتظمة (URI) لإعادة التوجيه مخطط HTTPS، وليس HTTP العادي. تُستثنى من هذه القاعدة معرّفات الموارد المنتظمة (URI) للمضيف المحلي (بما في ذلك معرّفات الموارد المنتظمة (URI) لعنوان IP للمضيف المحلي). |
المضيف |
لا يمكن للمضيفين أن يكونوا عناوين IP غير معدّلة. تُستثنى من هذه القاعدة عناوين IP للمضيف المحلي. |
النطاق |
“googleusercontent.com” .goo.gl ) ما لم يكن التطبيق يملك النطاق. بالإضافة إلى ذلك، إذا اختار تطبيق يملك نطاقًا أقصر
إعادة التوجيه إلى ذلك النطاق، يجب أن يحتوي معرّف الموارد المنتظم (URI) لإعادة التوجيه هذا على
“/google-callback/” في مساره أو أن ينتهي بـ
“/google-callback” . |
معلومات المستخدم |
لا يمكن أن تحتوي معرّفات الموارد المنتظمة (URI) الخاصة بإعادة التوجيه على المكوِّن الفرعي لـ userinfo. |
المسار |
لا يمكن أن تحتوي معرّفات الموارد المنتظمة (URI) الخاصة بإعادة التوجيه على اجتياز مسار (يُعرف أيضًا باسم تتبُّع الدليل)،
والذي يتم تمثيله بـ |
طلب بحث |
لا يمكن أن تتضمّن معرّفات الموارد المنتظمة (URI) الخاصة بإعادة التوجيه عمليات إعادة توجيه مفتوحة. |
الجزء |
لا يمكن أن تحتوي معرّفات الموارد المنتظمة (URI) لإعادة التوجيه على المكوِّن. |
الأحرف |
لا يمكن أن تحتوي معرّفات الموارد المنتظمة (URI) الخاصة بإعادة التوجيه على أحرف معيّنة، بما في ذلك:
|
التفويض التزايدي
في بروتوكول OAuth 2.0، يطلب تطبيقك إذنًا للوصول إلى الموارد التي يتم تحديدها من خلال النطاقات. ويُعدّ طلب تفويض للموارد في الوقت الذي تحتاج فيه إليها من أفضل الممارسات المتعلّقة بتجربة المستخدم. لتفعيل هذه الممارسة، يدعم خادم تفويض Google التفويض التزايدي. تتيح لك هذه الميزة طلب النطاقات عند الحاجة إليها، وفي حال منح المستخدم إذنًا للنطاق الجديد، تعرض رمز تفويض يمكن استبداله برمز مميّز يحتوي على جميع النطاقات التي منحها المستخدم المشروع.
على سبيل المثال، لنفترض أنّ أحد التطبيقات يسترد بيانات قناة المستخدم التي تمت المصادقة عليها على YouTube ويمكِّنه أيضًا
من استرداد بيانات "إحصاءات YouTube" من خلال عملية خاصة. في هذه الحالة، وقد يطلب التطبيق أثناء تسجيل الدخول
إذن الوصول إلى نطاق https://www.googleapis.com/auth/youtube.force-ssl
فقط. مع ذلك، إذا حاول المستخدم الوصول إلى بيانات "إحصاءات Google" الخاصة بقناته، يمكن للتطبيق أيضًا
طلب الوصول إلى نطاق https://www.googleapis.com/auth/yt-analytics.readonly
.
لتنفيذ التفويض التزايدي، عليك إكمال المسار العادي لطلب رمز الدخول، ولكن تأكَّد من أنّ طلب التفويض يتضمّن نطاقات تم منحها سابقًا. ويسمح هذا النهج لتطبيقك بتجنُّب الاضطرار إلى إدارة رموز دخول متعددة.
تنطبق القواعد التالية على رمز الدخول الذي يتم الحصول عليه من تفويض متزايد:
- يمكن استخدام الرمز المميّز للوصول إلى الموارد المقابلة لأي من النطاقات التي تم إدراجها في التفويض الجديد المجمّع.
- عند استخدام الرمز المميّز لإعادة التحميل من أجل التفويض المجمّع للحصول على رمز دخول، يمثّل رمز الدخول التفويض المجمّع ويمكن استخدامه لأي من قيم
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
في هذا المثال، يطلب تطبيق الاتصال الإذن بالوصول لاسترداد بيانات المستخدم على YouTube بالإضافة إلى أي أذونات وصول أخرى سبق أن منحها المستخدم للتطبيق.
GET https://accounts.google.com/o/oauth2/v2/auth? scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fyoutube.force-ssl& access_type=offline& state=security_token%3D138rk%3Btarget_url%3Dhttp...index& redirect_uri=http%3A%2F%2Flocalhost%2Foauth2callback& response_type=code& client_id=client_id& include_granted_scopes=true
Refreshing an access token (offline access)
Access tokens periodically expire and become invalid credentials for a related API request. You can refresh an access token without prompting the user for permission (including when the user is not present) if you requested offline access to the scopes associated with the token.
- If you use a Google API Client Library, the client object refreshes the access token as needed as long as you configure that object for offline access.
- If you are not using a client library, you need to set the
access_type
HTTP query parameter tooffline
when redirecting the user to Google's OAuth 2.0 server. In that case, Google's authorization server returns a refresh token when you exchange an authorization code for an access token. Then, if the access token expires (or at any other time), you can use a refresh token to obtain a new access token.
Requesting offline access is a requirement for any application that needs to access a Google
API when the user is not present. For example, an app that performs backup services or
executes actions at predetermined times needs to be able to refresh its access token when the
user is not present. The default style of access is called online
.
Server-side web applications, installed applications, and devices all obtain refresh tokens during the authorization process. Refresh tokens are not typically used in client-side (JavaScript) web applications.
PHP
If your application needs offline access to a Google API, set the API client's access type to
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", "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
مع رمز الخطأ.