استفاده از OAuth 2.0 برای برنامه‌های سرور وب

این سند توضیح می‌دهد که چگونه برنامه‌های کارساز وب از «کتابخانه‌های کارخواه Google API» یا نقاط پایانی Google OAuth 2.0 برای پیاده‌سازی مجوز OAuth 2.0 جهت دسترسی به YouTube Analytics API یا YouTube Reporting API استفاده می‌کنند.

‫OAuth 2.0 به کاربران اجازه می‌دهد داده‌های خاصی را با برنامه هم‌رسانی کنند و درعین‌حال نام‌های کاربری، گذرواژه‌ها، و سایر اطلاعات خود را خصوصی نگه دارند. برای مثال، یک برنامه می‌تواند از OAuth 2.0 برای دریافت اجازه جهت بازیابی داده‌های YouTube Analytics یک کانال استفاده کند.

این جریان OAuth 2.0 به‌طور خاص برای صدور مجوز کاربر است. این جریان برای برنامه‌هایی طراحی شده است که می‌توانند اطلاعات محرمانه را ذخیره کنند و وضعیت را حفظ کنند. یک برنامه کارساز وب که به‌درستی مجوز گرفته باشد می‌تواند درحالی‌که کاربر با برنامه تعامل دارد یا پس‌از اینکه کاربر برنامه را ترک کرد، به میانای برنامه‌سازی کاربردی دسترسی پیدا کند.

برنامه‌های کارساز وب اغلب از حساب‌های سرویس نیز برای مجاز کردن درخواست‌های API استفاده می‌کنند، به‌ویژه هنگام فراخوانی Cloud APIs برای دسترسی به داده‌های مبتنی بر پروژه به‌جای داده‌های مختص کاربر. برنامه‌های کارساز وب می‌توانند از حساب‌های خدمات همراه با مجوز کاربر استفاده کنند.

  • ‫YouTube Analytics API از جریان حساب سرویس پشتیبانی نمی‌کند.
  • «API گزارش‌دهی YouTube» فقط از جریان حساب سرویس برای مالکان محتوای YouTube که مالک و مدیر چندین کانال YouTube هستند پشتیبانی می‌کند. به‌طور خاص، مالکان محتوا می‌توانند از حساب‌های سرویس در درخواست‌های API استفاده کنند که مقدار پارامتر درخواست onBehalfOfContentOwner را تنظیم می‌کنند.

کتابخانه‌های مشتری

نمونه‌های مختص زبان در این صفحه از کتابخانه‌های مشتری Google API برای پیاده‌سازی مجوز OAuth 2.0 استفاده می‌کنند. برای اجرای نمونه‌های کد، ابتدا باید کتابخانه مشتری را برای زبان خود نصب کنید.

وقتی از «کتابخانه کارخواه Google API» برای مدیریت جریان OAuth 2.0 برنامه‌تان استفاده می‌کنید، کتابخانه کارخواه بسیاری از کنش‌هایی را که برنامه درغیراین‌صورت باید خودش مدیریت کند انجام می‌دهد. برای مثال، این خط‌مشی تعیین می‌کند که برنامه چه زمانی می‌تواند از کد دسترسی ذخیره‌شده استفاده کند یا آن را بازآوری کند و همچنین چه زمانی برنامه باید دوباره رضایت کاربر را کسب کند. کتابخانه کارخواه همچنین نشانی‌های وب بازهدایت صحیح تولید می‌کند و به پیاده‌سازی گرداننده‌های بازهدایت که کدهای مجوز را با کد دسترسی معاوضه می‌کنند کمک می‌کند.

«کتابخانه‌های مشتری Google API» برای برنامه‌های سمت سرور به زبان‌های زیر دردسترس است:

پیش‌نیازها

فعال کردن میاناهای برنامه‌سازی کاربردی برای پروژه

هر برنامه‌ای که میاناهای برنامه‌سازی کاربردی Google را فراخوانی می‌کند باید آن میاناهای برنامه‌سازی کاربردی را در «کنسول میانای برنامه‌سازی کاربردی» فعال کند.

برای فعال کردن میانای برنامه‌سازی کاربردی برای پروژه‌تان:

  1. کتابخانه میانای برنامه‌سازی کاربردی را در «کنسول Google API» باز کنید.
  2. اگر درخواست شد، پروژه‌ای را انتخاب کنید یا پروژه جدیدی ایجاد کنید.
  3. از صفحه «کتابخانه» برای پیدا کردن و فعال کردن YouTube Analytics API و YouTube Reporting API استفاده کنید. بسیاری از برنامه‌هایی که داده‌های YouTube Analytics را بازیابی می‌کنند، با YouTube Data API نیز ارتباط برقرار می‌کنند. هر API دیگری را که برنامه‌تان استفاده می‌کند پیدا کنید و آن‌ها را نیز فعال کنید.

ایجاد اعتبارنامه‌های مجوز

هر برنامه‌ای که از OAuth 2.0 برای دسترسی به Google API استفاده می‌کند باید اعتبارنامه مجوز داشته باشد که برنامه را برای سرور OAuth 2.0 Google شناسایی کند. مراحل زیر نحوه ایجاد اعتبارنامه برای پروژه‌تان را توضیح می‌دهد. سپس برنامه‌هایتان می‌توانند از این اطلاعات اعتباری برای دسترسی به میاناهای برنامه‌سازی کاربردی‌ای که برای آن پروژه فعال کرده‌اید استفاده کنند.

  1. به صفحه کارخواهان بروید.
  2. روی ایجاد کارخواه کلیک کنید.
  3. نوع برنامه برنامه وب را انتخاب کنید.
  4. فرم را تکمیل کنید و روی ایجاد کلیک کنید. برنامه‌هایی که از زبان‌ها و چارچوب‌هایی مثل PHP،‏ Java،‏ Python،‏ Ruby، و .NET استفاده می‌کنند باید شناسه‌های منبع یکنواخت بازهدایت مجاز را مشخص کنند. URIهای هدایت نقاط پایانی هستند که سرور OAuth 2.0 می‌تواند پاسخ‌ها را به آن‌ها ارسال کند. این نقطه‌های پایانی باید از قوانین اعتبارسنجی Google پیروی کنند.

    برای آزمایش، می‌توانید نشانی‌های وب را که به ماشین محلی ارجاع می‌دهند مشخص کنید، برای نمونه http://localhost:8080. همه مثال‌های این سند از http://localhost:8080 به‌عنوان URI هدایت استفاده می‌کنند.

    توصیه می‌کنیم نقطه‌های پایانی اصالت‌سنجی برنامه‌تان را طراحی کنید تا برنامه شما کدهای مجوز را در صفحه درمعرض منابع دیگر قرار ندهد.

پس‌از ایجاد اطلاعات کاربری، فایل client_secret.json را از «کنسول API» بارگیری کنید. فایل را به‌طور ایمن در مکانی ذخیره کنید که فقط برنامه شما بتواند به آن دسترسی داشته باشد.

شناسایی کردن دامنه‌های دسترسی

محدوده‌ها به برنامه شما امکان می‌دهند فقط به منابعی که نیاز دارد دسترسی پیدا کند و درعین‌حال به کاربران امکان می‌دهند میزان دسترسی‌ای را که به برنامه شما می‌دهند کنترل کنند. بنابراین، ممکن است بین تعداد دامنه‌های درخواستی و احتمال دریافت رضایت کاربر رابطه معکوس وجود داشته باشد.

پیش‌از اینکه پیاده‌سازی مجوز OAuth 2.0 را شروع کنید، توصیه می‌کنیم محدوده‌هایی را که برنامه‌تان برای دسترسی به آن‌ها به اجازه نیاز دارد شناسایی کنید.

همچنین توصیه می‌کنیم که برنامه‌تان ازطریق فرایند احراز هویت فزاینده برای دسترسی به دامنه‌های احراز هویت درخواست دهد. در این فرایند، برنامه‌تان برای دسترسی به داده‌های کاربر در بافت درخواست می‌دهد. این روال مطلوب به کاربران کمک می‌کند راحت‌تر متوجه شوند چرا برنامه‌تان به دسترسی‌ای که درخواست می‌کند نیاز دارد.

‫YouTube Analytics API از دامنه‌های زیر استفاده می‌کند:

دامنه توضیحات
https://www. googleapis. com/ auth/ youtube حساب YouTube خود را مدیریت کنید
https://www. googleapis. com/ auth/ youtube. readonly حساب YouTube خود را مشاهده کنید
https://www. googleapis. com/ auth/ youtubepartner دارایی ها و محتوای مرتبط خود را در YouTube مشاهده و مدیریت کنید
https://www. googleapis. com/ auth/ yt-analytics-monetary. readonly گزارش های پولی و غیر پولی YouTube Analytics را برای محتوای YouTube خود مشاهده کنید
https://www. googleapis. com/ auth/ yt-analytics. readonly گزارش‌های YouTube Analytics را برای محتوای YouTube خود مشاهده کنید

‫YouTube Reporting API از دامنه‌های زیر استفاده می‌کند:

دامنه توضیحات
https://www. googleapis. com/ auth/ yt-analytics-monetary. readonly گزارش های پولی و غیر پولی YouTube Analytics را برای محتوای YouTube خود مشاهده کنید
https://www. googleapis. com/ auth/ yt-analytics. readonly گزارش‌های YouTube Analytics را برای محتوای YouTube خود مشاهده کنید

سند OAuth 2.0 API Scopes حاوی فهرست کاملی از دامنه‌هایی است که می‌توانید برای دسترسی به Google APIs استفاده کنید.

الزامات خاص زبان

برای اجرای هرکدام از نمونه کدهای موجود در این سند، به «حساب Google»، دسترسی به اینترنت، و مرورگر وب نیاز دارید. اگر از یکی از کتابخانه‌های کارخواه میانای برنامه‌سازی کاربردی استفاده می‌کنید، الزامات مختص زبان را نیز در بخش‌های زیر ببینید.

PHP

برای اجرای نمونه‌های کد PHP در این سند، به موارد زیر نیاز دارید:

  • ‫PHP نسخه ۸.۰ یا بالاتر با نصب میانای خط فرمان (CLI) و افزونه JSON.
  • ابزار مدیریت وابستگی Composer.
  • کتابخانه کارخواهان Google APIs برای PHP:

    composer require google/apiclient:^2.15.0

برای اطلاعات بیشتر، کتابخانه کارخواه Google APIs برای PHP را ببینید.

Python

برای اجرای نمونه‌های کد Python در این سند، به موارد زیر نیاز دارید:

  • ‫Python 3.7 یا بالاتر
  • ابزار مدیریت بسته pip.
  • انتشار «کتابخانه کارخواه Google APIs برای Python 2.0»:
    pip install --upgrade google-api-python-client
  • google-auth،‏ google-auth-oauthlib، و google-auth-httplib2 برای صدور مجوز کاربر.
    pip install --upgrade google-auth google-auth-oauthlib google-auth-httplib2
  • چارچوب برنامه وب Flask Python.
    pip install --upgrade flask
  • کتابخانه HTTP requests.
    pip install --upgrade requests

اگر نمی‌توانید پایتون و راهنمای انتقال مرتبط را ارتقا دهید، یادداشت انتشار کتابخانه کارخواه Google API Python را مرور کنید.

Ruby

برای اجرای نمونه‌های کد Ruby در این سند، به موارد زیر نیاز دارید:

  • Ruby نسخه ۲.۶ یا بالاتر
  • کتابخانه Google Auth برای Ruby:

    gem install googleauth
  • کتابخانه‌های کارخواه برای میاناهای برنامه‌سازی کاربردی Google Drive و «تقویم»:

    gem install google-apis-drive_v3 google-apis-calendar_v3
  • چارچوب برنامه وب 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. اگر کاربر اجازه‌های درخواست‌شده را اعطا کند، برنامه شما توکن‌های موردنیاز برای ارسال درخواست‌های میانای برنامه‌سازی کاربردی ازطرف کاربر را بازیابی می‌کند.

مرحله ۱: تنظیم پارامترهای مجوز

اولین قدم شما ایجاد درخواست مجوز است. این درخواست پارامترهایی را تنظیم می‌کند که برنامه شما را شناسایی می‌کند و اجازه‌هایی را که از کاربر خواسته می‌شود به برنامه شما اعطا کند تعریف می‌کند.

  • اگر از کتابخانه کارخواه Google برای اصالت‌سنجی و مجوزدهی OAuth 2.0 استفاده می‌کنید، شیئی را ایجاد و پیکربندی می‌کنید که این پارامترها را تعریف می‌کند.
  • اگر مستقیماً نقطه پایانی Google OAuth 2.0 را فراخوانی کنید، نشانی وب تولید خواهید کرد و پارامترها را در آن نشانی وب تنظیم خواهید کرد.

برگه‌های زیر پارامترهای مجوز پشتیبانی‌شده را برای برنامه‌های سرور وب تعریف می‌کنند. مثال‌های مختص زبان همچنین نشان می‌دهند که چگونه از کتابخانه کارخواه یا کتابخانه مجوز برای پیکربندی شیئی که این پارامترها را تنظیم می‌کند استفاده کنید:

PHP

تکه‌کد زیر شیء Google\Client() را ایجاد می‌کند که پارامترهای درخواست صدور مجوز را تعریف می‌کند.

آن شیء از اطلاعات فایل client_secret.json برای شناسایی برنامه شما استفاده می‌کند. (برای اطلاعات بیشتر درباره آن فایل، به ایجاد اعتبارنامه مجوز مراجعه کنید.) این شیء همچنین دامنه‌هایی را که برنامه‌تان برای دسترسی به آن‌ها درخواست اجازه می‌کند و نشانی وب نقطه پایانی اصالت‌سنجی برنامه‌تان را که پاسخ سرور OAuth 2.0 در Google را مدیریت می‌کند شناسایی می‌کند. در نهایت، کد پارامترهای اختیاری access_type و include_granted_scopes را تنظیم می‌کند.

برای مثال، برای درخواست دسترسی آفلاین برای بازیابی گزارش‌های YouTube Analytics کاربر:

use Google\Client;

$client = new Client();

// Required, call the setAuthConfig function to load authorization credentials from
// client_secret.json file.
$client->setAuthConfig('client_secret.json');

// Required, to set the scope value, call the addScope function
$client->addScope(Google_Service_YouTubeAnalytics::YT_ANALYTICS_READONLY);

// Required, call the setRedirectUri function to specify a valid redirect URI for the
// provided client_id
$client->setRedirectUri('http://' . $_SERVER['HTTP_HOST'] . '/oauth2callback.php');

// Recommended, offline access will give you both an access and refresh token so that
// your app can refresh the access token without user interaction.
$client->setAccessType('offline');

