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

يشرح هذا المستند كيف تستخدم تطبيقات خادم الويب مكتبات عميل 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.

لتفعيل واجهة برمجة تطبيقات لمشروعك:

  1. Open the API Library في Google API Console.
  2. If prompted, select a project, or create a new one.
  3. استخدِم صفحة "المكتبة" للعثور على YouTube Data API وتفعيلها. ابحث عن أي واجهات برمجة تطبيقات أخرى سيستخدمها تطبيقك وفعّلها أيضًا.

إنشاء بيانات اعتماد التفويض

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

  1. Go to the Credentials page.
  2. انقر على إنشاء بيانات الاعتماد > معرِّف عميل OAuth.
  3. اختَر نوع تطبيق تطبيق الويب.
  4. املأ النموذج وانقر على إنشاء. إذا كانت التطبيقات تستخدم لغات وأُطر عمل، مثل 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 الذي يتطلّب الحصول على إذن المستخدم.

تلخّص القائمة التالية هذه الخطوات بسرعة:

  1. يحدِّد التطبيق الأذونات التي يحتاج إليها.
  2. يُعيد تطبيقك توجيه المستخدم إلى Google مع قائمة الأذونات المطلوبة.
  3. يقرر المستخدم ما إذا كان سيمنح الأذونات لتطبيقك أم لا.
  4. يعرف تطبيقك ما قرره المستخدم.
  5. إذا منح المستخدم الأذونات المطلوبة، يسترد تطبيقك الرموز المميزة اللازمة لتقديم طلبات واجهة برمجة التطبيقات نيابةً عن المستخدم.

الخطوة 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) المعتمَد لإعادة التوجيه لعنوان client_id المقدَّم، ستظهر لك رسالة الخطأ redirect_uri_mismatch.

يُرجى العلم أنّه يجب أن تتطابق جميع عناصر المخطَّط http أو https والحالة والشرطة المائلة اللاحقة ('/').

response_type مطلوب

تحدِّد هذه السياسة ما إذا كانت نقطة نهاية Google OAuth 2.0 تعرض رمز تفويض.

اضبط قيمة المَعلمة على code لتطبيقات خادم الويب.

scope مطلوب

تمثّل هذه السمة قائمة بالنطاقات مع الفصل بينها بمسافات تحدّد الموارد التي يمكن لتطبيقك الوصول إليها نيابةً عن المستخدم. تحدِّد هذه القيم شاشة الموافقة التي تعرضها Google للمستخدم.

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

يستخدم الإصدار الثالث من 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 قائمة كاملة بالنطاقات التي قد تستخدمها للوصول إلى واجهات برمجة تطبيقات Google.

ننصحك بأن يطلب تطبيقك الوصول إلى نطاقات التفويض في السياق المناسب كلما أمكن ذلك. من خلال طلب الوصول إلى بيانات المستخدمين في السياق، من خلال الإذن المتزايد، أنت تساعد المستخدمين في فهم سبب احتياج تطبيقك إلى الوصول الذي يطلبه.

access_type سمة مقترَحة

يشير هذا الحقل إلى ما إذا كان بإمكان تطبيقك إعادة تحميل رموز الدخول عندما لا يكون المستخدم متاحًا في المتصفّح. قيم المَعلمات الصالحة هي online، وهي القيمة التلقائية، وoffline.

اضبط القيمة على offline إذا كان تطبيقك يحتاج إلى إعادة تحميل رموز الدخول عندما لا يكون المستخدم متاحًا في المتصفّح. وهذه هي طريقة إعادة تحميل رموز الدخول الموضّحة لاحقًا في هذا المستند. تُوجِّه هذه القيمة خادم تفويض Google بعرض رمز مميز لإعادة التحميل ورمز دخول مميزًا في المرة الأولى التي يتبادل فيها تطبيقك رمز تفويض برموز مميّزة.

state سمة مقترَحة

تحدِّد هذه السياسة أي قيمة سلسلة يستخدمها تطبيقك للحفاظ على الحالة بين طلب التفويض واستجابة خادم التفويض. يعرض الخادم القيمة نفسها التي ترسلها كزوج name=value في مكوّن طلب البحث عن عنوان URL (?) في redirect_uri بعد موافقة المستخدم على طلب الوصول إلى تطبيقك أو رفضه.

