این سند توضیح میدهد که برنامههای وب سرور چگونه از «کتابخانههای کارخواه Google API» یا نقاط پایانی Google OAuth 2.0 برای پیادهسازی مجوز OAuth 2.0 جهت دسترسی به YouTube Data API استفاده میکنند.
OAuth 2.0 به کاربران اجازه میدهد دادههای خاصی را با برنامهای همرسانی کنند و درعینحال نامهای کاربری، گذرواژهها، و اطلاعات دیگرشان را خصوصی نگه دارند. برای مثال، یک برنامه میتواند از OAuth 2.0 برای دریافت اجازه برای بازیابی دادههای YouTube یک کانال استفاده کند.
این جریان OAuth 2.0 بهطور خاص برای صدور مجوز کاربر است. این نوع برای برنامههایی طراحی شده است که میتوانند اطلاعات محرمانه را ذخیره کنند و وضعیت را حفظ کنند. یک برنامه کارساز وب که بهدرستی مجوز گرفته باشد میتواند درحالیکه کاربر با برنامه تعامل دارد یا پساز اینکه کاربر برنامه را ترک کرد، به میانای برنامهسازی کاربردی دسترسی پیدا کند.
برنامههای سرور وب اغلب از حسابهای سرویس نیز برای صدور مجوز درخواستهای API استفاده میکنند، بهویژه هنگام فراخوانی Cloud API برای دسترسی به دادههای مبتنی بر پروژه بهجای دادههای مختص کاربر. برنامههای کارساز وب میتوانند از حسابهای خدمات همراه با مجوز کاربر استفاده کنند.
«میانای برنامهسازی کاربردی جاریسازی زنده YouTube» از جریان حساب سرویس پشتیبانی نمیکند. ازآنجاییکه هیچ راهی برای پیوند دادن «حساب سرویس» به حساب YouTube وجود ندارد، تلاش برای صدور مجوز درخواستها با این جریان، خطای NoLinkedYouTubeAccount را ایجاد میکند.
کتابخانههای مشتری
نمونههای مختص زبان در این صفحه از کتابخانههای کارخواه Google API برای پیادهسازی مجوز OAuth 2.0 استفاده میکنند. برای اجرای نمونههای کد، ابتدا باید کتابخانه مشتری را برای زبان خود نصب کنید.
وقتی از «کتابخانه کارخواه Google API» برای مدیریت جریان OAuth 2.0 برنامهتان استفاده میکنید، کتابخانه کارخواه کنشهای زیادی را انجام میدهد که درغیراینصورت برنامه باید خودش آنها را مدیریت کند. برای مثال، تعیین میکند که برنامه چه زمانی میتواند از نشانهای دسترسی ذخیرهشده استفاده کند یا آنها را بازآوری کند و همچنین چه زمانی برنامه باید رضایت را دوباره کسب کند. کتابخانه کارخواه همچنین نشانیهای وب بازهدایت صحیح تولید میکند و به پیادهسازی گردانندههای بازهدایت که کدهای مجوز را با کد دسترسی معاوضه میکنند کمک میکند.
«کتابخانههای کارخواه Google API» برای برنامههای سمت سرور برای زبانهای زیر دردسترس است:
پیشنیازها
فعال کردن میاناهای برنامهسازی کاربردی برای پروژه
هر برنامهای که میاناهای برنامهسازی کاربردی Google را فراخوانی میکند باید آن میاناهای برنامهسازی کاربردی را در «کنسول میانای برنامهسازی کاربردی» فعال کند.
برای فعال کردن میانای برنامهسازی کاربردی برای پروژهتان:
- در «کنسول Google API»، کتابخانه API را باز کنید.
- اگر درخواست شد، پروژهای را انتخاب کنید یا پروژه جدیدی ایجاد کنید.
- از صفحه «کتابخانه» برای پیدا کردن و فعال کردن YouTube Data API استفاده کنید. هر API دیگری را که برنامهتان استفاده خواهد کرد پیدا کنید و آنها را نیز فعال کنید.
ایجاد اعتبارنامههای مجوز
هر برنامهای که از OAuth 2.0 برای دسترسی به Google APIs استفاده میکند باید اطلاعات اعتباری مجوز داشته باشد که برنامه را به سرور OAuth 2.0 Google معرفی کند. مراحل زیر نحوه ایجاد اعتبارنامه برای پروژهتان را توضیح میدهد. سپس برنامههایتان میتوانند از اطلاعات اعتباری برای دسترسی به میاناهای برنامهسازی کاربردی که برای آن پروژه فعال کردهاید استفاده کنند.
- به صفحه «کارخواهان» بروید.
- روی ایجاد کارخواه کلیک کنید.
- نوع برنامه برنامه وب را انتخاب کنید.
- فرم را تکمیل کنید و روی ایجاد کلیک کنید. برنامههایی که از زبانها و چارچوبهایی
مثل PHP، Java، Python، Ruby، و NET .استفاده میکنند باید URIهای بازهدایت مجاز را مشخص کنند. URIهای
هدایت نقاط پایانی هستند که سرور OAuth 2.0 میتواند پاسخها را به آنها ارسال کند. این
نقطههای پایانی باید از قوانین اعتبارسنجی Google پیروی کنند.
برای آزمایش، میتوانید نشانیهای وب را که به ماشین محلی ارجاع میدهند مشخص کنید، برای نمونه
http://localhost:8080. همه مثالهای این سند ازhttp://localhost:8080بهعنوان URI هدایت استفاده میکنند.توصیه میکنیم پایانههای اصالتسنجی برنامهتان را بهگونهای طراحی کنید که برنامهتان کدهای مجوز را برای منابع دیگر در صفحه فاش نکند.
پساز ایجاد اطلاعات اعتباری، فایل client_secret.json را از «کنسول API» بارگیری کنید. فایل را بهطور ایمن در مکانی ذخیره کنید که فقط برنامه شما بتواند به آن دسترسی داشته باشد.
شناسایی محدودههای دسترسی
محدودهها به برنامه شما امکان میدهند فقط به منابعی که نیاز دارد دسترسی پیدا کند و درعینحال به کاربران امکان میدهند میزان دسترسیای را که به برنامه شما میدهند کنترل کنند. بنابراین، ممکن است بین تعداد گسترههای درخواستی و احتمال دریافت رضایت کاربر رابطه معکوس وجود داشته باشد.
قبلاز شروع پیادهسازی مجوز OAuth 2.0، توصیه میکنیم دامنههایی را که برنامهتان برای دسترسی به آنها نیاز به اجازه دارد شناسایی کنید.
همچنین توصیه میکنیم برنامه شما ازطریق فرایند مجوز فزاینده، که در آن برنامه شما دسترسی به دادههای کاربر را در بافت درخواست میکند، دسترسی به محدودههای مجوز را درخواست کند. این روال مطلوب به کاربران کمک میکند راحتتر متوجه شوند چرا برنامهتان به دسترسیای که درخواست میکند نیاز دارد.
YouTube Data API v3 از دامنههای زیر استفاده میکند:
| دامنه | توضیحات |
|---|---|
https://www. googleapis. com/ auth/ youtube | حساب YouTube خود را مدیریت کنید |
https://www. googleapis. com/ auth/ youtube. channel-memberships. creator | فهرستی از اعضای فعال فعلی کانال خود، سطح فعلی آنها و زمان عضویت آنها را مشاهده کنید |
https://www. googleapis. com/ auth/ youtube. force-ssl | ویدیوها، رتبهبندیها، نظرات و زیرنویسهای YouTube خود را مشاهده، ویرایش و برای همیشه حذف کنید |
https://www. googleapis. com/ auth/ youtube. readonly | حساب YouTube خود را مشاهده کنید |
https://www. googleapis. com/ auth/ youtube. upload | ویدیوهای YouTube خود را مدیریت کنید |
https://www. googleapis. com/ auth/ youtubepartner | دارایی ها و محتوای مرتبط خود را در YouTube مشاهده و مدیریت کنید |
https://www. googleapis. com/ auth/ youtubepartner-channel-audit | اطلاعات خصوصی مربوط به کانال YouTube خود را در طول فرآیند ممیزی با شریک YouTube مشاهده کنید |
سند OAuth 2.0 API Scopes حاوی فهرست کاملی از دامنههایی است که ممکن است برای دسترسی به Google API استفاده کنید.
الزامات خاص زبان
برای اجرای هریک از نمونههای کد در این سند، به «حساب Google»، دسترسی به اینترنت، و مرورگر وب نیاز دارید. اگر از یکی از کتابخانههای مشتری API استفاده میکنید، الزامات خاص زبان را نیز در بخشهای زیر ببینید.
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:
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
-
کتابخانههای مشتری برای Drive و Calendar Google APIs:
gem install google-apis-drive_v3 google-apis-calendar_v3
-
چارچوب برنامه وب Sinatra Ruby.
gem install sinatra
Node.js
برای اجرای نمونههای کد Node.js در این سند، به موارد زیر نیاز دارید:
- نسخه LTS نگهداری، LTS فعال، یا نسخه فعلی Node.js.
-
کارخواه Google APIs Node.js:
npm install googleapis crypto express express-session
HTTP/REST
برای اینکه بتوانید مستقیماً نقاط پایانی OAuth 2.0 را فراخوانی کنید، نیازی به نصب هیچ کتابخانهای ندارید.
دریافت کدهای دسترسی OAuth 2.0
مراحل زیر نشان میدهد که برنامه شما چگونه با سرور OAuth 2.0 Google تعامل میکند تا رضایت کاربر را برای انجام درخواست میانای برنامهسازی کاربردی ازطرف کاربر دریافت کند. برنامه شما باید قبلاز اجرای درخواست Google API که به مجوز کاربر نیاز دارد، این رضایت را داشته باشد.
فهرست زیر این مراحل را بهطور خلاصه نشان میدهد:
- برنامه شما اجازههای موردنیازش را شناسایی میکند.
- برنامه شما کاربر را بههمراه فهرست اجازههای درخواستشده به Google هدایت میکند.
- کاربر تصمیم میگیرد که این اجازهها را به برنامه شما بدهد یا نه.
- برنامه شما متوجه میشود که کاربر چه تصمیمی گرفته است.
- اگر کاربر اجازههای درخواستشده را اعطا کند، برنامه شما نشانهای لازم برای ایجاد درخواستهای «میانای برنامهسازی کاربردی» ازطرف کاربر را بازیابی میکند.
مرحله ۱: تنظیم پارامترهای مجوز
اولین قدم شما ایجاد درخواست مجوز است. این درخواست پارامترهایی را تنظیم میکند که برنامه شما را شناسایی میکند و اجازههایی را تعریف میکند که از کاربر خواسته میشود به برنامه شما اعطا کند.
- اگر از کتابخانه کارخواه Google برای اصالتسنجی و مجوزدهی OAuth 2.0 استفاده میکنید، شیئی را ایجاد و پیکربندی میکنید که این پارامترها را تعریف میکند.
- اگر مستقیماً نقطه پایانی Google OAuth 2.0 را فراخوانی کنید، نشانی وب تولید خواهید کرد و پارامترها را در آن نشانی وب تنظیم خواهید کرد.
برگههای زیر پارامترهای مجوز پشتیبانیشده برای برنامههای سرور وب را تعریف میکنند. مثالهای مختص زبان همچنین نشان میدهند که چگونه از کتابخانه کارخواه یا کتابخانه مجوز برای پیکربندی شیئی که این پارامترها را تنظیم میکند استفاده کنید:
PHP
تکهکد زیر شیء Google\Client() را ایجاد میکند که پارامترهای درخواست صدور مجوز را تعریف میکند.
آن شیء از اطلاعات فایل client_secret.json شما برای شناسایی برنامهتان استفاده میکند. (برای اطلاعات بیشتر درباره آن فایل، ایجاد اعتبارنامههای مجوز را ببینید.) این شیء همچنین دامنههایی را که برنامهتان برای دسترسی به آنها درخواست اجازه میکند و نشانی وب نقطه پایانی اصالتسنجی برنامهتان را که پاسخ سرور OAuth 2.0 در Google را مدیریت میکند شناسایی میکند. درنهایت، کد پارامترهای اختیاری access_type و
include_granted_scopes را تنظیم میکند.
برای مثال، برای درخواست دسترسی آفلاین برای بازیابی دادههای YouTube کاربر:
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_YouTube::YOUTUBE_FORCE_SSL); // Required, call the setRedirectUri function to specify a valid redirect URI for the // provided client_id $client->setRedirectUri('http://' . $_SERVER['HTTP_HOST'] . '/oauth2callback.php'); // Recommended, offline access will give you both an access and refresh token so that // your app can refresh the access token without user interaction. $client->setAccessType('offline'); // Recommended, call the setState function. Using a state value can increase your assurance that // an incoming connection is the result of an authentication request. $client->setState($sample_passthrough_value); // Optional, if your application knows which user is trying to authenticate, it can use this // parameter to provide a hint to the Google Authentication Server. $client->setLoginHint('hint@example.com'); // Optional, call the setPrompt function to set "consent" will prompt the user for consent $client->setPrompt('consent'); // Optional, call the setIncludeGrantedScopes function with true to enable incremental // authorization $client->setIncludeGrantedScopes(true);
Python
تکه کد زیر از واحد google-auth-oauthlib.flow برای ساختن درخواست
مجوز استفاده میکند.
این کد شیء Flow را میسازد که برنامه شما را بااستفاده از
اطلاعات فایل client_secret.json که پساز
ایجاد اطلاعات اعتباری مجوز بارگیری کردهاید شناسایی میکند. آن شیء همچنین دامنههایی را که برنامه شما برای دسترسی به آنها اجازه درخواست میکند و نشانی وب نقطه پایانی اصالتسنجی برنامه شما را که پاسخ سرور OAuth 2.0 از Google را مدیریت میکند مشخص میکند. در نهایت، کد
پارامترهای اختیاری access_type و include_granted_scopes را تنظیم میکند.
برای مثال، برای درخواست دسترسی آفلاین برای بازیابی دادههای YouTube کاربر:
import google.oauth2.credentials import google_auth_oauthlib.flow # Required, call the from_client_secrets_file method to retrieve the client ID from a # client_secret.json file. The client ID (from that file) and access scopes are required. (You can # also use the from_client_config method, which passes the client configuration as it originally # appeared in a client secrets file but doesn't access the file itself.) flow = google_auth_oauthlib.flow.Flow.from_client_secrets_file('client_secret.json', scopes=['https://www.googleapis.com/auth/youtube.force-ssl', '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 کاربر:
require 'googleauth' require 'googleauth/web_user_authorizer' require 'googleauth/stores/redis_token_store' require 'google/apis/youtube_v3' require 'google/apis/calendar_v3' # Required, call the from_file method to retrieve the client ID from a # client_secret.json file. client_id = Google::Auth::ClientId.from_file('/path/to/client_secret.json') # Required, scope value # Access scopes for two non-Sign-In scopes: Read-only Drive activity and Google Calendar. scope = ['Google::Apis::DriveV3::AUTH_DRIVE_METADATA_READONLY', 'Google::Apis::CalendarV3::AUTH_CALENDAR_READONLY'] # Required, Authorizers require a storage instance to manage long term persistence of # access and refresh tokens. token_store = Google::Auth::Stores::RedisTokenStore.new(redis: Redis.new) # Required, indicate where the API server will redirect the user after the user completes # the authorization flow. The redirect URI is required. The value must exactly # match one of the authorized redirect URIs for the OAuth 2.0 client, which you # configured in the API Console. If this value doesn't match an authorized URI, # you will get a 'redirect_uri_mismatch' error. callback_uri = '/oauth2callback' # To use OAuth2 authentication, we need access to a CLIENT_ID, CLIENT_SECRET, AND REDIRECT_URI # from the client_secret.json file. To get these credentials for your application, visit # https://console.cloud.google.com/apis/credentials. authorizer = Google::Auth::WebUserAuthorizer.new(client_id, scope, token_store, callback_uri)
برنامه شما از شیء کارخواه برای انجام عملیات OAuth 2.0 استفاده میکند، مانند تولید نشانیهای وب درخواست مجوز و اعمال کد دسترسی به درخواستهای 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/youtube.force-ssl', '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 کارخواهتان در
صفحه «کارخواهها» پیکربندی کردهاید. اگر این مقدار با شناسه منبع یکسان هدایت مجاز برای توجه داشته باشید که طرح |
||||||||||||||||
response_type |
الزامی
تعیین میکند که آیا نقطه پایان Google OAuth 2.0 کد مجوز برمیگرداند یا نه. مقدار پارامتر را برای برنامههای سرور وب روی |
||||||||||||||||
scope |
الزامی
فهرستی از حوزهها که با فاصله از هم جدا شدهاند و منابعی را که برنامه شما میتواند ازطرف کاربر به آنها دسترسی داشته باشد شناسایی میکند. این مقادیر به صفحه رضایت که Google به کاربر نمایش میدهد اطلاعرسانی میکند. گسترهها به برنامه شما امکان میدهند فقط به منابعی که نیاز دارد دسترسی داشته باشد و درعینحال به کاربران امکان میدهند میزان دسترسیای را که به برنامه شما میدهند کنترل کنند. بنابراین، رابطهای معکوس بین تعداد دامنههای درخواستی و احتمال کسب رضایت کاربر وجود دارد. YouTube Data API v3 از دامنههای زیر استفاده میکند:
سند OAuth 2.0 API Scopes فهرست کاملی از دامنههایی را که ممکن است برای دسترسی به Google APIs استفاده کنید ارائه میدهد. توصیه میکنیم برنامهتان درصورت امکان، دسترسی به گسترههای مجوز را در بافت درخواست کند. با درخواست دسترسی به دادههای کاربر در بافت، بااستفاده از مجوز فزاینده، به کاربران کمک میکنید متوجه شوند چرا برنامه شما به دسترسیای که درخواست میکند نیاز دارد. |
||||||||||||||||
access_type |
توصیهشده
نشان میدهد که آیا برنامه شما میتواند کد دسترسی را وقتی کاربر در مرورگر حضور ندارد بازآوری کند یا نه. مقادیر پارامتر معتبر عبارتند از اگر برنامه شما نیاز دارد کد دسترسی را وقتی کاربر در مرورگر حضور ندارد بازآوری کند،
مقدار را روی |
||||||||||||||||
state |
توصیهشده
هر مقدار رشتهای را که برنامه شما برای حفظ وضعیت بین درخواست
صدور مجوز و پاسخ سرور صدور مجوز استفاده میکند مشخص میکند.
سرور مقدار دقیقی را که بهعنوان جفت میتوانید از این پارامتر برای اهداف مختلفی استفاده کنید، ازجمله هدایت کاربر به
منبع صحیح در برنامهتان، ارسال نانس، و کاهش جعل درخواست
بینسایتی. ازآنجاییکه |
||||||||||||||||
include_granted_scopes |
اختیاری
به برنامهها امکان میدهد از صدور مجوز افزایشی برای درخواست دسترسی به
حوزههای اضافی در زمینه استفاده کنند. اگر مقدار این پارامتر را روی |
||||||||||||||||
enable_granular_consent |
اختیاری
پیشفرض وقتی Google اجازههای ریزدانه را برای برنامهای فعال میکند، این پارامتر دیگر تأثیری نخواهد داشت. |
||||||||||||||||
login_hint |
اختیاری
اگر برنامه شما میداند کدام کاربر درحال تلاش برای اصالتسنجی است، میتواند از این پارامتر برای ارائه راهنمایی به «سرور اصالتسنجی Google» استفاده کند. سرور از این راهنمایی برای ساده کردن جریان ورود به سیستم استفاده میکند، یا با پیشتکمیل کردن فیلد ایمیل در فرم ورود به سیستم یا با انتخاب جلسه چندورودی مناسب. مقدار پارامتر را روی نشانی ایمیل یا شناسه |
||||||||||||||||
prompt |
اختیاری
فهرست حساس به حروف بزرگ و کوچک با جداکننده فاصله از پیاموارههایی که به کاربر ارائه میشود. اگر این پارامتر را مشخص نکنید، فقط اولین باری که پروژه شما درخواست دسترسی میکند، از کاربر درخواست خواهد شد. برای اطلاعات بیشتر، درخواست رضایت مجدد را ببینید. مقادیر ممکن عبارتاند از:
|
||||||||||||||||
مرحله ۲: هدایت به سرور OAuth 2.0 Google
کاربر را به سرور OAuth 2.0 Google هدایت کنید تا فرایند اصالتسنجی و صدور مجوز را آغاز کند. معمولاً این اتفاق زمانی میافتد که برنامه شما برای اولینبار نیاز به دسترسی به دادههای کاربر دارد. درصورت مجوزدهی افزایشی، این مرحله زمانی نیز رخ میدهد که برنامه شما برای اولینبار نیاز به دسترسی به منابع اضافی دارد که اجازه دسترسی به آنها را ندارد.
PHP
- نشانی وبی برای درخواست دسترسی از سرور OAuth 2.0 متعلق به Google ایجاد کنید:
$auth_url = $client->createAuthUrl(); - هدایت کاربر به
$auth_url:header('Location: ' . filter_var($auth_url, FILTER_SANITIZE_URL));
Python
این مثال نشان میدهد که چگونه کاربر را بااستفاده از چارچوب برنامه وب Flask به نشانی وب اصالتسنجی هدایت کنید:
return flask.redirect(authorization_url)
Ruby
- نشانی وبی برای درخواست دسترسی از سرور OAuth 2.0 Google تولید کنید:
auth_uri = authorizer.get_authorization_url(request: request)
- کاربر را به
auth_uriهدایت کنید.
Node.js
-
از نشانی وب تولیدشده
authorizationUrlاز روش مرحله ۱generateAuthUrlبرای درخواست دسترسی از سرور Google OAuth 2.0 استفاده کنید. -
کاربر را به
authorizationUrlهدایت کنید.res.redirect(authorizationUrl);
HTTP/REST
نمونه هدایت به سرور مجوز Google
نشانی وب نمونه در زیر نشان داده شده است، با شکست خط و فاصله برای خوانایی. نشانی وب درخواست دسترسی به دامنهای میکند که اجازه دسترسی به بازیابی دادههای YouTube کاربر را میدهد. این روش از مجوز افزایشی (include_granted_scopes=true) استفاده میکند تا اطمینان حاصل شود که کد دسترسی جدید هر دامنهای را که کاربر قبلاً به برنامه دسترسی داده است، پوشش میدهد. چند پارامتر دیگر نیز در این مثال تنظیم شده است.
https://accounts.google.com/o/oauth2/v2/auth? scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fyoutube.force-ssl& access_type=offline& include_granted_scopes=true& response_type=code& state=state_parameter_passthrough_value& redirect_uri=http%3A%2F%2Flocalhost%2Foauth2callback& client_id=client_id
پساز ایجاد نشانی وب درخواست، کاربر را به آن هدایت کنید.
سرور OAuth 2.0 متعلق به 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%2Fyoutube.force-ssl& access_type=offline& include_granted_scopes=true& response_type=code& state=state_parameter_passthrough_value& redirect_uri=http%3A%2F%2Flocalhost%2Foauth2callback& client_id=client_id
پساز تکمیل جریان OAuth 2.0، مرورگرتان شما را به 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/youtube.force-ssl'], state=state) flow.redirect_uri = flask.url_for('oauth2callback', _external=True) authorization_response = flask.request.url flow.fetch_token(authorization_response=authorization_response) # Store the credentials in 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
در صفحه callback، از کتابخانه 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 |
یکی از نشانیهای وب هدایت فهرستشده برای پروژه شما در
Cloud Console
صفحه «کارخواهها» برای
client_id دادهشده. |
هرچند استفاده از DPoP اختیاری است، اما برای افزایش امنیت توصیه میشود. امنیت DPoP به محدود شدن کلید خصوصی به یک دستگاه واحد بستگی دارد؛ توصیه میکنیم آن را بهگونهای ذخیره کنید که نتوان آن را از دستگاه کپی کرد، برای مثال بااستفاده از TPM، Secure Enclaves، یا سایر محلهای ذخیره کلید با پشتیبانی سختافزار. برای استفاده از 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 از خط فرمان را نشان میدهد:
- تولید جفت کلید EC P-256:
openssl ecparam -name prime256v1 -genkey -noout -out dpop_private.pem openssl ec -in dpop_private.pem -pubout -out dpop_public.pem
- ایجاد سرصفحه 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" } } - ساختن محتوای DPoP:
بار داده باید شامل
jti(شناسه یکتا برای درخواست)،htm(روش HTTP، مثلاًPOST)،htu(HTTP URI، مثلاً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".
- برای تبادل کد مجوز،
- امضای مدرک:
سرصفحه و بار داده کدگذاریشده را با نقطه (
.) بههم متصل کنید، سپس نتیجه را با کلید خصوصیتان بااستفاده از ES256 امضا کنید. توجه داشته باشید که JWS نیاز دارد امضا در قالبR | Sبههمپیوسته خام (۶۴ بایت برای P-256) باشد. اگر مستقیماً از OpenSSL استفاده میکنید، باید امضای پیشفرض با کدبندی ASN.1 DER را به این قالب خام تبدیل کنید.
تبادل موفق با پاسخ 200 OK
حاوی نشانها مشخص میشود. اگر درطول تبادل از مدرک DPoP معتبری استفاده شود،
رمز بازآوری که Google برمیگرداند به کلید شما محدود خواهد شد، اما
رمزهای دسترسی محدود نخواهند شد. کدهای دسترسی بهجای DPoP، token_type مربوط به Bearer را حفظ خواهند کرد.
علاوهبراین، Google سرصفحه HTTP DPoP-Nonce را در پاسخ برمیگرداند.
کارخواه شما باید این عدد یکبارمصرف را ذخیره کند و آن را در ادعای nonce اثبات DPoP
در درخواستهای بعدی (مانند هنگام تبادل یک کد بازآوری برای یک کد دسترسی جدید، یا هنگام
فراخوانی میاناهای برنامهسازی کاربردی محافظتشده با DPoP) قرار دهد. بااستفاده از این تکعنصر صادرشده زودرس، میتوانید از خطای رفتوبرگشت اضافی (use_dpop_nonce) در درخواست بعدیتان جلوگیری کنید.
برای درخواستهای مبادله کد که با کد بازآوری محدود به DPoP انجام میشوند، باید مدرک DPoP ارائه شود.
اگر سرایند DPoP در زمان موردانتظار وجود نداشته باشد، نامعتبر باشد، یا اگر مدرک از کلیدی متفاوت با کلید محدودشده به کد استفاده کند، تبادل ناموفق رخ میدهد. در این موارد، سرور خطای
400 Bad Request را برمیگرداند.
اگر مدرک DPoP ادعاهای htm یا htu ناهماهنگ، iat منقضی، jti مجدداً استفادهشده، یا امضای نامعتبر داشته باشد، Google کد خطای invalid_dpop_proof برمیگرداند.
اگر یک «تکمنظوره DPoP» لازم باشد، مثلاً درطول تبادل کد نوسازی، و مدرک DPoP فاقد
ادعای nonce باشد، یا مقدار تکمنظوره برای سرور غیرقابلقبول باشد (مثلاً
منقضی شده باشد، قبلاً استفاده شده باشد، یا نادرست باشد)، Google کد خطای use_dpop_nonce
را همراه با DPoP-Nonce سرایند HTTP حاوی تکمنظوره جدیدی که میتوانید
در درخواست بعدی استفاده کنید برمیگرداند.
خطاهای دیگر ممکن است 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/youtube.force-ssl 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/youtube.force-ssl')) { // 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/youtube.force-ssl https://www.googleapis.com/auth/calendar.readonly", "refresh_token": "1//xEoDL4iW3cxlI7yDbSRFYNG01kVKM2C-259HOF2aQbI" }
فراخوانی میاناهای برنامهسازی کاربردی Google
PHP
با تکمیل مراحل زیر، از کد دسترسی برای فراخوانی Google APIs استفاده کنید:
- اگر نیاز دارید یک کد دسترسی را به یک شیء جدید
Google\Clientاعمال کنید — برای مثال، اگر کد دسترسی را در یک جلسه کاربر ذخیره کردهاید — از روشsetAccessTokenاستفاده کنید:$client->setAccessToken($access_token); - یک شیء سرویس برای API که میخواهید فراخوانی کنید بسازید. با ارائه شیء
Google\Clientمجاز به سازنده برای API که میخواهید فراخوانی کنید، شیء سرویس میسازید. برای مثال، برای فراخوانی YouTube Data API:$youtube = new Google_Service_YouTube($client); - بااستفاده از
میانای ارائهشده توسط شیء سرویس، درخواستهایی به سرویس میانای برنامهسازی کاربردی ارسال کنید.
برای مثال، برای استفاده از YouTube Data API برای بازیابی فهرست پخشهای زنده برای کانال کاربر اصیلسازیشده:
$broadcasts = $youtube->liveBroadcasts->listLiveBroadcasts('id,snippet', [ 'mine' => true ]);
Python
پساز دریافت کد دسترسی، برنامهتان میتواند از آن کد برای صدور مجوز درخواستهای API ازطرف حساب کاربری یا حساب سرویس مشخصی استفاده کند. از اطلاعات اعتباری مجوز مختص کاربر برای ساختن شیء سرویس برای API که میخواهید فراخوانی کنید استفاده کنید، و سپس از آن شیء برای ایجاد درخواستهای API مجاز استفاده کنید.
- یک شیء سرویس برای API که میخواهید فراخوانی کنید بسازید. با فراخوانی روش
buildکتابخانهgoogleapiclient.discoveryبا نام و نسخه API و اطلاعات اعتباری کاربر، یک شیء سرویس میسازید: برای مثال، برای فراخوانی نسخه ۳ از YouTube Data API:from googleapiclient.discovery import build youtube = build('youtube', 'v3', credentials=credentials)
- بااستفاده از
میانای ارائهشده توسط شیء سرویس، برای سرویس API درخواست کنید.
برای مثال، برای استفاده از YouTube Data API جهت بازیابی فهرست پخشهای مستقیم برای کانال کاربر اصالتسنجیشده:
broadcasts = youtube.liveBroadcasts().list(part='id,snippet', mine=True).execute()
Ruby
پساز دریافت کد دسترسی، برنامه شما میتواند از آن کد برای درخواستهای API ازطرف حساب کاربری یا حساب سرویس معین استفاده کند. از اطلاعات اعتباری مجوز مختص کاربر برای ساختن شیء سرویس برای API که میخواهید فراخوانی کنید استفاده کنید، و سپس از آن شیء برای ایجاد درخواستهای API مجاز استفاده کنید.
- یک شیء سرویس برای API که میخواهید فراخوانی کنید بسازید.
برای مثال، برای فراخوانی نسخه ۳ از YouTube Data API:
youtube = Google::Apis::YoutubeV3::YouTubeService.new
- اطلاعات کاربری را در سرویس تنظیم کنید:
youtube.authorization = credentials
- بااستفاده از میانای ارائهشده توسط شیء سرویس، درخواستهایی به سرویس API ارسال کنید.
برای مثال، برای استفاده از YouTube Data API برای بازیابی فهرست پخشهای زنده برای کانال کاربر اصیلسازیشده:
broadcasts = youtube.list_liveBroadcasts('id,snippet', mine: true)
یا اینکه مجوز میتواند بهصورت روشبهروش با ارائه پارامتر options به روش ارائه شود:
broadcasts = youtube.list_liveBroadcasts('id,snippet', mine: true)
Node.js
پساز دریافت کد دسترسی و تنظیم آن روی شیء OAuth2، از شیء
برای فراخوانی Google APIs استفاده کنید. برنامه شما میتواند از آن توکن برای صدور مجوز درخواستهای 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 API ازطرف حساب کاربری مشخصی استفاده کنید، بهشرطی که گستره(های) دسترسی موردنیاز API اعطا شده باشد. برای انجام این کار،
کد دسترسی را با گنجاندن پارامتر پُرسمان access_token یا مقدار سرصفحه HTTP Authorization در درخواست به میانای برنامهسازی کاربردی بگنجانید.Bearer درصورت امکان،
سرصفحه HTTP ترجیح داده میشود، زیرا رشتههای پُرسمان معمولاً در گزارشهای سرور قابلمشاهده هستند. در اکثر موارد میتوانید از کتابخانه کارخواه برای راهاندازی فراخوانیهایتان به میاناهای برنامهسازی کاربردی Google استفاده کنید (برای مثال، هنگام فراخوانی میانای برنامهسازی کاربردی جاریسازی زنده YouTube).
توجه داشته باشید که YouTube Live Streaming API از جریان حساب سرویس پشتیبانی نمیکند. ازآنجاییکه راهی برای پیوند دادن «حساب سرویس» به حساب YouTube وجود ندارد، تلاش برای صدور مجوز درخواستها با این جریان، خطای NoLinkedYouTubeAccount را ایجاد میکند.
میتوانید همه میاناهای برنامهسازی کاربردی Google را امتحان کنید و دامنههای آنها را در OAuth 2.0 Playground مشاهده کنید.
نمونههای HTTP GET
تماس با
liveBroadcasts.list
نقطه پایانی (API جاریسازی زنده YouTube) بااستفاده از سرصفحه Authorization: Bearer HTTP
ممکن است به این شکل باشد. توجه داشته باشید که باید کد دسترسی خودتان را مشخص کنید:
GET /youtube/v3/liveBroadcasts?part=id%2Csnippet&mine=true HTTP/1.1 Host: www.googleapis.com Authorization: Bearer access_token
در اینجا فراخوانی برای همان میانای برنامهسازی کاربردی برای کاربر اصالتسنجیشده بااستفاده از پارامتر رشته پُرسمان access_token ارائه شده است:
GET https://www.googleapis.com/youtube/v3/liveBroadcasts?access_token=access_token&part=id%2Csnippet&mine=true
curl مثال
میتوانید این فرمانها را با برنامه خط فرمان curl آزمایش کنید. در اینجا مثالی از
گزینه سرصفحه HTTP (ترجیحی) آورده شده است:
curl -H "Authorization: Bearer access_token" https://www.googleapis.com/youtube/v3/liveBroadcasts?part=id%2Csnippet&mine=true
یا، بهطور جایگزین، گزینه پارامتر رشته پُرسمان:
curl https://www.googleapis.com/youtube/v3/liveBroadcasts?access_token=access_token&part=id%2Csnippet&mine=true
نمونه کامل
نمونه زیر یک شیء با قالب JSON را چاپ میکند که پخشهای زنده را برای کانال YouTube کاربر اصالتسنجیشده نشان میدهد، پساز اینکه کاربر به برنامه اجازه میدهد آن دادهها را بازیابی کند.
PHP
برای اجرای این مثال:
- در «کنسول API»، نشانی وب ماشین محلی را به
فهرست نشانیهای وب هدایت مجدد اضافه کنید. برای مثال،
http://localhost:8080را اضافه کنید. - فهرست راهنمای جدیدی ایجاد کنید و به آن بروید. برای مثال:
mkdir ~/php-oauth2-example cd ~/php-oauth2-example
- کتابخانه Google API Client
برای PHP را بااستفاده از Composer نصب کنید:
composer require google/apiclient:^2.15.0
- فایلهای
index.phpوoauth2callback.phpرا با محتوای زیر ایجاد کنید. - نمونه را با سرور وب آزمایشی توکار PHP اجرا کنید:
php -S localhost:8080 ~/php-oauth2-example
index.php
<?php require_once __DIR__.'/vendor/autoload.php'; session_start(); $client = new Google\Client(); $client->setAuthConfig('client_secret.json'); // User granted permission as an access token is in the session. if (isset($_SESSION['access_token']) && $_SESSION['access_token']) { $client->setAccessToken($_SESSION['access_token']); // Check if user granted Drive permission if ($_SESSION['granted_scopes_dict']['Drive']) { echo "Drive feature is enabled."; echo "</br>"; $drive = new Drive($client); $files = array(); $response = $drive->files->listFiles(array()); foreach ($response->files as $file) { echo "File: " . $file->name . " (" . $file->id . ")"; echo "</br>"; } } else { echo "Drive feature is NOT enabled."; echo "</br>"; } // Check if user granted Calendar permission if ($_SESSION['granted_scopes_dict']['Calendar']) { echo "Calendar feature is enabled."; echo "</br>"; } else { echo "Calendar feature is NOT enabled."; echo "</br>"; } } else { // Redirect users to outh2call.php which redirects users to Google OAuth 2.0 $redirect_uri = 'http://' . $_SERVER['HTTP_HOST'] . '/oauth2callback.php'; header('Location: ' . filter_var($redirect_uri, FILTER_SANITIZE_URL)); } ?>
oauth2callback.php
<?php require_once __DIR__.'/vendor/autoload.php'; session_start(); $client = new Google\Client(); // Required, call the setAuthConfig function to load authorization credentials from // client_secret.json file. $client->setAuthConfigFile('client_secret.json'); $client->setRedirectUri('http://' . $_SERVER['HTTP_HOST']. $_SERVER['PHP_SELF']); // Required, to set the scope value, call the addScope function. $client->addScope(Google_Service_YouTube::YOUTUBE_FORCE_SSL); // 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 را اجرا کند، درصورتیکه کاربران اجازه را اعطا کرده باشند. درصورت لزوم، جریان صدور مجوز را شروع میکند. اگر موفقیتآمیز باشد، صفحه پاسخ میانای برنامهسازی کاربردی را نمایش میدهد.
- صفحه ساختگی برای فراخوانی Calendar API: این پیوند به صفحه ساختگیای اشاره میکند که تلاش میکند درخواست نمونه Calendar API را درصورت اعطای اجازه ازسوی کاربران اجرا کند. درصورت لزوم، جریان صدور مجوز را شروع میکند. اگر موفقیتآمیز باشد، صفحه پاسخ میانای برنامهسازی کاربردی را نمایش میدهد.
- جریان اصالتسنجی را مستقیماً آزمایش کنید: این پیوند به صفحهای اشاره میکند که تلاش میکند کاربر را ازطریق جریان صدور مجوز ارسال کند. برنامه برای ارسال درخواستهای مجاز «میانای برنامهسازی کاربردی» ازطرف کاربر اجازه میخواهد.
- لغو اعتبارنامههای فعلی: این پیوند به صفحهای اشاره میکند که اجازههایی را که کاربر قبلاً به برنامه اعطا کرده است لغو میکند.
- پاک کردن اطلاعات اعتباری جلسه Flask: این پیوند اطلاعات اعتباری مجوز را که در جلسه Flask ذخیره شده است پاک میکند. این کار به شما امکان میدهد ببینید اگر کاربری که قبلاً به برنامهتان اجازه داده است بخواهد درخواست میانای برنامهسازی کاربردی را در جلسه جدیدی اجرا کند چه اتفاقی میافتد. همچنین به شما امکان میدهد پاسخ میانای برنامهسازی کاربردی را که برنامهتان درصورت لغو اجازههای اعطاشده به برنامهتان توسط کاربر دریافت میکند ببینید، و برنامهتان همچنان تلاش میکند درخواستی را با کد دسترسی لغوشده مجاز کند.
# -*- 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/youtube.force-ssl', 'https://www.googleapis.com/auth/calendar.readonly'] API_SERVICE_NAME = 'youtube' API_VERSION = 'v3' app = flask.Flask(__name__) # Note: A secret key is included in the sample so that it works. # If you use this code in your application, replace this with a truly secret # key. See https://flask.palletsprojects.com/quickstart/#sessions. app.secret_key = 'REPLACE ME - this value is here as a placeholder.' @app.route('/') def index(): return print_index_table() @app.route('/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) broadcasts = youtube.liveBroadcasts().list(part='id,snippet', mine=True).execute() # Save credentials back to session in case access token was refreshed. flask.session['credentials'] = credentials_to_dict(credentials) return flask.jsonify(**broadcasts) 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/youtube.force-ssl' 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_v3' require 'google/apis/calendar_v3' require 'sinatra' configure do enable :sessions # Required, call the from_file method to retrieve the client ID from a # client_secret.json file. set :client_id, Google::Auth::ClientId.from_file('/path/to/client_secret.json') # Required, scope value # Access scopes for two non-Sign-In scopes: Read-only Drive activity and Google Calendar. scope = ['Google::Apis::DriveV3::AUTH_DRIVE_METADATA_READONLY', 'Google::Apis::CalendarV3::AUTH_CALENDAR_READONLY'] # Required, Authorizers require a storage instance to manage long term persistence of # access and refresh tokens. set :token_store, Google::Auth::Stores::RedisTokenStore.new(redis: Redis.new) # Required, indicate where the API server will redirect the user after the user completes # the authorization flow. The redirect URI is required. The value must exactly # match one of the authorized redirect URIs for the OAuth 2.0 client, which you # configured in the API Console. If this value doesn't match an authorized URI, # you will get a 'redirect_uri_mismatch' error. set :callback_uri, '/oauth2callback' # To use OAuth2 authentication, we need access to a CLIENT_ID, CLIENT_SECRET, AND REDIRECT_URI # from the client_secret.json file. To get these credentials for your application, visit # https://console.cloud.google.com/apis/credentials. set :authorizer, Google::Auth::WebUserAuthorizer.new(settings.client_id, settings.scope, settings.token_store, callback_uri: settings.callback_uri) end get '/' do # NOTE: Assumes the user is already authenticated to the app user_id = request.session['user_id'] # Fetch stored credentials for the user from the given request session. # nil if none present credentials = settings.authorizer.get_credentials(user_id, request) if credentials.nil? # Generate a url that asks the user to authorize requested scope(s). # Then, redirect user to the url. redirect settings.authorizer.get_authorization_url(request: request) end # User authorized the request. Now, check which scopes were granted. if credentials.scope.include?(Google::Apis::DriveV3::AUTH_DRIVE_METADATA_READONLY) # User authorized read-only Drive activity permission. # Example of using Google Drive API to list filenames in user's Drive. youtube = Google::Apis::YoutubeV3::YouTubeService.new broadcasts = youtube.list_liveBroadcasts('id,snippet', mine: true) "<pre>#{JSON.pretty_generate(broadcasts.to_h)}</pre>" else # User didn't authorize read-only Drive activity permission. # Update UX and application accordingly end # Check if user authorized Calendar read permission. if credentials.scope.include?(Google::Apis::CalendarV3::AUTH_CALENDAR_READONLY) # User authorized Calendar read permission. # Calling the APIs, etc. else # User didn't authorize Calendar read permission. # Update UX and application accordingly end end # Receive the callback from Google's OAuth 2.0 server. get '/oauth2callback' do # Handle the result of the oauth callback. Defers the exchange of the code by # temporarily stashing the results in the user's session. target_url = Google::Auth::WebUserAuthorizer.handle_auth_callback_deferred(request) redirect target_url end
Node.js
برای اجرای این نمونه:
-
در «کنسول API»، نشانی وب دستگاه محلی را به فهرست نشانیهای وب تغییرمسیر اضافه کنید. برای مثال،
http://localhostرا اضافه کنید. - مطمئن شوید که LTS نگهداری، LTS فعال، یا نسخه پخش فعلی Node.js را نصب کرده باشید.
-
فهرست راهنمای جدیدی ایجاد کنید و به آن بروید. برای مثال:
mkdir ~/nodejs-oauth2-example cd ~/nodejs-oauth2-example
-
کتابخانه کارخواه Google API را برای Node.js بااستفاده از npm نصب کنید:
npm install googleapis
-
فایلهای
main.jsرا با محتوای زیر بسازید. -
نمونه را اجرا کنید:
node .\main.js
main.js
const http = require('http'); const https = require('https'); const url = require('url'); const { google } = require('googleapis'); const crypto = require('crypto'); const express = require('express'); const session = require('express-session'); /** * To use OAuth2 authentication, we need access to a CLIENT_ID, CLIENT_SECRET, AND REDIRECT_URI. * To get these credentials for your application, visit * https://console.cloud.google.com/apis/credentials. */ const oauth2Client = new google.auth.OAuth2( YOUR_CLIENT_ID, YOUR_CLIENT_SECRET, YOUR_REDIRECT_URL ); // Access scopes for two non-Sign-In scopes: Read-only Drive activity and Google Calendar. const scopes = [ 'https://www.googleapis.com/auth/youtube.force-ssl', '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/youtube.force-ssl')) { // 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/youtube.force-ssl 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://youtube.googleapis.com/youtube/v3/liveBroadcasts' 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 اعمال میکند تا به توسعهدهندگان کمک کند برنامههایشان را ایمن نگه دارند. نشانیهای وب هدایتکننده شما باید از این قوانین پیروی کنند. برای تعریف دامنه، میزبان، مسیر، پُرسمان، طرح، و اطلاعات کاربر که در این قوانین استفاده میشود، به بخش ۳ «RFC 3986» مراجعه کنید.
| قوانین اعتبارسنجی | |
|---|---|
| طرح |
URIهای تغییرمسیر باید از طرح HTTPS استفاده کنند، نه HTTP ساده. «نشانیهای وب محلی» (ازجمله نشانیهای وب نشانی IP محلی) از این قانون مستثنا هستند. |
| میزبان |
میزبانها نمیتوانند نشانیهای IP خام باشند. نشانیهای IP میزبان محلی از این قانون مستثنا هستند. |
| دامنه |
“googleusercontent.com” باشد.goo.gl) باشد، مگر اینکه
برنامه مالک دامنه باشد. علاوهبراین، اگر برنامهای که مالک دامنه کوتاه کننده است تصمیم بگیرد به آن دامنه هدایت کند، آن نشانی وب هدایت باید یا حاوی “/google-callback/” در مسیر خود باشد یا با “/google-callback” پایان یابد. |
| Userinfo |
شناسه منبع یکسان تغییرمسیر نمیتواند حاوی زیرمؤلفه userinfo باشد. |
| مسیر |
شناسه منبع یکسان (URI) تغییرمسیر نمیتواند حاوی پیمایش مسیر (که به آن بازگشت دایرکتوری نیز میگویند) باشد،
که با |
| پُرسمان |
نشانیهای وب هدایت نباید حاوی هدایتهای باز باشند. |
| تکه |
شناسههای منبع یکسان تغییرمسیر نمیتوانند حاوی مؤلفه قطعه باشند. |
| شخصیتها |
نشانیهای وب هدایت نمیتوانند حاوی نویسههای خاصی باشند، ازجمله:
|
مجوزدهی افزایشی
در پروتکل OAuth 2.0، برنامه شما برای دسترسی به منابعی که با گسترهها شناسایی میشوند، درخواست مجوز میکند. بهترین روش تجربه کاربری این است که درخواست مجوز برای منابع را در زمانی که به آنها نیاز دارید انجام دهید. برای فعال کردن این روش، سرور مجوز Google از مجوز افزایشی پشتیبانی میکند. این ویژگی به شما امکان میدهد تا دامنهها را درصورت نیاز درخواست کنید و، اگر کاربر اجازه را برای دامنه جدید اعطا کند، یک کد مجوز برمیگرداند که ممکن است با یک کد حاوی همه دامنههایی که کاربر به پروژه اعطا کرده است مبادله شود.
برای مثال، فرض کنید برنامهای دادههای کانال YouTube کاربر اصالتسنجیشده را بازیابی میکند و همچنین
به کاربر امکان میدهد دادههای YouTube Analytics را ازطریق جریان خاصی بازیابی کند. در این حالت، هنگام ورود به سیستم، برنامه ممکن است فقط برای گستره https://www.googleapis.com/auth/youtube.force-ssl درخواست دسترسی کند. اما اگر کاربر بخواهد به دادههای Analytics برای کانال خود دسترسی پیدا کند، برنامه میتواند
درخواست دسترسی به دامنه https://www.googleapis.com/auth/yt-analytics.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 کاربر را دارد، علاوهبر هر دسترسی دیگری که کاربر قبلاً به برنامه اعطا کرده است.
GET https://accounts.google.com/o/oauth2/v2/auth?
scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fyoutube.force-ssl&
access_type=offline&
state=security_token%3D138rk%3Btarget_url%3Dhttp...index&
redirect_uri=http%3A%2F%2Flocalhost%2Foauth2callback&
response_type=code&
client_id=client_id&
include_granted_scopes=true
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_typeHTTP query parameter toofflinewhen redirecting the user to Google's OAuth 2.0 server. In that case, Google's authorization server returns a refresh token when you exchange an authorization code for an access token. Then, if the access token expires (or at any other time), you can use a refresh token to obtain a new access token.
Requesting offline access is a requirement for any application that needs to access a Google
API when the user is not present. For example, an app that performs backup services or
executes actions at predetermined times needs to be able to refresh its access token when the
user is not present. The default style of access is called online.
Server-side web applications, installed applications, and devices all obtain refresh tokens during the authorization process. Refresh tokens are not typically used in client-side (JavaScript) web applications.
PHP
If your application needs offline access to a Google API, set the API client's access type to
offline:
$client->setAccessType("offline");
پساز اینکه کاربر دسترسی آفلاین به دامنههای درخواستی را اعطا کرد، میتوانید همچنان از کارخواه میانای برنامهسازی کاربردی برای دسترسی به میاناهای برنامهسازی کاربردی Google ازطرف کاربر در زمانی که کاربر آفلاین است استفاده کنید. شیء کارخواه درصورت نیاز کد دسترسی را بازآوری خواهد کرد.
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
برای اطلاعات بیشتر درباره نحوه پیادهسازی «محافظت بینحسابی» و فهرست کامل رویدادهای دردسترس، به صفحه «محافظت از حسابهای کاربر با «محافظت بینحسابی»» مراجعه کنید.