// Recommended, call the setState function. Using a state value can increase your assurance that
// an incoming connection is the result of an authentication request.
$client->setState($sample_passthrough_value);

// Optional, if your application knows which user is trying to authenticate, it can use this
// parameter to provide a hint to the Google Authentication Server.
$client->setLoginHint('hint@example.com');

// Optional, call the setPrompt function to set "consent" will prompt the user for consent
$client->setPrompt('consent');

// Optional, call the setIncludeGrantedScopes function with true to enable incremental
// authorization
$client->setIncludeGrantedScopes(true);

Python

تکه کد زیر از واحد google-auth-oauthlib.flow برای ساختن درخواست مجوز استفاده می‌کند.

این کد شیء Flow را می‌سازد که برنامه شما را بااستفاده از اطلاعات فایل client_secret.json که پس‌از ایجاد اطلاعات اعتباری مجوز بارگیری کرده‌اید شناسایی می‌کند. آن شیء همچنین دامنه‌هایی را که برنامه شما برای دسترسی به آن‌ها اجازه درخواست می‌کند و نشانی وب نقطه پایانی اصالت‌سنجی برنامه شما را که پاسخ سرور OAuth 2.0 از Google را مدیریت می‌کند مشخص می‌کند. در نهایت، کد پارامترهای اختیاری access_type و include_granted_scopes را تنظیم می‌کند.

برای مثال، برای درخواست دسترسی آفلاین برای بازیابی گزارش‌های YouTube Analytics کاربر:

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/yt-analytics.readonly',
            'https://www.googleapis.com/auth/calendar.readonly'])

# Required, indicate where the API server will redirect the user after the user completes
# the authorization flow. The redirect URI is required. The value must exactly
# match one of the authorized redirect URIs for the OAuth 2.0 client, which you
# configured in the API Console. If this value doesn't match an authorized URI,
# you will get a 'redirect_uri_mismatch' error.
flow.redirect_uri = 'https://www.example.com/oauth2callback'

# Generate URL for request to Google's OAuth 2.0 server.
# Use kwargs to set optional request parameters.
authorization_url, state = flow.authorization_url(
    # Recommended, enable offline access so that you can refresh an access token without
    # re-prompting the user for permission. Recommended for web server apps.
    access_type='offline',
    # Optional, enable incremental authorization. Recommended as a best practice.
    include_granted_scopes='true',
    # Optional, if your application knows which user is trying to authenticate, it can use this
    # parameter to provide a hint to the Google Authentication Server.
    login_hint='hint@example.com',
    # Optional, set prompt to 'consent' will prompt the user for consent
    prompt='consent')

Ruby

از فایل client_secrets.json که ایجاد کرده‌اید برای پیکربندی شیء کارخواه در برنامه‌تان استفاده کنید. وقتی شیء کارخواه را پیکربندی می‌کنید، دامنه‌هایی را که برنامه‌تان برای دسترسی نیاز دارد، به‌همراه نشانی وب نقطه پایانی اصالت‌سنجی برنامه‌تان که پاسخ را از سرور OAuth 2.0 مدیریت می‌کند، مشخص می‌کنید.

برای مثال، برای درخواست دسترسی آفلاین برای بازیابی گزارش‌های YouTube Analytics کاربر:

require 'googleauth'
require 'googleauth/web_user_authorizer'
require 'googleauth/stores/redis_token_store'

require 'google/apis/youtube_analytics_v2'
require 'google/apis/calendar_v3'

# Required, call the from_file method to retrieve the client ID from a
# client_secret.json file.
client_id = Google::Auth::ClientId.from_file('/path/to/client_secret.json')

# Required, scope value 
# Access scopes for two non-Sign-In scopes: Read-only Drive activity and Google Calendar.
scope = ['Google::Apis::DriveV3::AUTH_DRIVE_METADATA_READONLY',
         'Google::Apis::CalendarV3::AUTH_CALENDAR_READONLY']

# Required, Authorizers require a storage instance to manage long term persistence of
# access and refresh tokens.
token_store = Google::Auth::Stores::RedisTokenStore.new(redis: Redis.new)

# Required, indicate where the API server will redirect the user after the user completes
# the authorization flow. The redirect URI is required. The value must exactly
# match one of the authorized redirect URIs for the OAuth 2.0 client, which you
# configured in the API Console. If this value doesn't match an authorized URI,
# you will get a 'redirect_uri_mismatch' error.
callback_uri = '/oauth2callback'

# To use OAuth2 authentication, we need access to a CLIENT_ID, CLIENT_SECRET, AND REDIRECT_URI
# from the client_secret.json file. To get these credentials for your application, visit
# https://console.cloud.google.com/apis/credentials.
authorizer = Google::Auth::WebUserAuthorizer.new(client_id, scope,
                                                token_store, callback_uri)

برنامه شما از شیء کارخواه برای انجام عملیات OAuth 2.0، مثل تولید نشانی‌های وب درخواست مجوز و اعمال کدهای دسترسی در درخواست‌های HTTP استفاده می‌کند.

Node.js

تکه‌کد زیر شیء google.auth.OAuth2 را ایجاد می‌کند که پارامترهای درخواست صدور مجوز را تعریف می‌کند.

آن شیء از اطلاعات فایل client_secret.json برای شناسایی برنامه شما استفاده می‌کند. برای درخواست اجازه از کاربر برای بازیابی کد دسترسی، او را به صفحه رضایت هدایت می‌کنید. برای ایجاد نشانی وب صفحه رضایت:

const {google} = require('googleapis');
const crypto = require('crypto');
const express = require('express');
const session = require('express-session');

/**
 * To use OAuth2 authentication, we need access to a CLIENT_ID, CLIENT_SECRET, AND REDIRECT_URI
 * from the client_secret.json file. To get these credentials for your application, visit
 * https://console.cloud.google.com/apis/credentials.
 */
const oauth2Client = new google.auth.OAuth2(
  YOUR_CLIENT_ID,
  YOUR_CLIENT_SECRET,
  YOUR_REDIRECT_URL
);

// Access scopes for two non-Sign-In scopes: Read-only Drive activity and Google Calendar.
const scopes = [
  'https://www.googleapis.com/auth/yt-analytics.readonly',
  'https://www.googleapis.com/auth/calendar.readonly'
];

// Generate a secure random state value.
const state = crypto.randomBytes(32).toString('hex');

// Store state in the session
req.session.state = state;

// Generate a url that asks permissions for the Drive activity and Google Calendar scope
const authorizationUrl = oauth2Client.generateAuthUrl({
  // 'online' (default) or 'offline' (gets refresh_token)
  access_type: 'offline',
  /** Pass in the scopes array defined above.
    * Alternatively, if only one scope is needed, you can pass a scope URL as a string */
  scope: scopes,
  // Enable incremental authorization. Recommended as a best practice.
  include_granted_scopes: true,
  // Include the state parameter to reduce the risk of CSRF attacks.
  state: state
});

نکته مهم - refresh_token فقط در اولین مجوز برگردانده می‌شود. جزئیات بیشتر اینجا.

HTTP/REST

نقطه پایان OAuth 2.0 در Google در https://accounts.google.com/o/oauth2/v2/auth قرار دارد. این نقطه پایانی فقط ازطریق HTTPS قابل‌دسترسی است. اتصال‌های HTTP ساده رد می‌شوند.

سرور مجوز Google از پارامترهای رشته پُرسمان زیر برای برنامه‌های سرور وب پشتیبانی می‌کند:

پارامترها
client_id الزامی

شناسه کارخواه برای برنامه شما. این مقدار را می‌توانید در «کنسول Cloud» صفحه «کارخواه‌ها» پیدا کنید.

redirect_uri الزامی

تعیین می‌کند که سرور میانای برنامه‌سازی کاربردی پس‌از تکمیل جریان مجوز توسط کاربر، او را به کجا هدایت کند. این مقدار باید دقیقاً با یکی از URIهای هدایت مجاز برای کارخواه OAuth 2.0 که در صفحه «کارخواه‌ها» در Cloud Console کارخواه پیکربندی کرده‌اید مطابقت داشته باشد. اگر این مقدار با نشانی وب بازگردان مجاز برای client_id ارائه‌شده مطابقت نداشته باشد، خطای redirect_uri_mismatch دریافت خواهید کرد.

توجه داشته باشید که طرح http یا https، حروف بزرگ و کوچک، و خط مورب پایانی ('/') باید همگی مطابقت داشته باشند.

response_type الزامی

تعیین می‌کند که آیا نقطه پایان Google OAuth 2.0 کد مجوز برمی‌گرداند یا نه.

برای برنامه‌های کارساز وب، مقدار پارامتر را روی code تنظیم کنید.

scope الزامی

فهرست جداشده با فاصله از حوزه‌هایی که منابعی را که برنامه شما می‌تواند ازطرف کاربر به آن‌ها دسترسی داشته باشد شناسایی می‌کند. این مقادیر به صفحه موافقت که Google به کاربر نمایش می‌دهد اطلاع می‌دهد.

محدوده‌ها به برنامه شما امکان می‌دهند فقط برای دسترسی به منابعی که نیاز دارد درخواست دهد و درعین‌حال به کاربران امکان می‌دهد میزان دسترسی‌ای را که به برنامه شما می‌دهند کنترل کنند. بنابراین، رابطه‌ای معکوس بین تعداد دامنه‌های درخواستی و احتمال کسب رضایت کاربر وجود دارد.

‫YouTube Analytics API از دامنه‌های زیر استفاده می‌کند:

دامنه توضیحات
https://www. googleapis. com/ auth/ youtube حساب YouTube خود را مدیریت کنید
https://www. googleapis. com/ auth/ youtube. readonly حساب YouTube خود را مشاهده کنید
https://www. googleapis. com/ auth/ youtubepartner دارایی ها و محتوای مرتبط خود را در YouTube مشاهده و مدیریت کنید
https://www. googleapis. com/ auth/ yt-analytics-monetary. readonly گزارش های پولی و غیر پولی YouTube Analytics را برای محتوای YouTube خود مشاهده کنید
https://www. googleapis. com/ auth/ yt-analytics. readonly گزارش‌های YouTube Analytics را برای محتوای YouTube خود مشاهده کنید

‫YouTube Reporting API از دامنه‌های زیر استفاده می‌کند:

دامنه توضیحات
https://www. googleapis. com/ auth/ yt-analytics-monetary. readonly گزارش های پولی و غیر پولی YouTube Analytics را برای محتوای YouTube خود مشاهده کنید
https://www. googleapis. com/ auth/ yt-analytics. readonly گزارش‌های YouTube Analytics را برای محتوای YouTube خود مشاهده کنید

سند OAuth 2.0 API Scopes فهرست کاملی از دامنه‌هایی را که ممکن است برای دسترسی به Google APIs استفاده کنید ارائه می‌دهد.

توصیه می‌کنیم برنامه شما هرزمان ممکن بود برای دامنه‌های مجوز در بافت درخواست دسترسی کند. با درخواست دسترسی به داده‌های کاربر در بافت، بااستفاده از مجوز فزاینده، به کاربران کمک می‌کنید متوجه شوند چرا برنامه‌تان به دسترسی‌ای که درخواست می‌کند نیاز دارد.

access_type توصیه‌شده

نشان می‌دهد که آیا برنامه شما می‌تواند کد دسترسی را وقتی کاربر در مرورگر حضور ندارد بازآوری کند یا نه. مقادیر پارامتر معتبر عبارتند از online، که مقدار پیش‌فرض است، و offline.

اگر برنامه شما نیاز دارد که وقتی کاربر در مرورگر حضور ندارد رمزهای دسترسی را بازآوری کند، مقدار را روی offline تنظیم کنید. این روش بازآوری کدهای دسترسی است که در ادامه این سند شرح داده شده است. این مقدار به سرور مجوز Google دستور می‌دهد اولین باری که برنامه شما کد مجوز را با ژتون‌ها معاوضه می‌کند، ژتون بازآوری و کد دسترسی را برگرداند.

state توصیه‌شده

هر مقدار رشته‌ای را که برنامه شما برای حفظ وضعیت بین درخواست صدور مجوز و پاسخ سرور صدور مجوز استفاده می‌کند مشخص می‌کند. پس‌از اینکه کاربر با درخواست دسترسی برنامه شما موافقت کرد یا آن را رد کرد، سرور مقدار دقیقی را که به‌عنوان جفت name=value در عنصر پُرسمان نشانی وب (?) از redirect_uri ارسال می‌کنید برمی‌گرداند.

می‌توانید از این پارامتر برای اهداف مختلفی استفاده کنید، ازجمله هدایت کاربر به منبع صحیح در برنامه‌تان، ارسال نانس، و کاهش جعل درخواست بین‌سایتی. ازآنجایی‌که redirect_uri شما قابل حدس زدن است، استفاده از مقدار state می‌تواند اطمینان شما را از اینکه اتصال ورودی نتیجه درخواست اصالت‌سنجی است افزایش دهد. اگر رشته‌ای تصادفی تولید کنید یا درهم‌سازی کوکی یا مقدار دیگری را که وضعیت مشتری را ضبط می‌کند کدبندی کنید، می‌توانید پاسخ را اعتبارسنجی کنید تا علاوه‌براین مطمئن شوید درخواست و پاسخ در یک مرورگر ایجاد شده‌اند و دربرابر حملاتی مثل جعل درخواست بین‌سایتی محافظت کنید. برای دیدن نمونه‌ای از نحوه ایجاد و تأیید کردن کد state، به اسناد OpenID Connect مراجعه کنید.

include_granted_scopes اختیاری

برنامه‌ها را قادر می‌سازد تا از مجوز افزایشی برای درخواست دسترسی به دامنه‌های اضافی در بافت استفاده کنند. اگر مقدار این پارامتر را روی true تنظیم کنید و درخواست صدور مجوز اعطا شود، رمز دسترسی جدید همچنین شامل هر محدوده‌ای می‌شود که کاربر قبلاً به برنامه اجازه دسترسی به آن را داده است. برای مشاهده نمونه‌ها، بخش مجوز افزایشی را ببینید.

login_hint اختیاری

اگر برنامه شما می‌داند کدام کاربر درحال تلاش برای اصالت‌سنجی است، می‌تواند از این پارامتر برای ارائه راهنمایی به «سرور اصالت‌سنجی Google» استفاده کند. سرور از این اشاره برای ساده کردن جریان ورود به سیستم استفاده می‌کند، یا با ازپیش پر کردن فیلد ایمیل در فرم ورود به سیستم یا با انتخاب جلسه ورود به سیستم چندگانه مناسب.

مقدار پارامتر را روی نشانی ایمیل یا شناسه sub تنظیم کنید که معادل شناسه Google کاربر است.