يمكنك استخدام هذه المَعلمة لعدة أغراض، مثل توجيه المستخدم إلى المورد الصحيح في تطبيقك، وإرسال رقم Nonces، والحدّ من تزييف الطلبات من مواقع إلكترونية متعددة. بما أنّه يمكن تخمين redirect_uri، قد يؤدي استخدام القيمة state إلى زيادة ضمانك بأنّ الاتصال الوارد يكون نتيجة طلب مصادقة. إذا أنشأت سلسلة عشوائية أو ترميز تجزئة ملف تعريف الارتباط أو قيمة أخرى تسجّل حالة العميل، يمكنك التحقّق من صحة الاستجابة بالإضافة إلى التأكّد من أنّ الطلب والاستجابة قد نشأا من المتصفح نفسه، لتوفير الحماية من هجمات مثل تزوير الطلبات من مواقع إلكترونية متعددة. راجِع مستندات OpenID Connect للاطّلاع على مثال عن كيفية إنشاء رمز مميّز state وتأكيده.

include_granted_scopes اختياريّ

تعمل هذه السياسة على السماح للتطبيقات باستخدام التفويض التزايدي لطلب الوصول إلى نطاقات إضافية في السياق. في حال ضبط قيمة هذه المَعلمة على true وتم منح طلب التفويض، سيغطي رمز الدخول الجديد أيضًا أي نطاقات منح المستخدم إذن الوصول إليها سابقًا. راجِع قسم التفويض المتزايد للاطّلاع على أمثلة.

login_hint اختياريّ

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

اضبط قيمة المَعلمة على عنوان بريد إلكتروني أو معرّف sub، ما يعادل معرّف Google للمستخدم.

prompt اختياريّ

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

القيم المتاحة:

none لا تعرض أي شاشات مصادقة أو موافقة. يجب عدم تحديده مع قيم أخرى.
consent اطلب من المستخدم الموافقة.
select_account اطلب من المستخدم اختيار حساب.

الخطوة 2: إعادة التوجيه إلى خادم OAuth 2.0 من Google

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

PHP

  1. إنشاء عنوان URL لطلب الوصول من خادم OAuth 2.0 في Google:
    $auth_url = $client->createAuthUrl();
  2. إعادة توجيه المستخدم إلى "$auth_url":
    header('Location: ' . filter_var($auth_url, FILTER_SANITIZE_URL));

Python

يوضّح هذا المثال كيفية إعادة توجيه المستخدم إلى عنوان URL الخاص بالتفويض باستخدام إطار عمل تطبيق الويب Flask:

return flask.redirect(authorization_url)

Ruby

  1. إنشاء عنوان URL لطلب الوصول من خادم OAuth 2.0 في Google:
    auth_uri = authorizer.get_authorization_url(login_hint: user_id, request: request)
  2. إعادة توجيه المستخدِم إلى "auth_uri"

Node.js

  1. يمكنك استخدام عنوان URL الذي تم إنشاؤه authorizationUrl من طريقة الخطوة 1 generateAuthUrl لطلب الوصول من خادم OAuth 2.0 في Google.
  2. إعادة توجيه المستخدِم إلى "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 من خلال إكمال الخطوات التالية:

  1. إذا كنت بحاجة إلى تطبيق رمز دخول على عنصر Google\Client جديد، على سبيل المثال، في حال تخزين رمز الدخول في جلسة مستخدم، استخدِم طريقة setAccessToken:
    $client->setAccessToken($access_token);
  2. أنشِئ عنصر خدمة لواجهة برمجة التطبيقات التي تريد طلبها. يمكنك إنشاء عنصر خدمة من خلال تقديم عنصر Google\Client معتمد إلى الدالة الإنشائية لواجهة برمجة التطبيقات التي تريد طلبها. على سبيل المثال، لطلب بيانات YouTube Data API:
    $youtube = new Google_Service_YouTube($client);
  3. أرسِل طلبات إلى خدمة واجهة برمجة التطبيقات باستخدام الواجهة التي يوفّرها عنصر الخدمة. على سبيل المثال، لاستخدام YouTube Data API لاسترداد قائمة بأحداث البث المباشر لقناة المستخدم الذي تمت المصادقة عليه:
    $broadcasts = $youtube->liveBroadcasts->listLiveBroadcasts('id,snippet', [ 'mine' => true ]);