prompt اختیاری

فهرست پیام‌واره‌های حساس به حروف بزرگ و کوچک که با فاصله از هم جدا شده‌اند و به کاربر ارائه می‌شود. اگر این پارامتر را مشخص نکنید، کاربر فقط اولین‌باری که پروژه شما درخواست دسترسی می‌کند از او درخواست می‌شود. برای اطلاعات بیشتر، درخواست رضایت مجدد را ببینید.

مقادیر ممکن عبارت‌اند از:

none هیچ صفحه اصالت‌سنجی یا رضایتی را نمایش ندهید. نباید با مقادیر دیگر مشخص شود.
consent از کاربر برای کسب رضایت درخواست کنید.
select_account از کاربر بخواهید حسابی را انتخاب کند.

مرحله ۲: هدایت به سرور OAuth 2.0 Google

کاربر را به سرور OAuth 2.0 Google هدایت کنید تا فرایند اصالت‌سنجی و صدور مجوز را آغاز کند. معمولاً این اتفاق زمانی می‌افتد که برنامه شما برای اولین‌بار نیاز به دسترسی به داده‌های کاربر دارد. در مورد صدور مجوز افزایشی، این مرحله همچنین زمانی رخ می‌دهد که برنامه شما برای اولین‌بار نیاز به دسترسی به منابع اضافی دارد که اجازه دسترسی به آن‌ها را ندارد.

PHP

  1. نشانی وبی برای درخواست دسترسی از سرور OAuth 2.0 متعلق به Google ایجاد کنید:
    $auth_url = $client->createAuthUrl();
  2. هدایت کاربر به $auth_url:
    header('Location: ' . filter_var($auth_url, FILTER_SANITIZE_URL));

Python

این مثال نشان می‌دهد که چگونه می‌توان کاربر را بااستفاده از چارچوب برنامه وب Flask به نشانی وب اصالت‌سنجی هدایت کرد:

return flask.redirect(authorization_url)

Ruby

  1. نشانی وبی برای درخواست دسترسی از سرور OAuth 2.0 Google تولید کنید:
    auth_uri = authorizer.get_authorization_url(request: request)
  2. کاربر را به auth_uri هدایت کنید.

Node.js

  1. از نشانی وب تولیدشده authorizationUrl از روش مرحله ۱ generateAuthUrl برای درخواست دسترسی از سرور Google OAuth 2.0 استفاده کنید.
  2. کاربر را به authorizationUrl هدایت کنید.
    res.redirect(authorizationUrl);

HTTP/REST

نمونه هدایت به سرور مجوز Google

نمونه نشانی وب زیر دسترسی آفلاین (access_type=offline) به دامنه‌ای را درخواست می‌کند که اجازه دسترسی برای بازیابی گزارش‌های YouTube Analytics کاربر را می‌دهد. این روش از صدور مجوز افزایشی استفاده می‌کند تا مطمئن شود که رمز دسترسی جدید همه حوزه‌هایی را که کاربر قبلاً به برنامه دسترسی داده است پوشش می‌دهد. نشانی وب همچنین مقادیر پارامترهای الزامی redirect_uri،‏ response_type، و client_id و همچنین پارامتر state را تنظیم می‌کند. نشانی وب حاوی شکستگی خط و فاصله برای خوانایی است.

https://accounts.google.com/o/oauth2/v2/auth?
 scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fyt-analytics.readonly&
 access_type=offline&
 include_granted_scopes=true&
 state=state_parameter_passthrough_value&
 redirect_uri=http%3A%2F%2Flocalhost%2Foauth2callback&
 response_type=code&
 client_id=client_id

پس‌از ایجاد نشانی وب درخواست، کاربر را به آن هدایت کنید.

سرور OAuth 2.0 متعلق به Google کاربر را اصالت‌سنجی می‌کند و موافقت کاربر را برای دسترسی برنامه شما به دامنه‌های درخواستی دریافت می‌کند. پاسخ بااستفاده از نشانی وب هدایت مجددی که مشخص کرده‌اید به برنامه‌تان ارسال می‌شود.

مرحله ۳: Google از کاربر درخواست رضایت می‌کند

در این مرحله، کاربر تصمیم می‌گیرد که دسترسی درخواستی را به برنامه شما اعطا کند یا نه. در این مرحله، Google پنجره رضایتی را نمایش می‌دهد که نام برنامه شما و سرویس‌های Google API را که برنامه برای دسترسی به آن‌ها با اطلاعات اعتباری مجوز کاربر درخواست اجازه می‌کند و خلاصه‌ای از دامنه‌های دسترسی که باید اعطا شود نشان می‌دهد. سپس کاربر می‌تواند با اعطای دسترسی به یک یا چند حوزه درخواست‌شده توسط برنامه شما موافقت کند یا درخواست را رد کند.

برنامه شما در این مرحله نیازی به انجام کاری ندارد زیرا منتظر پاسخ سرور OAuth 2.0 از Google است که نشان می‌دهد آیا دسترسی اعطا شده است یا خیر. آن پاسخ در مرحله زیر توضیح داده شده است.

خطاها

درخواست‌ها به نقطه پایانی مجوز OAuth 2.0 در Google ممکن است به‌جای جریان‌های اصالت‌سنجی و مجوز موردانتظار، پیام‌های خطای روبه‌کاربر نمایش دهند. کدهای خطای رایج و راه‌حل‌های پیشنهادی عبارت‌اند از:

admin_policy_enforced

«حساب Google» به‌دلیل خط‌مشی‌های سرپرست Google Workspace خود نمی‌تواند یک یا چند حوزه درخواستی را مجاز کند. برای اطلاعات بیشتر درباره اینکه سرپرست چگونه می‌تواند دسترسی به همه حوزه‌ها یا حوزه‌های حساس و محدودشده را تا زمانی که دسترسی به‌طور صریح به شناسه مشتری OAuth شما اعطا شود محدود کند، به مقاله راهنمای «سرپرست Google Workspace» مراجعه کنید کنترل کنید کدام برنامه‌های طرف سوم و داخلی به داده‌های Google Workspace دسترسی داشته باشند.

disallowed_useragent

نقطه پایان مجوز در نماینده کاربر جاسازی‌شده‌ای نمایش داده می‌شود که طبق خط‌مشی‌های OAuth 2.0 Google مجاز نیست.

توسعه‌دهندگان iOS و macOS ممکن است هنگام باز کردن درخواست‌های مجوز در WKWebView با این خطا مواجه شوند. توسعه‌دهندگان باید به‌جای آن از کتابخانه‌های iOS مانند ورود به سیستم با Google برای iOS یا AppAuth برای iOS از OpenID Foundation استفاده کنند.

توسعه‌دهندگان وب ممکن است با این خطا مواجه شوند وقتی برنامه iOS یا macOS پیوند وب عمومی را در نماینده کاربر جاسازی‌شده باز می‌کند و کاربر از سایت شما به نقطه پایانی مجوز OAuth 2.0 Google می‌رود. توسعه‌دهندگان باید اجازه دهند پیوندهای عمومی در مدیریت‌کننده پیوند پیش‌فرض سیستم‌عامل باز شوند، که شامل هر دو مدیریت‌کننده پیوندهای جهانی یا برنامه مرورگر پیش‌فرض می‌شود. کتابخانه SFSafariViewController نیز گزینه پشتیبانی‌شده‌ای است.

org_internal

شناسه کارخواه OAuth در درخواست بخشی از پروژه‌ای است که دسترسی به «حساب‌های Google» را در سازمان Google Cloud خاصی محدود می‌کند. برای اطلاعات بیشتر درباره این گزینه پیکربندی، به بخش نوع کاربر در مقاله راهنمای «راه‌اندازی صفحه موافقت OAuth» مراجعه کنید.

invalid_client

رمز کارخواه OAuth نادرست است. پیکربندی کارخواه OAuth، ازجمله شناسه کارخواه و رمز استفاده‌شده برای این درخواست را مرور کنید.

deleted_client

کارخواه OAuth که برای ایجاد درخواست استفاده می‌شود حذف شده است. حذف می‌تواند به‌صورت دستی یا به‌طور خودکار درصورت استفاده نشدن از کارخواه‌ها انجام شود. مشتریان حذف‌شده را می‌توان ظرف ۳۰ روز پس‌از حذف بازیابی کرد. بیشتر بدانید .

invalid_grant

هنگام بازآوری کد دسترسی یا استفاده از مجوز افزایشی، ممکن است کد منقضی شده باشد یا نامعتبر شده باشد. دوباره کاربر را اصالت‌سنجی کنید و برای دریافت کردن توکن‌های جدید از کاربر رضایت بگیرید. اگر همچنان این خطا را می‌بینید، مطمئن شوید که برنامه‌تان به‌درستی پیکربندی شده است و از نشان‌ها و پارامترهای صحیح در درخواستتان استفاده می‌کنید. درغیراین‌صورت، ممکن است حساب کاربر حذف یا غیرفعال شده باشد.

redirect_uri_mismatch

redirect_uri ارسال‌شده در درخواست مجوز با نشانی وب هدایت مجاز برای شناسه کارخواه OAuth مطابقت ندارد. نشانی‌های وب هدایت مجاز را در Google Cloud Console صفحه «کارخواه‌ها» مرور کنید.

پارامتر redirect_uri ممکن است به جریان OAuth خارج‌از باند (OOB) اشاره داشته باشد که منسوخ شده است و دیگر پشتیبانی نمی‌شود. برای به‌روزرسانی ادغام، به راهنمای انتقال مراجعه کنید.

invalid_request

مشکلی در درخواست شما وجود داشت. این مشکل ممکن است به چند دلیل باشد:

  • درخواست به‌درستی قالب‌بندی نشده بود
  • پارامترهای الزامی در درخواست وجود نداشت
  • درخواست از روش صدور مجوزی استفاده می‌کند که Google از آن پشتیبانی نمی‌کند. تأیید کنید که ادغام OAuth شما از روش ادغام توصیه‌شده استفاده می‌کند

مرحله ۴: رسیدگی به پاسخ سرور OAuth 2.0

سرور OAuth 2.0 بااستفاده از نشانی وب مشخص‌شده در درخواست، به درخواست دسترسی برنامه‌تان پاسخ می‌دهد.

اگر کاربر درخواست دسترسی را تأیید کند، پاسخ حاوی کد مجوز خواهد بود. اگر کاربر درخواست را تأیید نکند، پاسخ حاوی پیام خطا خواهد بود. کد مجوز یا پیام خطایی که به سرور وب برگردانده می‌شود در رشته پُرسمان ظاهر می‌شود، همان‌طور که در مثال‌های زیر نشان داده شده است:

پاسخ خطا:

https://oauth2.example.com/auth?error=access_denied

پاسخ کد مجوز:

https://oauth2.example.com/auth?code=4/P7q7W91a-oMsCeLvIaQm6bTrgtp7

نمونه پاسخ سرور OAuth 2.0

می‌توانید این جریان را با کلیک کردن روی نمونه نشانی وب زیر آزمایش کنید، که دسترسی فقط خواندنی برای مشاهده فراداده فایل‌های موجود در Google Drive شما و دسترسی فقط خواندنی برای مشاهده رویدادهای «تقویم Google» شما را درخواست می‌کند:

https://accounts.google.com/o/oauth2/v2/auth?
 scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fyt-analytics.readonly&
 access_type=offline&
 include_granted_scopes=true&
 state=state_parameter_passthrough_value&
 redirect_uri=http%3A%2F%2Flocalhost%2Foauth2callback&
 response_type=code&
 client_id=client_id

پس‌از تکمیل جریان OAuth 2.0، مرورگرتان شما را به OAuth 2.0 Playground هدایت می‌کند که ابزاری برای آزمایش جریان‌های OAuth است. خواهید دید که OAuth 2.0 Playground به‌طور خودکار کد صدور مجوز را ضبط کرده است.

مرحله ۵: معاوضه کد مجوز با ژتون‌های بازآوری و دسترسی

پس‌از اینکه سرور وب کد مجوز را دریافت کرد، می‌تواند کد مجوز را با کد دسترسی معاوضه کند.

PHP

برای تبدیل کد مجوز به کد دسترسی، از روش fetchAccessTokenWithAuthCode استفاده کنید:

$access_token = $client->fetchAccessTokenWithAuthCode($_GET['code']);

Python

در صفحه بازگشت تماس، از کتابخانه google-auth برای تأیید پاسخ سرور مجوزدهی استفاده کنید. سپس، از روش flow.fetch_token برای مبادله کد مجوز در آن پاسخ با کد دسترسی استفاده کنید:

state = flask.session['state']
flow = google_auth_oauthlib.flow.Flow.from_client_secrets_file(
    'client_secret.json',
    scopes=['https://www.googleapis.com/auth/yt-analytics.readonly'],
    state=state)
flow.redirect_uri = flask.url_for('oauth2callback', _external=True)

authorization_response = flask.request.url
flow.fetch_token(authorization_response=authorization_response)

# Store the credentials in browser session storage, but for security: client_id, client_secret,
# and token_uri are instead stored only on the backend server.
credentials = flow.credentials
flask.session['credentials'] = {
    'token': credentials.token,
    'refresh_token': credentials.refresh_token,
    'granted_scopes': credentials.granted_scopes}

Ruby

در صفحه برگشت تماس، از کتابخانه googleauth برای درستی‌سنجی پاسخ سرور مجوز استفاده کنید. از روش authorizer.handle_auth_callback_deferred برای ذخیره کردن کد مجوز و هدایت مجدد به نشانی وبی که در ابتدا درخواست مجوز کرده بود استفاده کنید. این کار تبادل کد را با ذخیره موقت نتایج در جلسه کاربر به‌تعویق می‌اندازد.

  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 شناسه کارخواه از Cloud Console صفحه کارخواه‌ها.
client_secret اختیاری

رمز کارخواه به‌دست‌آمده از صفحه کارخواه‌ها در «کنسول Cloud».

code کد مجوز برگشت‌داده‌شده از درخواست اولیه.
grant_type همان‌طور که در مشخصات OAuth 2.0 تعریف شده است، مقدار این فیلد باید روی authorization_code تنظیم شود.
redirect_uri یکی از URIهای هدایت فهرست‌شده برای پروژه‌تان در صفحه کارخواه‌ها در Cloud Console برای client_id داده‌شده.

اگرچه استفاده از DPoP اختیاری است، اما برای افزایش امنیت توصیه می‌شود. امنیت DPoP به محدود بودن کلید خصوصی به یک دستگاه بستگی دارد؛ توصیه می‌کنیم آن را به‌گونه‌ای ذخیره کنید که نتوان آن را از دستگاه کپی کرد، مثلاً بااستفاده از TPM،‏ Secure Enclave، یا دیگر محل‌های ذخیره کلید با پشتیبانی سخت‌افزاری. برای استفاده از DPoP، برنامه شما باید برای هر درخواست به نقطه پایانی توکن، یک JWT اثبات DPoP جدید و منحصربه‌فرد تولید کند و آن را به‌عنوان سرصفحه درخواست HTTP اضافه کند.

سرایند الزامی شرح
DPoP اختیاری اثبات DPoP یک JWT است که مالکیت کلید خصوصی را اثبات می‌کند. این سرصفحه است، نه پارامتر. درصورت ارائه، نشان‌های برگردانده‌شده به این کلید محدود می‌شوند. برای هر درخواست باید مدرک جدید و منحصربه‌فردی تولید شود و باید شامل ادعاهای htm (روش HTTP) و htu (شناسه منبع یکسان HTTP) باشد که با درخواست مطابقت داشته باشد.

تکه زیر یک درخواست نمونه را نشان می‌دهد:

POST /token HTTP/1.1
Host: oauth2.googleapis.com
Content-Type: application/x-www-form-urlencoded
DPoP: eyJ0eXAiOiJkcG9wK2p3dCIsImFsZyI6IkVTMjU2IiwiandrIjp7Imt0eSI6Ik\
 VDIiwieCI6Imw4dEZyaHgtMzR0VjNoUklDUkRZOXpDa0RscEJoRjQyVVFVZldWQVdCR\
 nMiLCJ5IjoiOVZFNGpmX09rX282NHpiVFRsY3VOSmFqSG10NnY5VERWclUwQ2R2R1JE\
 QSIsImNydiI6IlAtMjU2In19.eyJqdGkiOiItQndDM0VTYzZhY2MybFRjIiwiaHRtIj\
 oiUE9TVCIsImh0dSI6Imh0dHBzOi8vc2VydmVyLmV4YW1wbGUuY29tL3Rva2VuIiwia\
 WF0IjoxNTYyMjYyNjE2fQ.2-GxA6T8lP4vfrg8v-FdWP0A0zdrj8igiMLvqRMUvwnQg\
 4PtFLbdLXiOSsX0x7NVY-FNyJK70nfbV37xRZT3Lg

code=4/P7q7W91a-oMsCeLvIaQm6bTrgtp7&
client_id=your_client_id&
redirect_uri=https%3A//developers.google.com/oauthplayground&
grant_type=authorization_code

ساختن مدرک DPoP