Python

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

  1. أنشِئ عنصر خدمة لواجهة برمجة التطبيقات التي تريد طلبها. يمكنك إنشاء عنصر خدمة من خلال استدعاء طريقة build في مكتبة googleapiclient.discovery مع اسم واجهة برمجة التطبيقات وإصدارها وبيانات اعتماد المستخدم: على سبيل المثال، لطلب الإصدار 3 من YouTube Data API:
    from googleapiclient.discovery import build
    
    youtube = build('youtube', 'v3', credentials=credentials)
  2. أرسِل طلبات إلى خدمة واجهة برمجة التطبيقات باستخدام الواجهة التي يوفّرها عنصر الخدمة. على سبيل المثال، لاستخدام YouTube Data API لاسترداد قائمة بأحداث البث المباشر لقناة المستخدم الذي تمت المصادقة عليه:
    broadcasts = youtube.liveBroadcasts().list(part='id,snippet', mine=True).execute()

Ruby

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

  1. أنشِئ عنصر خدمة لواجهة برمجة التطبيقات التي تريد طلبها. على سبيل المثال، لطلب الإصدار 3 من YouTube Data API:
    youtube = Google::Apis::YoutubeV3::YouTubeService.new
  2. اضبط بيانات الاعتماد في الخدمة:
    youtube.authorization = credentials
  3. أرسِل طلبات إلى خدمة واجهة برمجة التطبيقات باستخدام الواجهة التي يوفّرها عنصر الخدمة. على سبيل المثال، لاستخدام 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

لتشغيل هذا المثال:

  1. في API Console، أضِف عنوان URL للجهاز المحلي إلى قائمة عناوين URL لإعادة التوجيه، على سبيل المثال http://localhost:8080.
  2. أنشِئ دليلاً جديدًا وغيِّر إليه. مثلاً:
    mkdir ~/php-oauth2-example
    cd ~/php-oauth2-example
  3. ثبِّت مكتبة برامج Google API للغة PHP باستخدام Composer:
    composer require google/apiclient:^2.10
  4. أنشئ الملفين index.php وoauth2callback.php باستخدام المحتوى أدناه.
  5. شغّل المثال باستخدام خادم ويب تم تكوينه لعرض لغة 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

لتشغيل هذا المثال:

  1. في API Console، أضِف عنوان URL للجهاز المحلي إلى قائمة عناوين URL لإعادة التوجيه، على سبيل المثال، أضِف http://localhost.
  2. تأكَّد من تثبيت قناة الدعم الطويل الأمد (LTS) للصيانة أو قناة الدعم الطويل الأمد (LTS) أو الإصدار الحالي من Node.js.
  3. أنشِئ دليلاً جديدًا وغيِّر إليه. مثلاً:
    mkdir ~/nodejs-oauth2-example
    cd ~/nodejs-oauth2-example
  4. Install the Google API Client Library for Node.js using npm:
    npm install googleapis
  5. أنشئ الملفات main.js باستخدام المحتوى أدناه.
  6. شغِّل المثال التالي:
    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”.
  • لا يمكن أن تحتوي معرّفات الموارد المنتظمة (URI) الخاصة بإعادة التوجيه على نطاقات اختصارات عناوين URL (مثل goo.gl) ما لم يكن التطبيق يملك النطاق. بالإضافة إلى ذلك، إذا اختار تطبيق يملك نطاقًا أقصر إعادة التوجيه إلى ذلك النطاق، يجب أن يحتوي معرّف الموارد المنتظم (URI) لإعادة التوجيه هذا على “/google-callback/” في مساره أو أن ينتهي بـ “/google-callback”.
  • معلومات المستخدم

    لا يمكن أن تحتوي معرّفات الموارد المنتظمة (URI) الخاصة بإعادة التوجيه على المكوِّن الفرعي لـ userinfo.

    المسار

    لا يمكن أن تحتوي معرّفات الموارد المنتظمة (URI) الخاصة بإعادة التوجيه على اجتياز مسار (يُعرف أيضًا باسم تتبُّع الدليل)، والذي يتم تمثيله بـ “/..” أو “\..” أو ترميز عنوان URL الخاص بهما.

    طلب بحث

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

    الجزء

    لا يمكن أن تحتوي معرّفات الموارد المنتظمة (URI) لإعادة التوجيه على المكوِّن.

    الأحرف لا يمكن أن تحتوي معرّفات الموارد المنتظمة (URI) الخاصة بإعادة التوجيه على أحرف معيّنة، بما في ذلك:
    • أحرف البدل ('*')
    • أحرف ASCII غير قابلة للطباعة
    • ترميزات نسبة مئوية غير صالحة (أي ترميز نسبة مئوية لا يتبع شكل ترميز عنوان URL لعلامة نسبة مئوية متبوعة برقمين سداسيين عشري)
    • أحرف خالية (حرف فارغ مرمّز، مثل %00، %C0%80)

    التفويض التزايدي

    في بروتوكول 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 to offline 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 مع رمز الخطأ.