مراحل زیر نحوه ساختن گواه DPoP بااستفاده از OpenSSL از خط فرمان را نشان می‌دهد:

  1. تولید جفت کلید EC P-256:
    openssl ecparam -name prime256v1 -genkey -noout -out dpop_private.pem
    openssl ec -in dpop_private.pem -pubout -out dpop_public.pem
  2. ایجاد سرصفحه DPoP:

    سرصفحه باید شامل ادعاهای typ، alg، و jwk (کلید عمومی) باشد. مقادیر x و y مختصات کدبندی‌شده Base64Url کلید عمومی EC شما هستند. این JSON را با Base64Url کدبندی کنید:

    {
      "typ":"dpop+jwt",
      "alg":"ES256",
      "jwk": {
        "kty":"EC",
        "x":"YOUR_PUBLIC_KEY_X",
        "y":"YOUR_PUBLIC_KEY_Y",
        "crv":"P-256"
      }
    }
  3. ایجاد بار داده DPoP:

    بار باید شامل jti (شناسه یکتای درخواست)، htm (روش HTTP، برای نمونه، POST)، htu (نشانی وب HTTP، برای نمونه، https://oauth2.googleapis.com/token)، و iat (زمان صدور) باشد. اگر در پاسخ به درخواست قبلی، یک nonce از سرور در سرصفحه DPoP-Nonce دریافت کردید، باید آن مقدار nonce را در ادعای nonce اضافه کنید. ادعای nonce برای تبادل کد مجوز اختیاری است و فقط زمانی استفاده می‌شود که سرایند DPoP-Nonce قبلاً دریافت شده باشد. این JSON را با Base64Url کدبندی کنید:

    {
      "jti":"JTI_VALUE",
      "htm":"POST",
      "htu":"https://oauth2.googleapis.com/token",
      "iat":YOUR_JWT_ISSUED_TIME,
      "nonce":"SERVER_PROVIDED_NONCE"
    }

    مقدار jti به نوع مبادله بستگی دارد:

    • برای تبادل کد مجوز، jti باید درهم‌سازی SHA256 کدبندی‌شده با Base64Url از کد مجوز باشد: "jti":"BASE64URL(SHA256(AUTHORIZATION_CODE))".
    • برای تبادل ژتون بازآوری، jti باید یک شناسه یکتا برای هر درخواست باشد: "jti":"YOUR_UNIQUE_PER_REQUEST_IDENTIFIER".
  4. امضا کردن مدرک:

    سرصفحه و محتوای کدبندی‌شده را با یک نقطه (.) به‌هم بچسبانید، سپس نتیجه را با کلید خصوصی خود بااستفاده از ES256 امضا کنید. توجه داشته باشید که JWS الزام می‌کند که امضا در قالب خام R | S به‌هم‌پیوسته باشد (۶۴ بایت برای P-256). اگر مستقیماً از OpenSSL استفاده می‌کنید، باید امضای پیش‌فرض با کدبندی ASN.1 DER را به این قالب خام تبدیل کنید.

تبادل موفق با پاسخ 200 OK حاوی نشان‌ها مشخص می‌شود. اگر درطول تبادل از اثبات DPoP معتبری استفاده شود، کد بازآوری که Google برمی‌گرداند به کلید شما محدود به DPoP خواهد بود، اما کدهای دسترسی محدود به DPoP نخواهند بود. رمزهای دسترسی token_type مربوط به Bearer را به‌جای DPoP حفظ خواهند کرد. علاوه‌براین، Google سرایند DPoP-Nonce HTTP را در پاسخ برمی‌گرداند. کارخواه شما باید این عدد یک‌بارمصرف را ذخیره کند و آن را در ادعای nonce اثبات DPoP در درخواست‌های بعدی (مانند هنگام تبادل یک کد بازآوری برای یک کد دسترسی جدید، یا هنگام فراخوانی میاناهای برنامه‌سازی کاربردی محافظت‌شده با DPoP) قرار دهد. بااستفاده از این عدد یک‌بارمصرف صادرشده زودهنگام، می‌توانید از خطای رفت‌وبرگشت اضافی (use_dpop_nonce) در درخواست بعدی‌تان جلوگیری کنید.

برای درخواست‌های تبادل ژتون که با ژتون‌های بازآوری محدودشده با DPoP انجام می‌شود، باید اثبات‌های DPoP اضافه شود.

تبادل ناموفق زمانی رخ می‌دهد که سرایند DPoP در زمان موردانتظار وجود نداشته باشد، نامعتبر باشد، یا اگر مدرک از کلیدی متفاوت با کلید متصل به کد استفاده کند. در این موارد، سرور خطای 400 Bad Request را برمی‌گرداند. اگر اثبات DPoP دارای ادعاهای htm یا htu نامطابق، iat منقضی‌شده، jti دوباره استفاده‌شده، یا امضای نامعتبر باشد، Google کد خطای invalid_dpop_proof را برمی‌گرداند. اگر یک DPoP nonce لازم باشد، مثلاً درطول تبادل ژتون بازآوری، و اثبات DPoP فاقد ادعای nonce باشد، یا مقدار nonce برای سرور غیرقابل‌قبول باشد (مثلاً منقضی شده باشد، قبلاً استفاده شده باشد، یا نادرست باشد)، Google کد خطای use_dpop_nonce را به‌همراه سرصفحه HTTP‏ DPoP-Nonce حاوی یک nonce جدید برمی‌گرداند که می‌توانید در درخواست بعدی استفاده کنید. خطاهای دیگر ممکن است invalid_grant را برگردانند.

‫Google با برگرداندن یک شیء JSON که حاوی یک کد دسترسی کوتاه‌مدت و یک کد نوسازی است به این درخواست پاسخ می‌دهد. توجه داشته باشید که ژتون بازآوری فقط درصورتی برگردانده می‌شود که برنامه شما پارامتر access_type را در درخواست اولیه به سرور مجوز Google روی offline تنظیم کرده باشد.

پاسخ حاوی فیلدهای زیر است:

فیلدها
access_token نشانه‌ای که برنامه شما برای صدور مجوز درخواست Google API ارسال می‌کند.
expires_in مدت‌زمان باقی‌مانده کد دسترسی برحسب ثانیه.
refresh_token نشانه‌ای که می‌توانید از آن برای دریافت نشانه دسترسی جدید استفاده کنید. کدهای بازآوری تا زمانی که کاربر دسترسی را لغو کند یا کد بازآوری منقضی شود معتبر هستند. اگر از DPoP استفاده شده باشد، کد بازآوری به کلید خصوصی‌ای که برای امضای مدرک DPoP استفاده شده است مقید می‌شود. مجدداً، این فیلد فقط درصورتی در این پاسخ وجود دارد که پارامتر access_type را در درخواست اولیه به سرور مجوز Google روی offline تنظیم کرده باشید.
refresh_token_expires_in طول عمر باقی‌مانده ژتون بازآوری برحسب ثانیه. این مقدار فقط زمانی تنظیم می‌شود که کاربر دسترسی مبتنی بر زمان اعطا کند.
scope دامنه‌های دسترسی اعطاشده توسط access_token به‌صورت فهرستی از رشته‌های حساس به حروف بزرگ و کوچک که با فاصله از هم جدا شده‌اند بیان می‌شود.
token_type نوع کد برگردانده‌شده. این مقدار همیشه Bearer است، حتی وقتی از DPoP استفاده می‌شود.

تکه کد زیر سرصفحه‌ها و متن پاسخ موفقیت‌آمیز نمونه‌ای را هنگام استفاده از DPoP نشان می‌دهد:

HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
DPoP-Nonce: AN3XwJjZsjnb0ZuWkRlek8QU7wY-Zhf-5IP6tO0tORz0KgtDT1Bo8FX-w4nz3r5lnepI

{
  "access_token": "1/fFAGRNJru1FTz70BzhT3Zg",
  "expires_in": 3920,
  "token_type": "Bearer",
  "scope": "https://www.googleapis.com/auth/yt-analytics.readonly https://www.googleapis.com/auth/calendar.readonly",
  "refresh_token": "1//xEoDL4iW3cxlI7yDbSRFYNG01kVKM2C-259HOF2aQbI"
}

خطاها

هنگام تبدیل کد مجوز به کد دسترسی ممکن است با خطای زیر به‌جای پاسخ موردانتظار مواجه شوید. کدهای خطای رایج و راه‌حل‌های پیشنهادی در این بخش فهرست شده‌اند.

invalid_grant

کد تأییدیه ارائه‌شده نامعتبر است یا قالب آن درست نیست. با بازراه‌اندازی فرایند OAuth، کد جدیدی درخواست کنید تا از کاربر بخواهید دوباره رضایت دهد.

مرحله ۶: بررسی اینکه کاربران کدام محدوده‌ها را اعطا کرده‌اند

هنگام درخواست چندین اجازه (محدوده)، ممکن است کاربران به برنامه شما اجازه دسترسی به همه آن‌ها را ندهند. برنامه شما باید بررسی کند که کدام محدوده‌ها واقعاً اعطا شده‌اند و در شرایطی که برخی‌از اجازه‌ها رد می‌شوند، به‌طور مناسب عمل کند، معمولاً با غیرفعال کردن ویژگی‌هایی که به آن محدوده‌های ردشده متکی هستند.

بااین‌حال، چند استثنا وجود دارد. برنامه‌های Google Workspace Enterprise با واگذاری اختیار در سطح دامنه، یا برنامه‌هایی که به‌عنوان معتمد علامت‌گذاری شده‌اند، از صفحه موافقت با اجازه‌های دقیق عبور می‌کنند. برای این برنامه‌ها، کاربران صفحه رضایت اجازه دانه‌ای را نخواهند دید. درعوض، برنامه‌تان یا همه گستره‌های درخواست‌شده را دریافت می‌کند یا هیچ‌کدام را دریافت نمی‌کند.

برای اطلاعات دقیق‌تر، نحوه مدیریت اجازه‌های ریزدانه را ببینید.

PHP

برای بررسی اینکه کاربر کدام محدوده‌ها را اعطا کرده است، از روش getGrantedScope() استفاده کنید:

// Space-separated string of granted scopes if it exists, otherwise null.
$granted_scopes = $client->getOAuth2Service()->getGrantedScope();

// Determine which scopes user granted and build a dictionary
$granted_scopes_dict = [
  'Drive' => str_contains($granted_scopes, Google\Service\Drive::DRIVE_METADATA_READONLY),
  'Calendar' => str_contains($granted_scopes, Google\Service\Calendar::CALENDAR_READONLY)
];

Python

شیء credentials برگردانده‌شده دارای ویژگی granted_scopes است، که فهرستی از دامنه‌هایی است که کاربر به برنامه شما اعطا کرده است.

credentials = flow.credentials
flask.session['credentials'] = {
    'token': credentials.token,
    'refresh_token': credentials.refresh_token,
    'granted_scopes': credentials.granted_scopes}

تابع زیر بررسی می‌کند که کاربر کدام محدوده‌ها را به برنامه شما اعطا کرده است.

def check_granted_scopes(credentials):
  features = {}
  if 'https://www.googleapis.com/auth/drive.metadata.readonly' in credentials['granted_scopes']:
    features['drive'] = True
  else:
    features['drive'] = False

  if 'https://www.googleapis.com/auth/calendar.readonly' in credentials['granted_scopes']:
    features['calendar'] = True
  else:
    features['calendar'] = False

  return features

Ruby

هنگام درخواست چندین محدوده به‌طور هم‌زمان، بررسی کنید کدام محدوده‌ها ازطریق دارایی scope از شیء credentials اعطا شده‌اند.

# User authorized the request. Now, check which scopes were granted.
if credentials.scope.include?(Google::Apis::DriveV3::AUTH_DRIVE_METADATA_READONLY)
  # User authorized read-only Drive activity permission.
  # Calling the APIs, etc
else
  # User didn't authorize read-only Drive activity permission.
  # Update UX and application accordingly
end

# Check if user authorized Calendar read permission.
if credentials.scope.include?(Google::Apis::CalendarV3::AUTH_CALENDAR_READONLY)
  # User authorized Calendar read permission.
  # Calling the APIs, etc.
else
  # User didn't authorize Calendar read permission.
  # Update UX and application accordingly
end

Node.js

هنگام درخواست چند گستره به‌طور هم‌زمان، بررسی کنید کدام گستره‌ها ازطریق ویژگی scope شیء tokens اعطا شده‌اند.

// User authorized the request. Now, check which scopes were granted.
if (tokens.scope.includes('https://www.googleapis.com/auth/yt-analytics.readonly'))
{
  // User authorized read-only Drive activity permission.
  // Calling the APIs, etc.
}
else
{
  // User didn't authorize read-only Drive activity permission.
  // Update UX and application accordingly
}

// Check if user authorized Calendar read permission.
if (tokens.scope.includes('https://www.googleapis.com/auth/calendar.readonly'))
{
  // User authorized Calendar read permission.
  // Calling the APIs, etc.
}
else
{
  // User didn't authorize Calendar read permission.
  // Update UX and application accordingly
}

HTTP/REST

برای بررسی اینکه آیا کاربر به برنامه شما اجازه دسترسی به دامنه خاصی را داده است یا نه، فیلد scope را در پاسخ کد دسترسی بررسی کنید. حوزه‌های دسترسی اعطاشده توسط access_token که به‌صورت فهرستی از رشته‌های حساس به حروف بزرگ و کوچک با فاصله از هم بیان شده است.

برای مثال، پاسخ کد دسترسی نمونه زیر نشان می‌دهد که کاربر به برنامه شما اجازه دسترسی به اجازه‌های فعالیت Drive فقط خواندنی و رویدادهای «تقویم» را داده است:

  {
    "access_token": "1/fFAGRNJru1FTz70BzhT3Zg",
    "expires_in": 3920,
    "token_type": "Bearer",
    "scope": "https://www.googleapis.com/auth/yt-analytics.readonly https://www.googleapis.com/auth/calendar.readonly",
    "refresh_token": "1//xEoDL4iW3cxlI7yDbSRFYNG01kVKM2C-259HOF2aQbI"
  }

فراخوانی میاناهای برنامه‌سازی کاربردی Google

PHP

با تکمیل مراحل زیر، از کد دسترسی برای فراخوانی Google APIs استفاده کنید:

  1. اگر لازم است کد دسترسی را برای شیء Google\Client جدیدی اعمال کنید — برای مثال، اگر کد دسترسی را در جلسه کاربر ذخیره کرده‌اید — از روش setAccessToken استفاده کنید:
    $client->setAccessToken($access_token);
  2. یک شیء سرویس برای API که می‌خواهید فراخوانی کنید بسازید. با ارائه شیء Google\Client مجاز به سازنده برای API که می‌خواهید فراخوانی کنید، شیء سرویس می‌سازید. برای مثال، برای فراخوانی YouTube Analytics API:
    $youtube = new Google_Service_YouTubeAnalytics($client);
  3. بااستفاده از میانای ارائه‌شده توسط شیء سرویس، درخواست‌هایی به سرویس میانای برنامه‌سازی کاربردی ارسال کنید. برای مثال، برای بازیابی گزارش YouTube Analytics برای کانال کاربر اصالت‌سنجی‌شده:
    $report = $youtube->reports->query('channel==MINE', '2016-05-01', '2016-06-30', 'views');

Python

پس‌از دریافت کد دسترسی، برنامه‌تان می‌تواند از آن کد برای صدور مجوز درخواست‌های API ازطرف حساب کاربری یا حساب سرویس مشخصی استفاده کند. از اطلاعات اعتباری مجوز مختص کاربر برای ساختن شیء سرویس برای API که می‌خواهید فراخوانی کنید استفاده کنید، و سپس از آن شیء برای ایجاد درخواست‌های API مجاز استفاده کنید.

  1. یک شیء سرویس برای API که می‌خواهید فراخوانی کنید بسازید. با فراخوانی روش build کتابخانه googleapiclient.discovery با نام و نسخه API و اطلاعات اعتباری کاربر، یک شیء سرویس می‌سازید: برای مثال، برای فراخوانی نسخه ۲ از YouTube Analytics API:
    from googleapiclient.discovery import build
    
    youtube = build('youtubeAnalytics', 'v2', credentials=credentials)
  2. بااستفاده از میانای ارائه‌شده توسط شیء سرویس، درخواست‌ها را به سرویس میانای برنامه‌سازی کاربردی ارسال کنید. برای مثال، برای بازیابی گزارش YouTube Analytics برای کانال کاربر اصالت‌سنجی‌شده:
    report = youtube.reports().query(ids='channel==MINE', start_date='2016-05-01', end_date='2016-06-30', metrics='views').execute()

Ruby

پس‌از دریافت کد دسترسی، برنامه‌تان می‌تواند از آن کد برای درخواست‌های میانای برنامه‌سازی کاربردی ازطرف حساب کاربری یا حساب خدمات مشخصی استفاده کند. از اطلاعات اعتباری مجوز ویژه کاربر برای ساختن یک شیء سرویس برای API که می‌خواهید فراخوانی کنید استفاده کنید، و سپس از آن شیء برای ایجاد درخواست‌های API مجاز استفاده کنید.

  1. برای API که می‌خواهید فراخوانی کنید، یک شیء سرویس بسازید. برای مثال، برای فراخوانی نسخه ۲ از YouTube Analytics API:
    youtube = Google::Apis::YoutubeAnalyticsV2::YouTubeAnalyticsService.new
  2. اطلاعات اعتباری را در سرویس تنظیم کنید:
    youtube.authorization = credentials
  3. بااستفاده از میانای ارائه‌شده توسط شیء سرویس، درخواست‌هایی به سرویس میانای برنامه‌سازی کاربردی ارسال کنید. برای مثال، برای بازیابی گزارش YouTube Analytics برای کانال کاربر اصیل‌سازی‌شده:
    report = youtube.query_report('channel==MINE', '2016-05-01', '2016-06-30', 'views')

یا اینکه با ارائه پارامتر options به یک روش، مجوز را می‌توان براساس هر روش ارائه کرد:

report = youtube.query_report('channel==MINE', '2016-05-01', '2016-06-30', 'views', options: { authorization: auth_client })

Node.js

پس‌از دریافت کد دسترسی و تنظیم آن روی شیء OAuth2، از شیء برای فراخوانی Google APIs استفاده کنید. برنامه شما می‌تواند از این کد برای مجاز کردن درخواست‌های API ازطرف حساب کاربری یا حساب سرویس معین استفاده کند. یک شیء سرویس برای API که می‌خواهید فراخوانی کنید بسازید. برای مثال، کد زیر از Google Drive API برای فهرست کردن نام فایل‌ها در Drive کاربر استفاده می‌کند.

const { google } = require('googleapis');

// Example of using Google Drive API to list filenames in user's Drive.
const drive = google.drive('v3');
drive.files.list({
  auth: oauth2Client,
  pageSize: 10,
  fields: 'nextPageToken, files(id, name)',
}, (err1, res1) => {
  if (err1) return console.log('The API returned an error: ' + err1);
  const files = res1.data.files;
  if (files.length) {
    console.log('Files:');
    files.map((file) => {
      console.log(`${file.name} (${file.id})`);
    });
  } else {
    console.log('No files found.');
  }
});

HTTP/REST

پس‌از اینکه برنامه شما کد دسترسی را دریافت کرد، می‌توانید از این کد برای تماس با «میانای برنامه‌سازی کاربردی Google» ازطرف حساب کاربری معینی استفاده کنید، به‌شرطی که محدوده(های) دسترسی موردنیاز میانای برنامه‌سازی کاربردی اعطا شده باشد. برای انجام این کار، کد دسترسی را با گنجاندن پارامتر پُرسمان access_token یا مقدار سرصفحه HTTP Authorization در درخواست به میانای برنامه‌سازی کاربردی بگنجانید.Bearer درصورت امکان، سرصفحه HTTP ترجیح داده می‌شود، زیرا رشته‌های پُرسمان معمولاً در گزارش‌های سرور قابل‌مشاهده هستند. در اکثر موارد می‌توانید از کتابخانه کارخواه برای راه‌اندازی فراخوانی‌هایتان به Google API استفاده کنید (برای مثال، هنگام فراخوانی YouTube Analytics API).

توجه داشته باشید که YouTube Analytics API از جریان حساب سرویس پشتیبانی نمی‌کند. «میانای برنامه‌سازی کاربردی گزارش‌دهی YouTube» فقط از حساب‌های خدماتی برای مالکان محتوای YouTube که مالک و مدیر چندین کانال YouTube هستند، مانند شرکت‌های ضبط موسیقی و استودیوهای فیلم‌سازی، پشتیبانی می‌کند.

می‌توانید همه میاناهای برنامه‌سازی کاربردی Google را امتحان کنید و دامنه‌های آن‌ها را در OAuth 2.0 Playground مشاهده کنید.

مثال‌های HTTP GET

فراخوانی نقطه پایان reports.query (YouTube Analytics API) بااستفاده از سرصفحه HTTP Authorization: Bearer ممکن است شبیه به این باشد. توجه داشته باشید که باید کد دسترسی خودتان را مشخص کنید:

GET /youtube/v2/reports?ids=channel%3D%3DMINE&startDate=2016-05-01&endDate=2016-06-30&metrics=views HTTP/1.1
Host: www.googleapis.com
Authorization: Bearer access_token

در اینجا فراخوانی به همان API برای کاربر اصیل بااستفاده از پارامتر رشته پُرسمان access_token ارائه شده است:

GET https://www.googleapis.com/youtube/v2/reports?access_token=access_token&ids=channel%3D%3DMINE&startDate=2016-05-01&endDate=2016-06-30&metrics=views

curl مثال

می‌توانید این فرمان‌ها را با برنامه خط فرمان curl آزمایش کنید. در اینجا نمونه‌ای آورده شده است که از گزینه سرصفحه HTTP (ترجیحی) استفاده می‌کند:

curl -H "Authorization: Bearer access_token" https://www.googleapis.com/youtube/v2/reports?ids=channel%3D%3DMINE&startDate=2016-05-01&endDate=2016-06-30&metrics=views

یا، به‌عنوان گزینه جایگزین، گزینه پارامتر رشته پُرسمان:

curl https://www.googleapis.com/youtube/v2/reports?access_token=access_token&ids=channel%3D%3DMINE&startDate=2016-05-01&endDate=2016-06-30&metrics=views

نمونه کامل

مثال زیر یک شیء با قالب JSON را چاپ می‌کند که داده‌های بازدیدها را برای کانال YouTube کاربر اصالت‌سنجی‌شده نشان می‌دهد، پس‌از اینکه کاربر به برنامه اجازه می‌دهد گزارش‌های YouTube Analytics را بازیابی کند.

PHP

برای اجرای این مثال:

  1. در «کنسول API»، نشانی وب ماشین محلی را به فهرست نشانی‌های وب هدایت مجدد اضافه کنید. برای مثال، http://localhost:8080 را اضافه کنید.
  2. دایرکتوری جدیدی ایجاد کنید و به آن تغییر دهید. برای مثال:
    mkdir ~/php-oauth2-example
    cd ~/php-oauth2-example
  3. کتابخانه کارخواه Google API برای PHP را بااستفاده از Composer نصب کنید:
    composer require google/apiclient:^2.15.0
  4. فایل‌های index.php و oauth2callback.php را با محتوای زیر ایجاد کنید.
  5. نمونه را با سرور وب آزمایشی توکار PHP اجرا کنید:
    php -S localhost:8080 ~/php-oauth2-example

index.php

<?php
require_once __DIR__.'/vendor/autoload.php';

session_start();

$client = new Google\Client();
$client->setAuthConfig('client_secret.json');

// User granted permission as an access token is in the session.
if (isset($_SESSION['access_token']) && $_SESSION['access_token'])
{
  $client->setAccessToken($_SESSION['access_token']);
  
  // Check if user granted Drive permission
  if ($_SESSION['granted_scopes_dict']['Drive']) {
    echo "Drive feature is enabled.";
    echo "</br>";
    $drive = new Drive($client);
    $files = array();
    $response = $drive->files->listFiles(array());
    foreach ($response->files as $file) {
        echo "File: " . $file->name . " (" . $file->id . ")";
        echo "</br>";
    }
  } else {
    echo "Drive feature is NOT enabled.";
    echo "</br>";
  }

   // Check if user granted Calendar permission
  if ($_SESSION['granted_scopes_dict']['Calendar']) {
    echo "Calendar feature is enabled.";
    echo "</br>";
  } else {
    echo "Calendar feature is NOT enabled.";
    echo "</br>";
  }
}
else
{
  // Redirect users to outh2call.php which redirects users to Google OAuth 2.0
  $redirect_uri = 'http://' . $_SERVER['HTTP_HOST'] . '/oauth2callback.php';
  header('Location: ' . filter_var($redirect_uri, FILTER_SANITIZE_URL));
}
?>

oauth2callback.php

<?php
require_once __DIR__.'/vendor/autoload.php';

session_start();

$client = new Google\Client();

// Required, call the setAuthConfig function to load authorization credentials from
// client_secret.json file.
$client->setAuthConfigFile('client_secret.json');
$client->setRedirectUri('http://' . $_SERVER['HTTP_HOST']. $_SERVER['PHP_SELF']);

// Required, to set the scope value, call the addScope function.
$client->addScope(Google_Service_YouTubeAnalytics::YT_ANALYTICS_READONLY);

// Enable incremental authorization. Recommended as a best practice.
$client->setIncludeGrantedScopes(true);

// Recommended, offline access will give you both an access and refresh token so that
// your app can refresh the access token without user interaction.
$client->setAccessType("offline");

// Generate a URL for authorization as it doesn't contain code and error
if (!isset($_GET['code']) && !isset($_GET['error']))
{
  // Generate and set state value
  $state = bin2hex(random_bytes(16));
  $client->setState($state);
  $_SESSION['state'] = $state;

  // Generate a url that asks permissions.
  $auth_url = $client->createAuthUrl();
  header('Location: ' . filter_var($auth_url, FILTER_SANITIZE_URL));
}

// User authorized the request and authorization code is returned to exchange access and
// refresh tokens.
if (isset($_GET['code']))
{
  // Check the state value
  if (!isset($_GET['state']) || $_GET['state'] !== $_SESSION['state']) {
    die('State mismatch. Possible CSRF attack.');
  }

  // Get access and refresh tokens (if access_type is offline)
  $token = $client->fetchAccessTokenWithAuthCode($_GET['code']);

  /** Save access and refresh token to the session variables.
    * ACTION ITEM: In a production app, you likely want to save the
    *              refresh token in a secure persistent storage instead. */
  $_SESSION['access_token'] = $token;
  $_SESSION['refresh_token'] = $client->getRefreshToken();
  
  // Space-separated string of granted scopes if it exists, otherwise null.
  $granted_scopes = $client->getOAuth2Service()->getGrantedScope();

  // Determine which scopes user granted and build a dictionary
  $granted_scopes_dict = [
    'Drive' => str_contains($granted_scopes, Google\Service\Drive::DRIVE_METADATA_READONLY),
    'Calendar' => str_contains($granted_scopes, Google\Service\Calendar::CALENDAR_READONLY)
  ];
  $_SESSION['granted_scopes_dict'] = $granted_scopes_dict;
  
  $redirect_uri = 'http://' . $_SERVER['HTTP_HOST'] . '/';
  header('Location: ' . filter_var($redirect_uri, FILTER_SANITIZE_URL));
}

// An error response e.g. error=access_denied
if (isset($_GET['error']))
{
  echo "Error: ". $_GET['error'];
}
?>

Python

این نمونه از چارچوب Flask استفاده می‌کند. این برنامه یک برنامه وب را در http://localhost:8080 اجرا می‌کند که به شما امکان می‌دهد جریان OAuth 2.0 را آزمایش کنید. اگر به آن نشانی وب بروید، باید پنج پیوند ببینید:

  • فراخوانی Drive API: این پیوند به صفحه‌ای اشاره می‌کند که اگر کاربران اجازه دهند، درخواست نمونه API را اجرا می‌کند. درصورت لزوم، جریان صدور مجوز را شروع می‌کند. درصورت موفقیت‌آمیز بودن، صفحه پاسخ API را نمایش می‌دهد.
  • صفحه ساختگی برای فراخوانی Calendar API: این پیوند به صفحه ساختگی‌ای اشاره می‌کند که تلاش می‌کند درخواست نمونه Calendar API را درصورت اعطای اجازه ازسوی کاربران اجرا کند. درصورت لزوم، جریان صدور مجوز را شروع می‌کند. اگر موفقیت‌آمیز باشد، صفحه پاسخ میانای برنامه‌سازی کاربردی را نمایش می‌دهد.
  • جریان اصالت‌سنجی را مستقیماً آزمایش کنید: این پیوند به صفحه‌ای اشاره می‌کند که تلاش می‌کند کاربر را ازطریق جریان صدور مجوز ارسال کند. برنامه برای ارسال درخواست‌های مجاز API ازطرف کاربر، اجازه درخواست می‌کند.
  • لغو اعتبارنامه‌های فعلی: این پیوند به صفحه‌ای اشاره می‌کند که اجازه‌هایی را که کاربر قبلاً به برنامه اعطا کرده است لغو می‌کند.
  • پاک کردن اطلاعات اعتباری جلسه Flask: این پیوند اطلاعات اعتباری مجوز را که در جلسه Flask ذخیره شده است پاک می‌کند. این کار به شما امکان می‌دهد ببینید اگر کاربری که قبلاً به برنامه‌تان اجازه داده است بخواهد درخواست میانای برنامه‌سازی کاربردی را در جلسه جدیدی اجرا کند چه اتفاقی می‌افتد. همچنین به شما امکان می‌دهد پاسخ API را که برنامه شما درصورت لغو اجازه‌های اعطاشده به برنامه شما توسط کاربر دریافت می‌کند ببینید، و برنامه شما همچنان سعی می‌کند درخواستی را با یک کد دسترسی لغوشده مجاز کند.
# -*- coding: utf-8 -*-

import os
import flask
import json
import requests

import google.oauth2.credentials
import google_auth_oauthlib.flow
import googleapiclient.discovery

# This variable specifies the name of a file that contains the OAuth 2.0
# information for this application, including its client_id and client_secret.
CLIENT_SECRETS_FILE = "client_secret.json"

# The OAuth 2.0 access scope allows for access to the
# authenticated user's account and requires requests to use an SSL connection.
SCOPES = ['https://www.googleapis.com/auth/yt-analytics.readonly',
          'https://www.googleapis.com/auth/calendar.readonly']
API_SERVICE_NAME = 'youtubeAnalytics'
API_VERSION = 'v2'

app = flask.Flask(__name__)
# Note: A secret key is included in the sample so that it works.
# If you use this code in your application, replace this with a truly secret
# key. See https://flask.palletsprojects.com/quickstart/#sessions.
app.secret_key = 'REPLACE ME - this value is here as a placeholder.'

@app.route('/')
def index():
  return print_index_table()

@app.route('/drive')
def drive_api_request():
  if 'credentials' not in flask.session:
    return flask.redirect('authorize')

  features = flask.session['features']

  if features['drive']:
    # Load client secrets from the server-side file.
    with open(CLIENT_SECRETS_FILE, 'r') as f:
        client_config = json.load(f)['web']

    # Load user-specific credentials from browser session storage.
    session_credentials = flask.session['credentials']

    # Reconstruct the credentials object.
    credentials = google.oauth2.credentials.Credentials(
        refresh_token=session_credentials.get('refresh_token'),
        scopes=session_credentials.get('granted_scopes'),
        token=session_credentials.get('token'),
        client_id=client_config.get('client_id'),
        client_secret=client_config.get('client_secret'),
        token_uri=client_config.get('token_uri'))

    youtube = googleapiclient.discovery.build(
        API_SERVICE_NAME, API_VERSION, credentials=credentials)

    report = youtube.reports().query(ids='channel==MINE', start_date='2016-05-01', end_date='2016-06-30', metrics='views').execute()

    # Save credentials back to session in case access token was refreshed.
    flask.session['credentials'] = credentials_to_dict(credentials)

    return flask.jsonify(**report)
  else:
    # User didn't authorize read-only Drive activity permission.
    return '<p>Drive feature is not enabled.</p>'

@app.route('/calendar')
def calendar_api_request():
  if 'credentials' not in flask.session:
    return flask.redirect('authorize')

  features = flask.session['features']

  if features['calendar']:
    # User authorized Calendar read permission.
    # Calling the APIs, etc.
    return ('<p>User granted the Google Calendar read permission. '+
            'This sample code does not include code to call Calendar</p>')
  else:
    # User didn't authorize Calendar read permission.
    # Update UX and application accordingly
    return '<p>Calendar feature is not enabled.</p>'

@app.route('/authorize')
def authorize():
  # Create flow instance to manage the OAuth 2.0 Authorization Grant Flow steps.
  flow = google_auth_oauthlib.flow.Flow.from_client_secrets_file(
      CLIENT_SECRETS_FILE, scopes=SCOPES)

  # The URI created here must exactly match one of the authorized redirect URIs
  # for the OAuth 2.0 client, which you configured in the API Console. If this
  # value doesn't match an authorized URI, you will get a 'redirect_uri_mismatch'
  # error.
  flow.redirect_uri = flask.url_for('oauth2callback', _external=True)

  authorization_url, state = flow.authorization_url(
      # Enable offline access so that you can refresh an access token without
      # re-prompting the user for permission. Recommended for web server apps.
      access_type='offline',
      # Enable incremental authorization. Recommended as a best practice.
      include_granted_scopes='true')

  # Store the state so the callback can verify the auth server response.
  flask.session['state'] = state

  return flask.redirect(authorization_url)

@app.route('/oauth2callback')
def oauth2callback():
  # Specify the state when creating the flow in the callback so that it can
  # verified in the authorization server response.
  state = flask.session['state']

  flow = google_auth_oauthlib.flow.Flow.from_client_secrets_file(
      CLIENT_SECRETS_FILE, scopes=SCOPES, state=state)
  flow.redirect_uri = flask.url_for('oauth2callback', _external=True)

  # Use the authorization server's response to fetch the OAuth 2.0 tokens.
  authorization_response = flask.request.url
  flow.fetch_token(authorization_response=authorization_response)

  # Store credentials in the session.
  # ACTION ITEM: In a production app, you likely want to save these
  #              credentials in a persistent database instead.
  credentials = flow.credentials
  
  credentials = credentials_to_dict(credentials)
  flask.session['credentials'] = credentials

  # Check which scopes user granted
  features = check_granted_scopes(credentials)
  flask.session['features'] = features
  return flask.redirect('/')
  
@app.route('/revoke')
def revoke():
  if 'credentials' not in flask.session:
    return ('You need to <a href="/authorize">authorize</a> before ' +
            'testing the code to revoke credentials.')

  # Load client secrets from the server-side file.
  with open(CLIENT_SECRETS_FILE, 'r') as f:
      client_config = json.load(f)['web']

  # Load user-specific credentials from the session.
  session_credentials = flask.session['credentials']

  # Reconstruct the credentials object.
  credentials = google.oauth2.credentials.Credentials(
      refresh_token=session_credentials.get('refresh_token'),
      scopes=session_credentials.get('granted_scopes'),
      token=session_credentials.get('token'),
      client_id=client_config.get('client_id'),
      client_secret=client_config.get('client_secret'),
      token_uri=client_config.get('token_uri'))

  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:
    # Clear the user's session credentials after successful revocation
    if 'credentials' in flask.session:
        del flask.session['credentials']
        del flask.session['features']
    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,
          'granted_scopes': credentials.granted_scopes}

def check_granted_scopes(credentials):
  features = {}
  if 'https://www.googleapis.com/auth/yt-analytics.readonly' in credentials['granted_scopes']:
    features['drive'] = True
  else:
    features['drive'] = False

  if 'https://www.googleapis.com/auth/calendar.readonly' in credentials['granted_scopes']:
    features['calendar'] = True
  else:
    features['calendar'] = False

  return features

def print_index_table():
  return ('<table>' + 
          '<tr><td><a href="/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="/drive">Call Drive API directly</a></td>' +
          '<td> Use stored credentials to call the API, you still might not be prompted to reauthorize ' +
          '    the application.</td></tr>' +
          '<tr><td><a href="/calendar">Call Calendar API directly</a></td>' +
          '<td> Use stored credentials to call the API, 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="/authorize">authorize</a> ' +
          '    again, you should go back to the auth flow.' +
          '</td></tr></table>')

if __name__ == '__main__':
  # When running locally, disable OAuthlib's HTTPs verification.
  # ACTION ITEM for developers:
  #     When running in production *do not* leave this option enabled.
  os.environ['OAUTHLIB_INSECURE_TRANSPORT'] = '1'

  # This disables the requested scopes and granted scopes check.
  # If users only grant partial request, the warning would not be thrown.
  os.environ['OAUTHLIB_RELAX_TOKEN_SCOPE'] = '1'

  # Specify a hostname and port that are set as a valid redirect URI
  # for your API project in the Google API Console.
  app.run('localhost', 8080, debug=True)

Ruby

این نمونه از چارچوب Sinatra استفاده می‌کند.

require 'googleauth'
require 'googleauth/web_user_authorizer'
require 'googleauth/stores/redis_token_store'

require 'google/apis/youtube_analytics_v2'
require 'google/apis/calendar_v3'

require 'sinatra'

configure do
  enable :sessions

  # Required, call the from_file method to retrieve the client ID from a
  # client_secret.json file.
  set :client_id, Google::Auth::ClientId.from_file('/path/to/client_secret.json')

  # Required, scope value
  # Access scopes for two non-Sign-In scopes: Read-only Drive activity and Google Calendar.
  scope = ['Google::Apis::DriveV3::AUTH_DRIVE_METADATA_READONLY',
           'Google::Apis::CalendarV3::AUTH_CALENDAR_READONLY']

  # Required, Authorizers require a storage instance to manage long term persistence of
  # access and refresh tokens.
  set :token_store, Google::Auth::Stores::RedisTokenStore.new(redis: Redis.new)

  # Required, indicate where the API server will redirect the user after the user completes
  # the authorization flow. The redirect URI is required. The value must exactly
  # match one of the authorized redirect URIs for the OAuth 2.0 client, which you
  # configured in the API Console. If this value doesn't match an authorized URI,
  # you will get a 'redirect_uri_mismatch' error.
  set :callback_uri, '/oauth2callback'

  # To use OAuth2 authentication, we need access to a CLIENT_ID, CLIENT_SECRET, AND REDIRECT_URI
  # from the client_secret.json file. To get these credentials for your application, visit
  # https://console.cloud.google.com/apis/credentials.
  set :authorizer, Google::Auth::WebUserAuthorizer.new(settings.client_id, settings.scope,
                          settings.token_store, callback_uri: settings.callback_uri)
end

get '/' do
  # NOTE: Assumes the user is already authenticated to the app
  user_id = request.session['user_id']

  # Fetch stored credentials for the user from the given request session.
  # nil if none present
  credentials = settings.authorizer.get_credentials(user_id, request)

  if credentials.nil?
    # Generate a url that asks the user to authorize requested scope(s).
    # Then, redirect user to the url.
    redirect settings.authorizer.get_authorization_url(request: request)
  end
  
  # User authorized the request. Now, check which scopes were granted.
  if credentials.scope.include?(Google::Apis::DriveV3::AUTH_DRIVE_METADATA_READONLY)
    # User authorized read-only Drive activity permission.
    # Example of using Google Drive API to list filenames in user's Drive.
    youtube = Google::Apis::YoutubeAnalyticsV2::YouTubeAnalyticsService.new
    report = youtube.query_report('channel==MINE', '2016-05-01', '2016-06-30', 'views', options: { authorization: auth_client })
    
    "<pre>#{JSON.pretty_generate(report.to_h)}</pre>"
  else
    # User didn't authorize read-only Drive activity permission.
    # Update UX and application accordingly
  end

  # Check if user authorized Calendar read permission.
  if credentials.scope.include?(Google::Apis::CalendarV3::AUTH_CALENDAR_READONLY)
    # User authorized Calendar read permission.
    # Calling the APIs, etc.
  else
    # User didn't authorize Calendar read permission.
    # Update UX and application accordingly
  end
end

# Receive the callback from Google's OAuth 2.0 server.
get '/oauth2callback' do
  # Handle the result of the oauth callback. Defers the exchange of the code by
  # temporarily stashing the results in the user's session.
  target_url = Google::Auth::WebUserAuthorizer.handle_auth_callback_deferred(request)
  redirect target_url
end

Node.js

برای اجرای این نمونه:

  1. در «کنسول API»، نشانی وب دستگاه محلی را به فهرست نشانی‌های وب تغییرمسیر اضافه کنید. برای مثال، http://localhost را اضافه کنید.
  2. مطمئن شوید که نسخه LTS نگهداری، LTS فعال، یا نسخه فعلی Node.js را نصب کرده‌اید.
  3. فهرست راهنمای جدیدی ایجاد کنید و به آن بروید. برای مثال:
    mkdir ~/nodejs-oauth2-example
    cd ~/nodejs-oauth2-example
  4. کتابخانه کارخواه Google API را برای Node.js بااستفاده از 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 two non-Sign-In scopes: Read-only Drive activity and Google Calendar.
const scopes = [
  'https://www.googleapis.com/auth/yt-analytics.readonly',
  'https://www.googleapis.com/auth/calendar.readonly'
];

/* Global variable that stores user credential in this code example.
 * ACTION ITEM for developers:
 *   Store user's refresh token in your data store if
 *   incorporating this code into your real app.
 *   For more information on handling refresh tokens,
 *   see https://github.com/googleapis/google-api-nodejs-client#handling-refresh-tokens
 */
let userCredential = null;

async function main() {
  const app = express();

  app.use(session({
    secret: 'your_secure_secret_key', // Replace with a strong secret
    resave: false,
    saveUninitialized: false,
  }));

  // Example on redirecting user to Google's OAuth 2.0 server.
  app.get('/', async (req, res) => {
    // Generate a secure random state value.
    const state = crypto.randomBytes(32).toString('hex');
    // Store state in the session
    req.session.state = state;

    // Generate a url that asks permissions for the Drive activity and Google Calendar scope
    const authorizationUrl = oauth2Client.generateAuthUrl({
      // 'online' (default) or 'offline' (gets refresh_token)
      access_type: 'offline',
      /** Pass in the scopes array defined above.
        * Alternatively, if only one scope is needed, you can pass a scope URL as a string */
      scope: scopes,
      // Enable incremental authorization. Recommended as a best practice.
      include_granted_scopes: true,
      // Include the state parameter to reduce the risk of CSRF attacks.
      state: state
    });

    res.redirect(authorizationUrl);
  });

  // Receive the callback from Google's OAuth 2.0 server.
  app.get('/oauth2callback', async (req, res) => {
    // Handle the OAuth 2.0 server response
    let q = url.parse(req.url, true).query;

    if (q.error) { // An error response e.g. error=access_denied
      console.log('Error:' + q.error);
    } else if (q.state !== req.session.state) { //check state value
      console.log('State mismatch. Possible CSRF attack');
      res.end('State mismatch. Possible CSRF attack');
    } else { // Get access and refresh tokens (if access_type is offline)
      let { tokens } = await oauth2Client.getToken(q.code);
      oauth2Client.setCredentials(tokens);

      /** Save credential to the global variable in case access token was refreshed.
        * ACTION ITEM: In a production app, you likely want to save the refresh token
        *              in a secure persistent database instead. */
      userCredential = tokens;
      
      // User authorized the request. Now, check which scopes were granted.
      if (tokens.scope.includes('https://www.googleapis.com/auth/yt-analytics.readonly'))
      {
        // User authorized read-only Drive activity permission.
        // Example of using Google Drive API to list filenames in user's Drive.
        const drive = google.drive('v3');
        drive.files.list({
          auth: oauth2Client,
          pageSize: 10,
          fields: 'nextPageToken, files(id, name)',
        }, (err1, res1) => {
          if (err1) return console.log('The API returned an error: ' + err1);
          const files = res1.data.files;
          if (files.length) {
            console.log('Files:');
            files.map((file) => {
              console.log(`${file.name} (${file.id})`);
            });
          } else {
            console.log('No files found.');
          }
        });
      }
      else
      {
        // User didn't authorize read-only Drive activity permission.
        // Update UX and application accordingly
      }

      // Check if user authorized Calendar read permission.
      if (tokens.scope.includes('https://www.googleapis.com/auth/calendar.readonly'))
      {
        // User authorized Calendar read permission.
        // Calling the APIs, etc.
      }
      else
      {
        // User didn't authorize Calendar read permission.
        // Update UX and application accordingly
      }
    }
  });

  // Example on revoking a token
  app.get('/revoke', async (req, res) => {
    // Build the string for the POST request
    let postData = "token=" + userCredential.access_token;

    // Options for POST request to Google's OAuth 2.0 server to revoke a token
    let postOptions = {
      host: 'oauth2.googleapis.com',
      port: '443',
      path: '/revoke',
      method: 'POST',
      headers: {
        'Content-Type': 'application/x-www-form-urlencoded',
        'Content-Length': Buffer.byteLength(postData)
      }
    };

    // Set up the request
    const postReq = https.request(postOptions, function (res) {
      res.setEncoding('utf8');
      res.on('data', d => {
        console.log('Response: ' + d);
      });
    });

    postReq.on('error', error => {
      console.log(error)
    });

    // Post the request with data
    postReq.write(postData);
    postReq.end();
  });


  const server = http.createServer(app);
  server.listen(8080);
}
main().catch(console.error);

HTTP/REST

این نمونه Python از چارچوب Flask و کتابخانه Requests برای نمایش جریان وب OAuth 2.0 استفاده می‌کند. توصیه می‌کنیم برای این جریان از «کتابخانه کارخواه Google API» برای Python استفاده کنید. (مثال در برگه Python از کتابخانه مشتری استفاده می‌کند.)

import json
import flask
import requests

app = flask.Flask(__name__)

# To get these credentials (CLIENT_ID CLIENT_SECRET) and for your application, visit
# https://console.cloud.google.com/apis/credentials.
CLIENT_ID = '123456789.apps.googleusercontent.com'
CLIENT_SECRET = 'abc123'  # Read from a file or environmental variable in a real app

# Access scopes for two non-Sign-In scopes: Read-only Drive activity and Google Calendar.
SCOPE = 'https://www.googleapis.com/auth/yt-analytics.readonly https://www.googleapis.com/auth/calendar.readonly'

# Indicate where the API server will redirect the user after the user completes
# the authorization flow. The redirect URI is required. The value must exactly
# match one of the authorized redirect URIs for the OAuth 2.0 client, which you
# configured in the API Console. If this value doesn't match an authorized URI,
# you will get a 'redirect_uri_mismatch' error.
REDIRECT_URI = 'http://example.com/oauth2callback'

@app.route('/')
def index():
  if 'credentials' not in flask.session:
    return flask.redirect(flask.url_for('oauth2callback'))

  credentials = json.loads(flask.session['credentials'])

  if credentials['expires_in'] <= 0:
    return flask.redirect(flask.url_for('oauth2callback'))
  else: 
    # User authorized the request. Now, check which scopes were granted.
    if 'https://www.googleapis.com/auth/drive.metadata.readonly' in credentials['scope']:
      # User authorized read-only Drive activity permission.
      # Example of using Google Drive API to list filenames in user's Drive.
      headers = {'Authorization': 'Bearer {}'.format(credentials['access_token'])}
      req_uri = 'https://youtubeanalytics.googleapis.com/v2/reports'
      r = requests.get(req_uri, headers=headers).text
    else:
      # User didn't authorize read-only Drive activity permission.
      # Update UX and application accordingly
      r = 'User did not authorize Drive permission.'

    # Check if user authorized Calendar read permission.
    if 'https://www.googleapis.com/auth/calendar.readonly' in credentials['scope']:
      # User authorized Calendar read permission.
      # Calling the APIs, etc.
      r += 'User authorized Calendar permission.'
    else:
      # User didn't authorize Calendar read permission.
      # Update UX and application accordingly
      r += 'User did not authorize Calendar permission.'

  return r

@app.route('/oauth2callback')
def oauth2callback():
  if 'code' not in flask.request.args:
    state = str(uuid.uuid4())
    flask.session['state'] = state
    # Generate a url that asks permissions for the Drive activity
    # and Google Calendar scope. Then, redirect user to the url.
    auth_uri = ('https://accounts.google.com/o/oauth2/v2/auth?response_type=code'
                '&client_id={}&redirect_uri={}&scope={}&state={}').format(CLIENT_ID, REDIRECT_URI,
                                                                          SCOPE, state)
    return flask.redirect(auth_uri)
  else:
    if 'state' not in flask.request.args or flask.request.args['state'] != flask.session['state']:
      return 'State mismatch. Possible CSRF attack.', 400

    auth_code = flask.request.args.get('code')
    data = {'code': auth_code,
            'client_id': CLIENT_ID,
            'client_secret': CLIENT_SECRET,
            'redirect_uri': REDIRECT_URI,
            'grant_type': 'authorization_code'}

    # Exchange authorization code for access and refresh tokens (if access_type is offline)
    r = requests.post('https://oauth2.googleapis.com/token', data=data)
    flask.session['credentials'] = r.text
    return flask.redirect(flask.url_for('index'))

if __name__ == '__main__':
  import uuid
  app.secret_key = str(uuid.uuid4())
  app.debug = False
  app.run()

قوانین اعتبارسنجی نشانی وب هدایت

Google قوانین اعتبارسنجی زیر را برای هدایت شناسه‌های URI اعمال می‌کند تا به توسعه‌دهندگان کمک کند برنامه‌هایشان را ایمن نگه دارند. URIهای تغییرمسیر شما باید از این قوانین پیروی کنند. برای تعریف دامنه، میزبان، مسیر، پُرسمان، طرح، و اطلاعات کاربر که در این قوانین استفاده می‌شود، به بخش ۳ «RFC 3986» مراجعه کنید.

قوانین اعتبارسنجی
طرح

URIهای تغییرمسیر باید از طرح HTTPS استفاده کنند، نه HTTP ساده. شناسه‌های منبع یکسان Localhost (ازجمله شناسه‌های منبع یکسان نشانی IP در localhost) از این قانون مستثنی هستند.

میزبان

میزبان‌ها نمی‌توانند نشانی‌های IP خام باشند. نشانی‌های IP میزبان محلی از این قانون مستثنی هستند.

دامنه
  • دامنه سطح بالای میزبان (دامنه سطح بالا) باید به فهرست پسوند عمومی تعلق داشته باشد.
  • دامنه‌های میزبان نمی‌تواند “googleusercontent.com” باشد.
  • شناسه‌های منبع یکسان هدایت نمی‌توانند حاوی دامنه‌های کوتاه‌کننده نشانی وب (مثل goo.gl) باشند، مگراینکه برنامه مالک دامنه باشد. علاوه‌براین، اگر برنامه‌ای که مالک دامنه کوتاه‌کننده است تصمیم بگیرد به آن دامنه هدایت کند، آن URI هدایت باید یا حاوی “/google-callback/” در مسیرش باشد یا به “/google-callback” ختم شود.
  • Userinfo

    شناسه منبع یکسان تغییرمسیر نمی‌تواند حاوی زیرمؤلفه userinfo باشد.

    مسیر

    «شناسه‌های یکنواخت منبع» هدایتگر نمی‌تواند حاوی پیمایش مسیر (که به آن پس‌گرد مسیر هم گفته می‌شود) باشد، که با “/..” یا “\..” یا کدبندی نشانی وب آن‌ها نشان داده می‌شود.

    پُرسمان

    نشانی‌های وب هدایت نباید حاوی هدایت‌های باز باشند.

    Fragment

    نشانی‌های وب هدایت مجدد نمی‌توانند شامل عنصر بخش باشند.

    شخصیت‌ها شناسه منبع یکسان تغییرمسیر نمی‌تواند حاوی نویسه‌های خاصی باشد، ازجمله:
    • نویسه‌های عام ('*')
    • نویسه‌های ASCII چاپ‌نشدنی
    • کدبندی‌های درصد نامعتبر (هر کدبندی درصدی که از قالب کدبندی نشانی وب علامت درصد به‌دنبال دو رقم مبنای شانزده پیروی نکند)
    • نویسه‌های تهی (نویسه تهی کدبندی‌شده، برای نمونه، %00، %C0%80)

    مجوز افزایشی

    در پروتکل OAuth 2.0، برنامه شما برای دسترسی به منابعی که با حوزه‌ها شناسایی می‌شوند، درخواست مجوز می‌کند. بهترین روش تجربه کاربری این است که درخواست مجوز برای منابع را در زمانی که به آن‌ها نیاز دارید انجام دهید. برای فعال کردن این روش، سرور مجوز Google از مجوز افزایشی پشتیبانی می‌کند. این ویژگی به شما امکان می‌دهد تا دامنه‌ها را درصورت نیاز درخواست کنید و، اگر کاربر اجازه را برای دامنه جدید اعطا کند، یک کد مجوز برمی‌گرداند که ممکن است با یک کد حاوی همه دامنه‌هایی که کاربر به پروژه اعطا کرده است مبادله شود.

    برای مثال، فرض کنید برنامه‌ای گزارش‌های YouTube Analytics را بازیابی می‌کند، که برخی از آن‌ها گزارش‌های پولی هستند که نیاز به دسترسی به دامنه اضافی دارند که برای گزارش‌های دیگر لازم نیست. در این حالت، هنگام ورود به سیستم، برنامه ممکن است فقط درخواست دسترسی به https://www.googleapis.com/auth/yt-analytics.readonly را داشته باشد. بااین‌حال، اگر کاربر سعی کند گزارش پولی را بازیابی کند، برنامه می‌تواند درخواست دسترسی به گستره https://www.googleapis.com/auth/yt-analytics-monetary.readonly را نیز داشته باشد.

    برای پیاده‌سازی مجوز افزایشی، جریان عادی درخواست کد دسترسی را تکمیل می‌کنید اما مطمئن شوید که درخواست مجوز شامل محدوده‌هایی باشد که قبلاً اعطا شده است. این رویکرد به برنامه شما امکان می‌دهد از مدیریت چندین کد دسترسی اجتناب کند.

    قوانین زیر برای کد دسترسی به‌دست‌آمده از مجوز افزایشی اعمال می‌شود:

    • از این کد می‌توان برای دسترسی به منابع مربوط به هریک از دامنه‌هایی که در مجوز ترکیبی جدید گنجانده شده‌اند استفاده کرد.
    • وقتی از ژتون بازآوری برای مجوز ترکیبی جهت دریافت کد دسترسی استفاده می‌کنید، کد دسترسی نشان‌دهنده مجوز ترکیبی است و می‌تواند برای هریک از مقادیر scope موجود در پاسخ استفاده شود.
    • مجوز ترکیبی شامل همه دامنه‌هایی است که کاربر به پروژه میانای برنامه‌سازی کاربردی اعطا کرده است، حتی اگر این اعطاها از کارخواه‌های مختلف درخواست شده باشد. برای مثال، اگر کاربری بااستفاده از کلاینت رایانه برنامه به یک حوزه دسترسی اعطا کند و سپس حوزه دیگری را ازطریق کلاینت تلفن همراه به همان برنامه اعطا کند، مجوز ترکیبی شامل هر دو حوزه خواهد بود.
    • اگر نشانه‌ای را که نشان‌دهنده مجوز ترکیبی است باطل کنید، دسترسی به همه حوزه‌های آن مجوز ازطرف کاربر مرتبط به‌طور هم‌زمان باطل می‌شود.

    نمونه‌های کد مختص زبان در مرحله ۱: تنظیم مجوز هدایت به سرور 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 Analytics کاربر را دارد.

    GET https://accounts.google.com/o/oauth2/v2/auth?
      scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fyt-analytics.readonly&
      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
    
          

    Refresh 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");

    پس‌از اینکه کاربر دسترسی آفلاین به دامنه‌های درخواستی اعطا کرد، می‌توانید همچنان از کارخواه API برای دسترسی به «میاناهای برنامه‌سازی کاربردی Google» ازطرف کاربر در زمانی که کاربر آفلاین است استفاده کنید. شیء کارخواه کد دسترسی را درصورت نیاز بازآوری می‌کند.

    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')

    پس‌از اینکه کاربر دسترسی آفلاین به دامنه‌های درخواستی اعطا کرد، می‌توانید همچنان از کارخواه API برای دسترسی به «میاناهای برنامه‌سازی کاربردی Google» ازطرف کاربر در زمانی که کاربر آفلاین است استفاده کنید. شیء کارخواه کد دسترسی را درصورت نیاز بازآوری خواهد کرد.

    Ruby

    اگر برنامه‌تان به دسترسی آفلاین به میانای برنامه‌سازی کاربردی Google نیاز دارد، نوع دسترسی کارخواه میانای برنامه‌سازی کاربردی را روی offline تنظیم کنید:

    auth_client.update!(
      :additional_parameters => {"access_type" => "offline"}
    )

    پس‌از اینکه کاربر دسترسی آفلاین به دامنه‌های درخواستی را اعطا کرد، می‌توانید همچنان از کارخواه میانای برنامه‌سازی کاربردی برای دسترسی به میاناهای برنامه‌سازی کاربردی Google ازطرف کاربر در زمانی که کاربر آفلاین است استفاده کنید. شیء کارخواه کد دسترسی را درصورت نیاز بازآوری خواهد کرد.

    Node.js

    اگر برنامه شما به دسترسی آفلاین به «میانای برنامه‌سازی کاربردی Google» نیاز دارد، نوع دسترسی کارخواه «میانای برنامه‌سازی کاربردی» را روی 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 ازطرف کاربر در زمانی که کاربر آفلاین است استفاده کنید. شیء کارخواه کد دسترسی را درصورت نیاز بازآوری می‌کند.

    کدهای دسترسی منقضی می‌شوند. این کتابخانه به‌طور خودکار از یک ژتون بازآوری برای دریافت یک کد دسترسی جدید استفاده می‌کند، اگر کد دسترسی قبلی درحال انقضا باشد. یک راه آسان برای اطمینان از اینکه همیشه جدیدترین توکن‌ها را ذخیره می‌کنید، استفاده از رویداد توکن‌ها است:

    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`
    });

    وقتی کارخواه ژتون بازآوری داشته باشد، ژتون‌های دسترسی به‌طور خودکار در فراخوانی بعدی به API دریافت و بازآوری خواهند شد.

    HTTP/REST

    برای بازآوری کد دسترسی، برنامه‌تان درخواست HTTPS POST به سرور مجوز Google (https://oauth2.googleapis.com/token) ارسال می‌کند که شامل پارامترهای زیر در بدنه درخواست است:

    نام مقدار
    client_id شناسه مشتری به‌دست‌آمده از کنسول API.
    client_secret اختیاری

    رمز کارخواه دریافت‌شده از کنسول API.

    grant_type همان‌طور که در مشخصات OAuth 2.0 تعریف شده است، مقدار این فیلد باید روی refresh_token تنظیم شود.
    refresh_token نمودار بازآوری برگشتی از تبادل کد مجوز.

    هرچند استفاده از DPoP اختیاری است، اما برای افزایش امنیت توصیه می‌شود. برای استفاده از DPoP با رمز بازآوری، برنامه شما باید برای هر درخواست به نقطه پایانی رمز، یک JWT اثبات DPoP جدید و منحصربه‌فرد تولید کند. این مدرک باید با همان کلید خصوصی‌ای امضا شود که درطول تبادل اولیه کد مجوز استفاده شده است. برنامه شما مدرک را به‌عنوان سرصفحه درخواست HTTP اضافه می‌کند.

    سرایند الزامی شرح
    DPoP اختیاری اثبات DPoP یک JWT است که مالکیت کلید خصوصی را اثبات می‌کند. این سرصفحه است، نه پارامتر. درصورت ارائه، نشان‌های برگردانده‌شده به این کلید محدود می‌شوند. برای هر درخواست باید مدرک جدید و منحصربه‌فردی تولید شود و باید شامل ادعاهای htm (روش HTTP) و htu (شناسه منبع یکسان HTTP) باشد که با درخواست مطابقت داشته باشد.

    قطعه کد زیر یک درخواست نمونه را نشان می‌دهد:

    POST /token HTTP/1.1
    Host: oauth2.googleapis.com
    Content-Type: application/x-www-form-urlencoded
    DPoP: DPOP_PROOF_JWT
    
    client_id=your_client_id&
    refresh_token=refresh_token&
    grant_type=refresh_token

    برای استفاده از DPoP با ژتون بازآوری، باید JWT اثبات DPoP جدید و منحصربه‌فردی برای درخواست تولید کنید. برای دستورالعمل‌های گام‌به‌گام درباره تولید جفت کلید و ساختن JWT، به ساختن اثبات DPoP مراجعه کنید.

    تبادل موفق با پاسخ 200 OK حاوی کد دسترسی جدید نشان داده می‌شود. وقتی از DPoP استفاده می‌شود، token_type Bearer است. پاسخ موفقیت‌آمیز تأیید می‌کند که اثبات DPoP برای ژتون بازآوری پذیرفته شده است. Google همچنین ممکن است سرصفحه HTTP جدید DPoP-Nonce را در پاسخ برگرداند؛ درصورت برگردانده شدن، کارخواه شما باید این nonce را در حافظه نهان ذخیره کند و آن را در ادعای nonce اثبات DPoP در درخواست‌های بعدی لحاظ کند.

    اگر سرایند DPoP وجود نداشته باشد، نامعتبر باشد، یا از کلید نادرستی استفاده کند، تبادل ناموفق رخ می‌دهد. برای جزئیات مربوط به کدهای خطای خاص DPoP و مدیریت نانس‌ها، به تبادل ناموفق مراجعه کنید.

    تکه کد زیر سرصفحه‌ها و متن پاسخ موفقیت‌آمیز نمونه‌ای را هنگام استفاده از DPoP نشان می‌دهد:

    HTTP/1.1 200 OK
    Content-Type: application/json; charset=utf-8
    DPoP-Nonce: AN3XwJjZsjnb0ZuWkRlek8QU7wY-Zhf-5IP6tO0tORz0KgtDT1Bo8FX-w4nz3r5lnepI
    
    {
      "access_token": "1/fFAGRNJru1FTz70BzhT3Zg",
      "expires_in": 3920,
      "scope": "https://www.googleapis.com/auth/drive.metadata.readonly https://www.googleapis.com/auth/calendar.readonly",
      "token_type": "Bearer"
    }

    توجه داشته باشید که محدودیت‌هایی برای تعداد کدهای بازآوری صادرشده وجود دارد؛ یک محدودیت برای ترکیب کاربر/کارخواه، و محدودیت دیگر برای کاربر در همه کارخواه‌ها. باید کدهای بازآوری را در فضای ذخیره‌سازی بلندمدت ذخیره کنید و تا زمانی که معتبر هستند از آن‌ها استفاده کنید. اگر برنامه شما توکن‌های بازآوری زیادی درخواست کند، ممکن است با این محدودیت‌ها مواجه شود، در این صورت توکن‌های بازآوری قدیمی‌تر ازکار خواهند افتاد.

    ابطال کد

    در برخی موارد، ممکن است کاربر بخواهد دسترسی اعطاشده به برنامه‌ای را لغو کند. کاربر می‌تواند با مراجعه به تنظیمات حساب، دسترسی را لغو کند. برای اطلاعات بیشتر، به سند پشتیبانی برداشتن دسترسی سایت یا برنامه در بخش «برنامه‌ها و سایت‌های طرف سوم با امکان دسترسی به حساب شما» مراجعه کنید.

    همچنین این امکان وجود دارد که برنامه به‌صورت برنامه‌نویسی‌شده دسترسی اعطاشده به آن را لغو کند. لغو برنامه‌ریزی‌شده در مواردی که کاربر لغو اشتراک می‌کند، برنامه را برمی‌دارد، یا منابع API موردنیاز برنامه به‌طور قابل‌توجهی تغییر کرده است، اهمیت دارد. به‌عبارت دیگر، بخشی از فرایند برداشتن محتوا می‌تواند شامل درخواست API برای اطمینان از برداشته شدن اجازه‌هایی باشد که قبلاً به برنامه داده شده است.

    PHP

    برای لغو کردن کد به‌صورت برنامه‌نویسی‌شده، با revokeToken() تماس بگیرید:

    $client->revokeToken();

    Python

    برای باطل کردن برنامه‌ریزی‌شده یک کد، درخواستی به https://oauth2.googleapis.com/revoke ارسال کنید که کد را به‌عنوان پارامتر دربرمی‌گیرد و سرصفحه Content-Type را تنظیم می‌کند:

    requests.post('https://oauth2.googleapis.com/revoke',
        params={'token': credentials.token},
        headers = {'content-type': 'application/x-www-form-urlencoded'})

    Ruby

    برای لغو کردن برنامه‌ریزی‌شده یک کد، یک درخواست HTTP به نقطه پایان oauth2.revoke ارسال کنید:

    uri = URI('https://oauth2.googleapis.com/revoke')
    response = Net::HTTP.post_form(uri, 'token' => auth_client.access_token)

    این ژتون می‌تواند ژتون دسترسی یا ژتون بازآوری باشد. اگر کد از نوع کد دسترسی باشد و کد بازآوری متناظر داشته باشد، کد بازآوری نیز باطل خواهد شد.

    اگر ابطال باموفقیت پردازش شود، کد وضعیت پاسخ 200 خواهد بود. برای شرایط خطا، رمز وضعیت 400 به‌همراه کد خطا برگردانده می‌شود.

    Node.js

    برای لغو کردن برنامه‌ریزی‌شده یک کد، یک درخواست HTTPS POST به نقطه پایان /revoke ارسال کنید:

    const https = require('https');
    
    // Build the string for the POST request
    let postData = "token=" + userCredential.access_token;
    
    // Options for POST request to Google's OAuth 2.0 server to revoke a token
    let postOptions = {
      host: 'oauth2.googleapis.com',
      port: '443',
      path: '/revoke',
      method: 'POST',
      headers: {
        'Content-Type': 'application/x-www-form-urlencoded',
        'Content-Length': Buffer.byteLength(postData)
      }
    };
    
    // Set up the request
    const postReq = https.request(postOptions, function (res) {
      res.setEncoding('utf8');
      res.on('data', d => {
        console.log('Response: ' + d);
      });
    });
    
    postReq.on('error', error => {
      console.log(error)
    });
    
    // Post the request with data
    postReq.write(postData);
    postReq.end();

    پارامتر رمز می‌تواند رمز دسترسی یا رمز بازآوری باشد. اگر کد از نوع کد دسترسی باشد و کد بازآوری متناظر داشته باشد، کد بازآوری نیز باطل خواهد شد.

    اگر ابطال باموفقیت پردازش شود، کد وضعیت پاسخ 200 خواهد بود. برای شرایط خطا، رمز وضعیت 400 به‌همراه کد خطا برگردانده می‌شود.

    HTTP/REST

    برای لغو کردن توکن به‌صورت برنامه‌نویسی‌شده، برنامه شما درخواستی به https://oauth2.googleapis.com/revoke ارسال می‌کند و توکن را به‌عنوان پارامتر اضافه می‌کند:

    curl -d -X -POST --header "Content-type:application/x-www-form-urlencoded" \
            https://oauth2.googleapis.com/revoke?token={token}

    کد می‌تواند کد دسترسی یا کد بازآوری باشد. اگر داده‌واحد یک داده‌واحد دسترسی باشد و داده‌واحد بازآوری مربوطه را داشته باشد، داده‌واحد بازآوری نیز باطل خواهد شد.

    اگر لغو با موفقیت پردازش شود، رمز وضعیت HTTP پاسخ 200 است. برای شرایط خطا، رمز وضعیت HTTP 400 به‌همراه کد خطا برگردانده می‌شود.

    دسترسی زمان‌محور

    دسترسی مبتنی بر زمان به کاربر امکان می‌دهد برای انجام یک کنش، به برنامه شما اجازه دهد برای مدت محدودی به داده‌هایش دسترسی داشته باشد. دسترسی مبتنی بر زمان در محصولات منتخب Google درطول جریان موافقت دردسترس است و به کاربران امکان می‌دهد برای مدت محدودی دسترسی اعطا کنند. برای مثال، Data Portability API امکان انتقال یک‌باره داده‌ها را فراهم می‌کند.

    وقتی کاربری به برنامه شما دسترسی زمان‌دار می‌دهد، رمز بازآوری پس‌از مدت زمان مشخص منقضی می‌شود. توجه داشته باشید که ژتون‌های بازآوری ممکن است در شرایط خاصی زودتر باطل شوند؛ برای جزئیات بیشتر، این موارد را ببینید. فیلد refresh_token_expires_in که در پاسخ تبادل کد مجوز برگردانده می‌شود، نشان‌دهنده زمان باقی‌مانده تا انقضای ژتون بازآوری در چنین مواردی است.

    پیاده‌سازی «محافظت بین‌حسابی»

    یکی از اقدامات تکمیلی که باید برای محافظت از حساب‌های کاربران خود انجام دهید، پیاده‌سازی «محافظت بین‌حسابی» بااستفاده از «سرویس محافظت بین‌حسابی» Google است. این سرویس به شما امکان می‌دهد در اعلان‌های رویداد امنیتی مشترک شوید که اطلاعاتی درباره تغییرات عمده در حساب کاربر به برنامه‌تان ارائه می‌دهد. سپس می‌توانید از این اطلاعات برای اقدام کردن براساس نحوه تصمیم‌گیری‌تان برای پاسخ دادن به رویدادها استفاده کنید.

    برخی‌از نمونه‌های انواع رویدادهایی که «سرویس محافظت بین‌حسابی» Google به برنامه‌تان ارسال می‌کند عبارت‌اند از:

    • https://schemas.openid.net/secevent/risc/event-type/sessions-revoked
    • https://schemas.openid.net/secevent/oauth/event-type/token-revoked
    • https://schemas.openid.net/secevent/risc/event-type/account-disabled

    برای کسب اطلاعات بیشتر درباره نحوه پیاده‌سازی «محافظت بین‌حسابی» و فهرست کامل رویدادهای دردسترس، به صفحه «محافظت از حساب‌های کاربری با محافظت بین‌حسابی» مراجعه کنید.