שימוש ב-OAuth 2.0 לאפליקציות של שרת אינטרנט

במאמר הזה מוסבר איך אפליקציות של שרתי אינטרנט משתמשות בספריות לקוח של Google API או בנקודות קצה של Google OAuth 2.0 כדי להטמיע הרשאה של OAuth 2.0 לגישה ל-Google APIs.

פרוטוקול OAuth 2.0 מאפשר למשתמשים לשתף נתונים ספציפיים עם אפליקציה, תוך שמירה על הפרטיות של שמות המשתמשים, הסיסמאות ומידע אחר. לדוגמה, אפליקציה יכולה להשתמש ב-OAuth 2.0 כדי לקבל הרשאה ממשתמשים לאחסן קבצים ב-Google Drive שלהם.

תהליך OAuth 2.0 הזה מיועד במיוחד להרשאת משתמשים. הוא מיועד לאפליקציות שיכולות לאחסן מידע סודי ולשמור על מצב. אפליקציית שרת אינטרנט עם הרשאה מתאימה יכולה לגשת ל-API בזמן שהמשתמש מקיים אינטראקציה עם האפליקציה או אחרי שהמשתמש יצא מהאפליקציה.

אפליקציות של שרתי אינטרנט משתמשות לעיתים קרובות גם ב חשבונות שירות כדי לאשר בקשות ל-API, במיוחד כשקוראים ל-Cloud APIs כדי לגשת לנתונים שמבוססים על פרויקט ולא לנתונים ספציפיים למשתמש. אפליקציות של שרתי אינטרנט יכולות להשתמש בחשבונות שירות בשילוב עם הרשאות משתמש.

ספריות לקוח

בדוגמאות הספציפיות לשפה שמופיעות בדף הזה נעשה שימוש ב-Google API Client Libraries כדי להטמיע הרשאה של OAuth 2.0. כדי להריץ את דוגמאות הקוד, צריך קודם להתקין את ספריית הלקוח בשפה הרלוונטית.

כשמשתמשים בספריית לקוח של Google API כדי לטפל בתהליך OAuth 2.0 של האפליקציה, ספריית הלקוח מבצעת פעולות רבות שהאפליקציה הייתה צריכה לבצע בעצמה. לדוגמה, הוא קובע מתי האפליקציה יכולה להשתמש באסימוני גישה מאוחסנים או לרענן אותם, וגם מתי האפליקציה צריכה לקבל שוב את הסכמת המשתמש. ספריית הלקוח גם יוצרת כתובות URL נכונות להפניה אוטומטית ועוזרת להטמיע מטפלים בהפניה אוטומטית שממירים קודי הרשאה לטוקנים של גישה.

ספריות לקוח של Google API לאפליקציות בצד השרת זמינות בשפות הבאות:

דרישות מוקדמות

הפעלת ממשקי API בפרויקט

בכל אפליקציה ששולחת קריאות ל-Google APIs צריך להפעיל את ממשקי ה-API האלה ב- API Console.

כדי להפעיל API בפרויקט:

  1. Open the API Library ב Google API Console.
  2. If prompted, select a project, or create a new one.
  3. ב- API Library מוצגת רשימה של כל ממשקי ה-API הזמינים, מקובצים לפי משפחת מוצרים ופופולריות. אם ה-API שרוצים להפעיל לא מופיע ברשימה, אפשר להשתמש בחיפוש כדי למצוא אותו, או ללחוץ על הצגת הכול במשפחת המוצרים שאליה הוא שייך.
  4. בוחרים את ה-API שרוצים להפעיל ולוחצים על הלחצן הפעלה.
  5. If prompted, enable billing.
  6. If prompted, read and accept the API's Terms of Service.

יצירת פרטי כניסה להרשאה

לכל אפליקציה שמשתמשת ב-OAuth 2.0 כדי לגשת ל-Google APIs צריכים להיות פרטי הרשאה שמזהים את האפליקציה בשרת OAuth 2.0 של Google. בשלבים הבאים מוסבר איך ליצור פרטי כניסה לפרויקט. לאחר מכן, האפליקציות יכולות להשתמש בפרטי הכניסה כדי לגשת לממשקי API שהפעלתם בפרויקט הזה.

  1. Go to the Credentials page.
  2. לוחצים על Create Client (יצירת לקוח).
  3. בוחרים את סוג האפליקציה Web application.
  4. ממלאים את הטופס ולוחצים על יצירה. באפליקציות שמשתמשות בשפות ובמסגרות כמו PHP, ‏ Java, ‏ Python, ‏ Ruby ו-NET, צריך לציין מזהי URI של הפניות אוטומטיות מורשים. כתובות ה-URI להפניה אוטומטית הן נקודות הקצה שאליהן שרת OAuth 2.0 יכול לשלוח תגובות. נקודות הקצה האלה צריכות לעמוד בכללי האימות של Google.

    לצורך בדיקה, אפשר לציין כתובות URI שמפנות למכונה המקומית, כמו http://localhost:8080. לכן, חשוב לדעת שכל הדוגמאות במסמך הזה משתמשות ב-http://localhost:8080 כ-URI להפניה.

    מומלץ לתכנן את נקודות הקצה של האימות באפליקציה כך שהאפליקציה לא תחשוף קודי הרשאה למקורות אחרים בדף.

אחרי שיוצרים את פרטי הכניסה, מורידים את הקובץ client_secret.json מ- API Console. מאחסנים את הקובץ באופן מאובטח במיקום שרק האפליקציה שלכם יכולה לגשת אליו.

זיהוי היקפי גישה

היקפי הרשאות מאפשרים לאפליקציה לבקש גישה רק למשאבים שהיא צריכה, וגם מאפשרים למשתמשים לשלוט בהיקף הגישה שהם מעניקים לאפליקציה. לכן, יכול להיות שיהיה קשר הפוך בין מספר ההיקפים המבוקשים לבין הסבירות לקבלת הסכמת המשתמש.

לפני שמתחילים להטמיע הרשאה מסוג OAuth 2.0, מומלץ לזהות את היקפי ההרשאות שהאפליקציה תזדקק להם כדי לגשת למשאבים.

מומלץ גם שהאפליקציה תבקש גישה להיקפי הרשאות באמצעות תהליך של הרשאה מצטברת, שבו האפליקציה מבקשת גישה לנתוני המשתמש בהקשר. השיטה המומלצת הזו עוזרת למשתמשים להבין בקלות למה האפליקציה שלכם צריכה את הגישה שהיא מבקשת.

במסמך היקפי OAuth 2.0 API מופיעה רשימה מלאה של היקפי הרשאות שאפשר להשתמש בהם כדי לגשת אל Google APIs.

דרישות ספציפיות לשפה

כדי להריץ את אחת מדוגמאות הקוד במסמך הזה, צריך חשבון Google, גישה לאינטרנט ודפדפן אינטרנט. אם אתם משתמשים באחת מספריות הלקוח של API, כדאי לעיין גם בדרישות הספציפיות לשפה שבהמשך.

PHP

כדי להריץ את דוגמאות הקוד של PHP שמופיעות במאמר הזה, תצטרכו:

  • ‫PHP 8.0 ואילך עם ממשק שורת הפקודה (CLI) ותוסף JSON מותקנים.
  • כלי לניהול תלות Composer.
  • ספריית הלקוח של Google APIs ל-PHP:

    composer require google/apiclient:^2.15.0

מידע נוסף זמין במאמר ספריית הלקוח של Google APIs ל-PHP.

Python

כדי להריץ את דוגמאות הקוד של Python במאמר הזה, תצטרכו:

  • ‫Python 3.7 ואילך
  • כלי לניהול חבילות pip.
  • הגרסה 2.0 של ספריית הלקוח של 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 web application framework.
    pip install --upgrade flask
  • ספריית ה-HTTP‏ requests.
    pip install --upgrade requests

אם אתם לא מצליחים לשדרג את Python ואת מדריך ההעברה המשויך, כדאי לעיין בהערות על הגרסה של ספריית הלקוח של Google API ל-Python.

Ruby

כדי להריץ את דוגמאות הקוד של Ruby במאמר הזה, תצטרכו:

  • ‫Ruby 2.6 ואילך
  • ספריית Google Auth ל-Ruby:

    gem install googleauth
  • ספריות הלקוח של Google APIs ל-Drive וליומן:

    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 כדי לקבל את הסכמת המשתמש לביצוע בקשת API בשמו. האפליקציה צריכה לקבל את ההסכמה הזו לפני שהיא יכולה לבצע בקשת Google API שמחייבת הרשאת משתמש.

הנה סיכום מהיר של השלבים:

  1. האפליקציה מזהה את ההרשאות שהיא צריכה.
  2. האפליקציה מפנה את המשתמש ל-Google יחד עם רשימת ההרשאות המבוקשות.
  3. המשתמש מחליט אם להעניק את ההרשאות לאפליקציה שלכם.
  4. האפליקציה שלכם תדע מה המשתמש החליט.
  5. אם המשתמש העניק את ההרשאות המבוקשות, האפליקציה מאחזרת את האסימונים שנדרשים כדי לשלוח בקשות API בשם המשתמש.

שלב 1: הגדרת פרמטרים של הרשאה

השלב הראשון הוא ליצור את בקשת ההרשאה. הבקשה הזו מגדירה פרמטרים שמזהים את האפליקציה שלכם ומגדירים את ההרשאות שהמשתמש יתבקש להעניק לאפליקציה.

  • אם משתמשים בספריית לקוח של Google לאימות ולמתן הרשאות באמצעות OAuth 2.0, צריך ליצור ולהגדיר אובייקט שמגדיר את הפרמטרים האלה.
  • אם קוראים ישירות לנקודת הקצה של Google OAuth 2.0, המערכת יוצרת כתובת URL ומגדירה את הפרמטרים בכתובת ה-URL הזו.

בכרטיסיות שבהמשך מפורטים פרמטרי ההרשאה הנתמכים לאפליקציות של שרתי אינטרנט. בדוגמאות הספציפיות לשפה מוצג גם אופן השימוש בספריית לקוח או בספריית הרשאות כדי להגדיר אובייקט שמגדיר את הפרמטרים האלה.

PHP

קטע הקוד הבא יוצר אובייקט Google\Client() שמגדיר את הפרמטרים בבקשת ההרשאה.

האובייקט הזה משתמש במידע מקובץ client_secret.json כדי לזהות את האפליקציה שלכם. (מידע נוסף על הקובץ הזה זמין במאמר בנושא יצירת פרטי כניסה לאימות). האובייקט גם מזהה את היקפי ההרשאות שהאפליקציה מבקשת גישה אליהם ואת כתובת ה-URL של נקודת הקצה לאימות של האפליקציה, שתטפל בתגובה משרת OAuth 2.0 של Google. לבסוף, הקוד מגדיר את הפרמטרים האופציונליים access_type ו-include_granted_scopes.

לדוגמה, הקוד הזה מבקש גישה לקריאה בלבד במצב אופליין למטא נתונים של משתמש ב-Google Drive ולאירועים ביומן:

use Google\Client;

$client = new Client();

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

// Required, to set the scope value, call the addScope function
$client->addScope([Google\Service\Drive::DRIVE_METADATA_READONLY, Google\Service\Calendar::CALENDAR_READONLY]);

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

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

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

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

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

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

Python

בקטע הקוד הבא נעשה שימוש במודול google-auth-oauthlib.flow כדי ליצור את בקשת ההרשאה.

הקוד יוצר אובייקט Flow שמזהה את האפליקציה באמצעות מידע מהקובץ client_secret.json שהורדתם אחרי יצירת פרטי הרשאה. האובייקט הזה גם מזהה את היקפי ההרשאות שהאפליקציה מבקשת גישה אליהם ואת כתובת ה-URL של נקודת הקצה לאימות של האפליקציה, שתטפל בתגובה משרת OAuth 2.0 של Google. לבסוף, הקוד מגדיר את הפרמטרים האופציונליים access_type ו-include_granted_scopes.

לדוגמה, הקוד הזה מבקש גישה לקריאה בלבד במצב אופליין למטא נתונים של משתמש ב-Google Drive ולאירועים ביומן:

import google.oauth2.credentials
import google_auth_oauthlib.flow

# Required, call the from_client_secrets_file method to retrieve the client ID from a
# client_secret.json file. The client ID (from that file) and access scopes are required. (You can
# also use the from_client_config method, which passes the client configuration as it originally
# appeared in a client secrets file but doesn't access the file itself.)
flow = google_auth_oauthlib.flow.Flow.from_client_secrets_file('client_secret.json',
    scopes=['https://www.googleapis.com/auth/drive.metadata.readonly',
            'https://www.googleapis.com/auth/calendar.readonly'])

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

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

Ruby

משתמשים בקובץ client_secrets.json שיצרתם כדי להגדיר אובייקט לקוח באפליקציה. כשמגדירים אובייקט לקוח, מציינים את ההיקפים שהאפליקציה צריכה לגשת אליהם, וגם את כתובת ה-URL של נקודת הקצה לאימות של האפליקציה, שתטפל בתגובה מהשרת של OAuth 2.0.

לדוגמה, הקוד הזה מבקש גישה לקריאה בלבד ולגישה אופליין למטא נתונים של משתמש ב-Google Drive ולאירועים ביומן:

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

require 'google/apis/drive_v3'
require 'google/apis/calendar_v3'

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

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

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

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

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

האפליקציה משתמשת באובייקט הלקוח כדי לבצע פעולות OAuth 2.0, כמו יצירת כתובות URL של בקשות הרשאה והחלת אסימוני גישה על בקשות HTTP.

Node.js

קטע הקוד הבא יוצר אובייקט google.auth.OAuth2 שמגדיר את הפרמטרים בבקשת ההרשאה.

האובייקט הזה משתמש במידע מקובץ client_secret.json כדי לזהות את האפליקציה. כדי לבקש הרשאות ממשתמש לאחזור טוקן גישה, מפנים אותו לדף הסכמה. כדי ליצור כתובת URL של דף בקשת הסכמה:

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

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

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

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

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

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

הערה חשובה – הערך refresh_token מוחזר רק בהרשאה הראשונה. פרטים נוספים זמינים כאן.

HTTP/REST

נקודת הקצה של Google OAuth 2.0 היא https://accounts.google.com/o/oauth2/v2/auth. נקודת הקצה הזו נגישה רק דרך HTTPS. חיבורי HTTP רגילים נדחים.

שרת ההרשאות של Google תומך בפרמטרים הבאים של מחרוזת השאילתה לאפליקציות של שרת אינטרנט:

פרמטרים
client_id חובה

מזהה הלקוח של האפליקציה. אפשר למצוא את הערך הזה ב .

redirect_uri חובה

הפרמטר הזה קובע לאן שרת ה-API מפנה את המשתמש אחרי שהוא מסיים את תהליך ההרשאה. הערך חייב להיות זהה לאחד מכתובות ה-URI המורשות להפניה אוטומטית של לקוח OAuth 2.0, שהגדרתם ב של הלקוח. אם הערך הזה לא תואם ל-URI של הפניה אוטומטית מורשה שצוין ב-client_id, תופיע השגיאה redirect_uri_mismatch.

שימו לב שחייבת להיות התאמה בין הסכימה http או https, האותיות הקטנות והגדולות והלוכסן האחורי ('/').

response_type חובה

הפונקציה קובעת אם נקודת הקצה של Google OAuth 2.0 מחזירה קוד הרשאה.

מגדירים את ערך הפרמטר ל-code עבור אפליקציות של שרת אינטרנט.

scope חובה

רשימה של היקפי הרשאות שמופרדים ברווחים ומזהים את המשאבים שהאפליקציה יכולה לגשת אליהם בשם המשתמש. הערכים האלה משמשים את מסך ההסכמה שמוצג למשתמש על ידי Google.

היקפי הרשאות מאפשרים לאפליקציה לבקש גישה רק למשאבים שהיא צריכה, וגם מאפשרים למשתמשים לשלוט במידת הגישה שהם מעניקים לאפליקציה. לכן, יש קשר הפוך בין מספר ההיקפים המבוקשים לבין הסבירות לקבלת הסכמת המשתמש.

מומלץ לבקש גישה להיקפי הרשאה בהקשר של הבקשה, כשאפשר. כשאתם מבקשים גישה לנתוני משתמשים בהקשר המתאים, באמצעות הרשאה מצטברת, אתם עוזרים למשתמשים להבין בקלות רבה יותר למה האפליקציה שלכם צריכה את הגישה שהיא מבקשת.

access_type מומלץ

ההגדרה הזו מציינת אם האפליקציה יכולה לרענן את טוקני הגישה כשהמשתמש לא נמצא בדפדפן. הערכים החוקיים של הפרמטר הם online, שהוא ערך ברירת המחדל, ו-offline.

מגדירים את הערך ל-offline אם האפליקציה צריכה לרענן את טוקני הגישה כשהמשתמש לא נמצא בדפדפן. זוהי שיטת הרענון של אסימוני הגישה שמתוארת בהמשך המאמר. הערך הזה מורה לשרת ההרשאות של Google להחזיר אסימון רענון וגם אסימון גישה בפעם הראשונה שהאפליקציה מחליפה קוד הרשאה באסימונים.

state מומלץ

מציין ערך מחרוזת שהאפליקציה משתמשת בו כדי לשמור על מצב בין בקשת ההרשאה לבין התגובה של שרת ההרשאה. השרת מחזיר את הערך המדויק שאתם שולחים כצמד name=value ברכיב השאילתה של כתובת ה-URL‏ (?) של redirect_uri אחרי שהמשתמש מאשר או דוחה את בקשת הגישה של האפליקציה שלכם.

אפשר להשתמש בפרמטר הזה למגוון מטרות, כמו הפניית המשתמש למשאב הנכון באפליקציה, שליחת ערכי nonce וצמצום הסיכון לזיוף בקשות חוצות אתרים. מכיוון שאפשר לנחש את redirect_uri, שימוש בערך state יכול להגדיל את הביטחון שלכם בכך שחיבור נכנס הוא תוצאה של בקשת אימות. אם יוצרים מחרוזת אקראית או מקודדים את הגיבוב של קובץ Cookie או ערך אחר שמתעד את מצב הלקוח, אפשר לאמת את התגובה כדי לוודא שהבקשה והתגובה הגיעו מאותו דפדפן, וכך להגן מפני מתקפות כמו זיוף בקשות חוצות אתרים. בתיעוד של OpenID Connect יש דוגמה לאופן שבו יוצרים ומאשרים אסימון state.

include_granted_scopes אופציונלי

מאפשרת לאפליקציות להשתמש בהרשאה מצטברת כדי לבקש גישה להיקפי הרשאות נוספים בהקשר. אם מגדירים את הערך של הפרמטר הזה ל-true ובקשת ההרשאה מאושרת, אז אסימון הגישה החדש יכלול גם את כל ההיקפים שהמשתמש העניק לאפליקציה גישה אליהם בעבר. דוגמאות מפורטות בקטע בנושא הרשאה מצטברת.

login_hint אופציונלי

אם האפליקציה יודעת איזה משתמש מנסה לבצע אימות, היא יכולה להשתמש בפרמטר הזה כדי לספק רמז לשרת האימות של Google. השרת משתמש ברמז כדי לפשט את תהליך הכניסה, למשל על ידי מילוי מראש של שדה האימייל בטופס הכניסה או על ידי בחירת סשן הכניסה המתאים.

מגדירים את ערך הפרמטר לכתובת אימייל או למזהה sub, ששווה למזהה Google של המשתמש.

prompt אופציונלי

רשימה של הנחיות שמוצגות למשתמש, מופרדות ברווחים ורגישות לאותיות רישיות. אם לא מציינים את הפרמטר הזה, המשתמש יתבקש לתת הרשאה רק בפעם הראשונה שבה הפרויקט מבקש גישה. מידע נוסף זמין במאמר בנושא בקשת הסכמה מחדש.

הערכים האפשריים הם:

none לא להציג מסכי אימות או הסכמה. אסור לציין אותו עם ערכים אחרים.
consent שליחת בקשה למשתמש להביע הסכמה.
select_account מבקשים מהמשתמש לבחור חשבון.

שלב 2: הפניה לשרת OAuth 2.0 של Google

הפניית המשתמש לשרת OAuth 2.0 של Google כדי להתחיל את תהליך האימות וההרשאה. בדרך כלל זה קורה כשהאפליקציה צריכה לגשת לנתונים של המשתמש בפעם הראשונה. במקרה של הרשאת גישה מצטברת, השלב הזה מתרחש גם כשהאפליקציה צריכה לגשת למשאבים נוספים שאין לה עדיין הרשאה לגשת אליהם.

PHP

  1. יוצרים כתובת URL כדי לבקש גישה משרת OAuth 2.0 של Google:
    $auth_url = $client->createAuthUrl();
  2. הפניה אוטומטית של המשתמש אל $auth_url:
    header('Location: ' . filter_var($auth_url, FILTER_SANITIZE_URL));

Python

בדוגמה הזו מוצג איך להפנות את המשתמש לכתובת ה-URL של ההרשאה באמצעות מסגרת אפליקציית האינטרנט Flask:

return flask.redirect(authorization_url)

Ruby

  1. יוצרים כתובת URL כדי לבקש גישה משרת OAuth 2.0 של Google:
    auth_uri = authorizer.get_authorization_url(request: request)
  2. הפניה אוטומטית של המשתמש אל auth_uri.

Node.js

  1. משתמשים בכתובת ה-URL שנוצרה authorizationUrl משלב 1 בשיטת generateAuthUrl כדי לבקש גישה משרת OAuth 2.0 של Google.
  2. הפניה אוטומטית של המשתמש אל authorizationUrl.
    res.redirect(authorizationUrl);

HTTP/REST

דוגמה להפניה מותנית לשרת ההרשאות של Google

למטה מוצגת כתובת URL לדוגמה, עם מעברי שורה ורווחים כדי שיהיה קל לקרוא אותה.

https://accounts.google.com/o/oauth2/v2/auth?
 scope=https%3A//www.googleapis.com/auth/drive.metadata.readonly%20https%3A//www.googleapis.com/auth/calendar.readonly&
 access_type=offline&
 include_granted_scopes=true&
 response_type=code&
 state=state_parameter_passthrough_value&
 redirect_uri=https%3A//oauth2.example.com/code&
 client_id=client_id

אחרי שיוצרים את כתובת ה-URL של הבקשה, מפנים אליה את המשתמש.

שרת OAuth 2.0 של Google מאמת את המשתמש ומקבל ממנו הסכמה לאפליקציה שלכם לגשת להיקפי ההרשאות המבוקשים. התגובה נשלחת בחזרה לאפליקציה באמצעות כתובת ה-URL להפניה אוטומטית שציינתם.

שלב 3: המשתמש מקבל בקשה להסכמה מ-Google

בשלב הזה, המשתמש מחליט אם להעניק לאפליקציה שלכם את הגישה המבוקשת. בשלב הזה, Google מציגה חלון הסכמה שבו מופיעים שם האפליקציה ושירותי Google API שהאפליקציה מבקשת הרשאת גישה אליהם באמצעות פרטי ההרשאה של המשתמש, וגם סיכום של היקפי הגישה שיוענקו. לאחר מכן, המשתמש יכול להסכים להעניק גישה להיקף אחד או יותר של הרשאות שהאפליקציה מבקשת, או לדחות את הבקשה.

האפליקציה לא צריכה לעשות שום דבר בשלב הזה, כי היא ממתינה לתשובה משרת OAuth 2.0 של Google, שתציין אם ניתנה גישה כלשהי. התגובה הזו מוסברת בשלב הבא.

שגיאות

יכול להיות שבקשות לנקודת הקצה של הרשאת OAuth 2.0 של Google יציגו הודעות שגיאה שמוצגות למשתמשים, במקום תהליכי האימות וההרשאה הצפויים. בהמשך מפורטים קודי שגיאה נפוצים והצעות לפתרונות.

admin_policy_enforced

לא ניתן לאשר את חשבון Google לאחת או יותר מההרשאות המבוקשות בגלל המדיניות של האדמין ב-Google Workspace. מידע נוסף על האופן שבו אדמין יכול להגביל את הגישה לכל היקפי ההרשאות או להיקפי הרשאות רגישים ומוגבלים עד למתן גישה מפורשת למזהה לקוח OAuth זמין במאמר שליטה בגישה של אפליקציות של צד שלישי ואפליקציות פנימיות לנתונים ב-Google Workspace במרכז העזרה לאדמינים של Google Workspace.

disallowed_useragent

נקודת הקצה של ההרשאה מוצגת בתוך סוכן משתמש מוטמע שאסור לשימוש על פי מדיניות Google בנושא OAuth 2.0.

Android

מפתחי Android עשויים להיתקל בהודעת השגיאה הזו כשהם פותחים בקשות הרשאה ב-android.webkit.WebView. במקום זאת, מפתחים צריכים להשתמש בספריות של Android כמו כניסה באמצעות חשבון Google ל-Android או AppAuth ל-Android של OpenID Foundation.

מפתחי אתרים עשויים להיתקל בשגיאה הזו כשמשתמש עובר מאתר שלכם לנקודת ההרשאה של Google OAuth 2.0, ואפליקציית Android פותחת קישור כללי לאתר בסוכן משתמש מוטמע. מפתחים צריכים לאפשר פתיחה של קישורים כלליים בטיפול בקישורים שמוגדר כברירת מחדל במערכת ההפעלה, כולל טיפול בקישורים לאפליקציות ל-Android או באפליקציית הדפדפן שמוגדרת כברירת מחדל. ספריית Android Custom Tabs היא גם אפשרות נתמכת.

iOS

מפתחים של iOS ו-macOS עשויים להיתקל בשגיאה הזו כשהם פותחים בקשות הרשאה ב-WKWebView. במקום זאת, מפתחים צריכים להשתמש בספריות iOS כמו Google Sign-In for iOS או AppAuth for iOS של OpenID Foundation.

מפתחי אתרים עשויים להיתקל בשגיאה הזו כשמשתמש מנווט באתר שלכם מאפליקציית iOS או macOS שפותחת קישור כללי לאינטרנט בסוכן משתמש מוטמע, אל נקודת הקצה של Google להרשאה באמצעות OAuth 2.0. מפתחים צריכים לאפשר פתיחה של קישורים כלליים בטיפול הקישורים שמוגדר כברירת מחדל במערכת ההפעלה, כולל טיפול בקישורים אוניברסליים או באפליקציית הדפדפן שמוגדרת כברירת מחדל. ספריית SFSafariViewController היא גם אפשרות נתמכת.

org_internal

מזהה לקוח OAuth בבקשה הוא חלק מפרויקט שמגביל את הגישה לחשבונות Google ב ארגון ספציפי ב-Google Cloud. מידע נוסף על אפשרות ההגדרה הזו זמין בקטע סוג המשתמש במאמר העזרה בנושא הגדרת מסך הסכמה ל-OAuth.

invalid_client

סוד הלקוח של OAuth שגוי. כדאי לבדוק את ההגדרה של לקוח OAuth, כולל מזהה הלקוח והסוד שמשמשים לבקשה הזו.

deleted_client

לקוח ה-OAuth שמשמש לשליחת הבקשה נמחק. המחיקה יכולה להתבצע באופן ידני או אוטומטי במקרה של לקוחות שלא נעשה בהם שימוש . אפשר לשחזר לקוחות שנמחקו תוך 30 יום ממועד המחיקה. מידע נוסף

invalid_grant

כשמרעננים אסימון גישה או משתמשים בהרשאה מצטברת, יכול להיות שתוקף האסימון פג או שהוא בוטל. מאמתים שוב את המשתמש ומבקשים ממנו להביע הסכמה כדי לקבל טוקנים חדשים. אם השגיאה הזו ממשיכה להופיע, צריך לוודא שהאפליקציה הוגדרה בצורה נכונה ושהשתמשתם בטוקנים ובפרמטרים הנכונים בבקשה. אחרת, יכול להיות שחשבון המשתמש נמחק או הושבת.

redirect_uri_mismatch

הפרמטר redirect_uri שמועבר בבקשת ההרשאה לא תואם לכתובת ה-URI המורשית להפניה אוטומטית עבור מזהה הלקוח של OAuth. בודקים את כתובות ה-URI המורשות להפניה אוטומטית ב- .

הפרמטר redirect_uri עשוי להתייחס לתהליך OAuth out-of-band (OOB) שהוצא משימוש וכבר לא נתמך. כדי לעדכן את השילוב, אפשר לעיין במדריך להעברת נתונים.

invalid_request

משהו השתבש בבקשה ששלחת. יכולות להיות לכך כמה סיבות:

  • הפורמט של הבקשה לא תקין
  • בבקשה חסרים פרמטרים נדרשים
  • הבקשה משתמשת בשיטת הרשאה ש-Google לא תומכת בה. אימות ששילוב ה-OAuth משתמש בשיטת שילוב מומלצת

שלב 4: טיפול בתגובת השרת של OAuth 2.0

שרת OAuth 2.0 מגיב לבקשת הגישה של האפליקציה באמצעות כתובת ה-URL שצוינה בבקשה.

אם המשתמש מאשר את בקשת הגישה, התשובה מכילה קוד הרשאה. אם המשתמש לא מאשר את הבקשה, התשובה מכילה הודעת שגיאה. קוד ההרשאה או הודעת השגיאה שמוחזרים לשרת האינטרנט מופיעים במחרוזת השאילתה, כמו שמוצג בהמשך:

תגובת שגיאה:

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

תגובה עם קוד הרשאה:

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

דוגמה לתגובת שרת OAuth 2.0

כדי לבדוק את התהליך הזה, אפשר ללחוץ על כתובת ה-URL לדוגמה הבאה, ששולחת בקשה לגישת קריאה בלבד כדי להציג מטא נתונים של קבצים ב-Google Drive וגישת קריאה בלבד כדי להציג את האירועים ביומן Google:

https://accounts.google.com/o/oauth2/v2/auth?
 scope=https%3A//www.googleapis.com/auth/drive.metadata.readonly%20https%3A//www.googleapis.com/auth/calendar.readonly&
 access_type=offline&
 include_granted_scopes=true&
 response_type=code&
 state=state_parameter_passthrough_value&
 redirect_uri=https%3A//oauth2.example.com/code&
 client_id=client_id

אחרי השלמת תהליך ההרשאה באמצעות OAuth 2.0, אמורה להיות הפניה אוטומטית לכתובת http://localhost/oauth2callback, ובדרך כלל תופיע שגיאה 404 NOT FOUND אלא אם המחשב המקומי מציג קובץ בכתובת הזו. בשלב הבא מפורט מידע נוסף על המידע שמוחזר ב-URI כשהמשתמש מופנה חזרה לאפליקציה שלכם.

שלב 5: המרת קוד הרשאה לאסימוני רענון וגישה

אחרי ששרת האינטרנט מקבל את קוד ההרשאה, הוא יכול להחליף את קוד ההרשאה באסימון גישה.

PHP

כדי להחליף קוד הרשאה בטוקן גישה, משתמשים בשיטה fetchAccessTokenWithAuthCode:

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

Python

בדף הקריאה החוזרת, משתמשים בספרייה google-auth כדי לאמת את התגובה של שרת ההרשאות. לאחר מכן, משתמשים בשיטה flow.fetch_token כדי להחליף את קוד ההרשאה בתשובה הזו באסימון גישה:

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

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

# Store the credentials in the session.
# ACTION ITEM for developers:
#     Store user's access and refresh tokens in your data store if
#     incorporating this code into your real app.
credentials = flow.credentials
flask.session['credentials'] = {
    'token': credentials.token,
    'refresh_token': credentials.refresh_token,
    'token_uri': credentials.token_uri,
    'client_id': credentials.client_id,
    'client_secret': credentials.client_secret,
    'granted_scopes': credentials.granted_scopes}

Ruby

בדף הקריאה החוזרת, משתמשים בספרייה googleauth כדי לאמת את התגובה של שרת ההרשאות. משתמשים בשיטה authorizer.handle_auth_callback_deferred כדי לשמור את קוד ההרשאה ולחזור לכתובת ה-URL שבה נשלחה במקור בקשת ההרשאה. הפעולה הזו דוחה את החלפת הקוד על ידי אחסון התוצאות באופן זמני בסשן של המשתמש.

  target_url = Google::Auth::WebUserAuthorizer.handle_auth_callback_deferred(request)
  redirect target_url

Node.js

כדי להחליף קוד הרשאה באסימון גישה, משתמשים בשיטה getToken:

const url = require('url');

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

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

    let { tokens } = await oauth2Client.getToken(q.code);
    oauth2Client.setCredentials(tokens);
});

HTTP/REST

כדי להחליף קוד הרשאה באסימון גישה, קוראים לנקודת הקצה https://oauth2.googleapis.com/token ומגדירים את הפרמטרים הבאים:

שדות
client_id מזהה הלקוח שהתקבל מ .
client_secret סוד הלקוח שהתקבל מ- .
code קוד ההרשאה שמוחזר מהבקשה הראשונית.
grant_type כמו שמוגדר במפרט של OAuth 2.0, הערך של השדה הזה צריך להיות authorization_code.
redirect_uri אחת מכתובות ה-URI להפניה אוטומטית שמופיעות בפרויקט ב- עבור client_id הנתון.

בקטע הקוד הבא מוצגת בקשה לדוגמה:

POST /token HTTP/1.1
Host: oauth2.googleapis.com
Content-Type: application/x-www-form-urlencoded

code=4/P7q7W91a-oMsCeLvIaQm6bTrgtp7&
client_id=your_client_id&
client_secret=your_client_secret&
redirect_uri=https%3A//oauth2.example.com/code&
grant_type=authorization_code

Google מגיבה לבקשה הזו ומחזירה אובייקט JSON שמכיל אסימון גישה לטווח קצר ואסימון רענון. שימו לב שאסימון הרענון מוחזר רק אם האפליקציה שלכם הגדירה את הפרמטר access_type לערך offline בבקשה הראשונית לשרת ההרשאות של Google.

התשובה מכילה את השדות הבאים:

שדות
access_token האסימון שהאפליקציה שולחת כדי לאשר בקשת Google API.
expires_in משך החיים שנותר של אסימון הגישה בשניות.
refresh_token טוקן שאפשר להשתמש בו כדי לקבל טוקן גישה חדש. תוקף הטוקנים לרענון הוא עד שהמשתמש מבטל את הגישה או עד שתוקף הטוקן לרענון פג. שוב, השדה הזה מופיע בתגובה רק אם הגדרתם את הפרמטר access_type לערך offline בבקשה הראשונית לשרת ההרשאות של Google.
refresh_token_expires_in משך החיים שנותר לאסימון הרענון בשניות. הערך הזה מוגדר רק כשהמשתמש מעניק גישה מוגבלת בזמן.
scope היקפי הגישה שניתנים על ידי access_token מוצגים כרשימה של מחרוזות שמופרדות ברווחים, והן תלויות רישיות.
token_type סוג הטוקן שמוחזר. בשלב הזה, הערך של השדה הזה תמיד מוגדר ל-Bearer.

בקטע הקוד הבא מוצגת תגובה לדוגמה:

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

שגיאות

כשמחליפים את קוד ההרשאה באסימון גישה, יכול להיות שתיתקלו בשגיאה הבאה במקום בתגובה הצפויה. בהמשך מפורטים קודי שגיאה נפוצים והצעות לפתרונות.

invalid_grant

קוד ההרשאה שצוין לא תקין או שהפורמט שלו שגוי. כדי לבקש קוד חדש, צריך להפעיל מחדש את תהליך ה-OAuth כדי לבקש מהמשתמש שוב לאשר את ההסכמה.

שלב 6: בדיקה של היקפי ההרשאות שהמשתמשים העניקו

כשמבקשים כמה הרשאות (היקפי הרשאות), יכול להיות שהמשתמשים לא יאשרו לאפליקציה שלכם גישה לכולן. האפליקציה צריכה לאמת אילו היקפי הרשאות ניתנו בפועל, ולטפל בצורה תקינה במצבים שבהם נדחות הרשאות מסוימות. בדרך כלל, האפליקציה משביתה את התכונות שמסתמכות על היקפי ההרשאות שנדחו.

עם זאת, יש מקרים חריגים. אפליקציות של Google Workspace Enterprise עם הענקת הרשאות ברמת הדומיין, או אפליקציות שמסומנות כמהימנות, לא יציגו את מסך ההסכמה להרשאות המפורטות. במקרה של האפליקציות האלה, המשתמשים לא יראו את מסך ההסכמה עם ההרשאות המפורטות. במקום זאת, האפליקציה תקבל את כל ההיקפים המבוקשים או אף אחד מהם.

מידע מפורט יותר זמין במאמר בנושא איך מטפלים בהרשאות גרנולריות.

PHP

כדי לבדוק אילו היקפי הרשאות המשתמש העניק, משתמשים בשיטה getGrantedScope():

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

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

Python

אובייקט credentials שמוחזר כולל מאפיין granted_scopes, שהוא רשימה של היקפי ההרשאות שהמשתמש העניק לאפליקציה.

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

הפונקציה הבאה בודקת אילו היקפי הרשאות המשתמש העניק לאפליקציה.

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

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

  return features

Ruby

כשמבקשים כמה היקפי הרשאה בבת אחת, צריך לבדוק אילו היקפי הרשאה אושרו דרך המאפיין scope של האובייקט credentials.

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

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

Node.js

כשמבקשים כמה היקפי הרשאה בבת אחת, צריך לבדוק אילו היקפי הרשאה אושרו דרך המאפיין scope של האובייקט tokens.

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

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

HTTP/REST

כדי לבדוק אם המשתמש העניק לאפליקציה שלכם גישה להיקף מסוים, צריך לבדוק את השדה scope בתגובה של אסימון הגישה. היקפי הגישה שניתנו על ידי access_token, שמוצגים כרשימה של מחרוזות תלויות-אותיות רישיות שמופרדות ברווחים.

לדוגמה, התגובה הבאה של אסימון גישה לדוגמה מציינת שהמשתמש העניק לאפליקציה שלכם גישה להרשאות קריאה בלבד של פעילות ב-Drive ואירועים ביומן:

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

קריאה לממשקי Google APIs

PHP

כדי להשתמש באסימון הגישה להפעלת ממשקי Google API, צריך לבצע את השלבים הבאים:

  1. אם אתם צריכים להחיל אסימון גישה על אובייקט Google\Client חדש – לדוגמה, אם שמרתם את אסימון הגישה בסשן משתמש – השתמשו בשיטה setAccessToken:
    $client->setAccessToken($access_token);
  2. יוצרים אובייקט שירות עבור ה-API שרוצים להפעיל. כדי ליצור אובייקט שירות, צריך לספק אובייקט Google\Client מורשה לקונסטרוקטור של ה-API שאליו רוצים להתקשר. לדוגמה, כדי להפעיל את Drive API:
    $drive = new Google\Service\Drive($client);
  3. שולחים בקשות לשירות ה-API באמצעות הממשק שמסופק על ידי אובייקט השירות. לדוגמה, כדי להציג את רשימת הקבצים ב-Google Drive של המשתמש המאומת:
    $files = $drive->files->listFiles(array());

Python

אחרי קבלת אסימון גישה, האפליקציה יכולה להשתמש באסימון הזה כדי לאשר בקשות API מטעם חשבון משתמש או חשבון שירות מסוים. משתמשים בפרטי ההרשאה הספציפיים למשתמש כדי ליצור אובייקט שירות עבור ה-API שאליו רוצים לשלוח קריאה, ואז משתמשים באובייקט הזה כדי לשלוח בקשות API עם הרשאה.

  1. יוצרים אובייקט שירות עבור ה-API שרוצים להפעיל. כדי ליצור אובייקט שירות, קוראים לשיטה build של הספרייה googleapiclient.discovery עם השם והגרסה של ה-API ופרטי הכניסה של המשתמש: לדוגמה, כדי לקרוא לגרסה 3 של Drive API:
    from googleapiclient.discovery import build
    
    drive = build('drive', 'v2', credentials=credentials)
  2. שולחים בקשות לשירות ה-API באמצעות הממשק שמסופק על ידי אובייקט השירות. לדוגמה, כדי להציג את רשימת הקבצים ב-Google Drive של המשתמש המאומת:
    files = drive.files().list().execute()

Ruby

אחרי קבלת אסימון גישה, האפליקציה יכולה להשתמש באסימון הזה כדי לשלוח בקשות API בשם חשבון משתמש או חשבון שירות מסוים. משתמשים בפרטי ההרשאה הספציפיים למשתמש כדי ליצור אובייקט שירות עבור ה-API שאליו רוצים לשלוח קריאה, ואז משתמשים באובייקט הזה כדי לשלוח בקשות API עם הרשאה.

  1. יוצרים אובייקט שירות עבור ה-API שרוצים להפעיל. לדוגמה, כדי להפעיל את גרסה 3 של Drive API:
    drive = Google::Apis::DriveV3::DriveService.new
  2. מגדירים את פרטי הכניסה בשירות:
    drive.authorization = credentials
  3. שולחים בקשות לשירות ה-API באמצעות הממשק שמסופק על ידי אובייקט השירות. לדוגמה, כדי להציג את רשימת הקבצים ב-Google Drive של המשתמש המאומת:
    files = drive.list_files

לחלופין, אפשר לספק הרשאה לכל שיטה בנפרד על ידי העברת הפרמטר options לשיטה:

files = drive.list_files(options: { authorization: credentials })

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. כדי לעשות את זה, צריך לכלול את אסימון הגישה בבקשה ל-API באמצעות פרמטר access_token של שאילתה או ערך של Authorization כותרת HTTP Bearer. כשניתן, עדיף להשתמש בכותרת HTTP, כי מחרוזות שאילתה נוטות להיות גלויות ביומני השרת. ברוב המקרים, אפשר להשתמש בספריית לקוח כדי להגדיר את הקריאות ל-Google APIs (לדוגמה, כשקוראים ל-Drive Files API).

אתם יכולים להתנסות בכל ממשקי Google APIs ולראות את היקפי ההרשאות שלהם ב-OAuth 2.0 Playground.

דוגמאות ל-HTTP GET

קריאה לנקודת הקצה drive.files (ה-API של קובצי Drive) באמצעות כותרת ה-HTTP‏ Authorization: Bearer עשויה להיראות כך: שימו לב: צריך לציין טוקן גישה משלכם:

GET /drive/v2/files HTTP/1.1
Host: www.googleapis.com
Authorization: Bearer access_token

זוהי קריאה לאותו API עבור המשתמש המאומת באמצעות פרמטר מחרוזת השאילתה access_token:

GET https://www.googleapis.com/drive/v2/files?access_token=access_token

curl דוגמאות

אפשר לבדוק את הפקודות האלה באמצעות אפליקציית שורת הפקודה curl. הנה דוגמה לשימוש באפשרות של כותרת HTTP (מומלץ):

curl -H "Authorization: Bearer access_token" https://www.googleapis.com/drive/v2/files

או לחלופין, האפשרות של פרמטר מחרוזת השאילתה:

curl https://www.googleapis.com/drive/v2/files?access_token=access_token

דוגמה מלאה

בדוגמה הבאה מודפסת רשימה של קבצים ב-Google Drive של משתמש בפורמט JSON, אחרי שהמשתמש מאמת את עצמו ומביע הסכמה לאפליקציה לגשת למטא-נתונים של Drive של המשתמש.

PHP

כדי להריץ את הדוגמה הזו:

  1. ב- API Console, מוסיפים את כתובת ה-URL של המכונה המקומית לרשימה של כתובות URL להפניה אוטומטית. לדוגמה, מוסיפים את http://localhost:8080.
  2. יוצרים ספרייה חדשה ועוברים אליה. לדוגמה:
    mkdir ~/php-oauth2-example
    cd ~/php-oauth2-example
  3. מתקינים את ספריית הלקוח של Google API ל-PHP באמצעות Composer:
    composer require google/apiclient:^2.15.0
  4. יוצרים את הקבצים index.php ו-oauth2callback.php עם התוכן הבא.
  5. מריצים את הדוגמה באמצעות שרת האינטרנט המובנה של PHP לבדיקה:
    php -S localhost:8080 ~/php-oauth2-example

index.php

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

session_start();

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

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

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

oauth2callback.php

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

session_start();

$client = new Google\Client();

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

// Required, to set the scope value, call the addScope function.
$client->addScope([Google\Service\Drive::DRIVE_METADATA_READONLY, Google\Service\Calendar::CALENDAR_READONLY]);

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

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

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

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

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

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

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

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

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

Python

בדוגמה הזו נעשה שימוש ב-framework‏ Flask. היא מריצה אפליקציית אינטרנט בכתובת http://localhost:8080 שמאפשרת לכם לבדוק את תהליך OAuth 2.0. אם תעברו לכתובת ה-URL הזו, אמורים להופיע חמישה קישורים:

  • קריאה ל-Drive API: הקישור הזה מפנה לדף שמנסה להריץ בקשת API לדוגמה אם המשתמשים העניקו את ההרשאה. אם צריך, הוא מתחיל את תהליך ההרשאה. אם הפעולה בוצעה ללא שגיאות, התגובה של ה-API תוצג בדף.
  • דף מוקדם לקריאה ל-Calendar API: הקישור הזה מוביל לדף מוקדם שמנסה לבצע בקשה לדוגמה ל-Calendar API אם המשתמשים העניקו את ההרשאה. במקרה הצורך, הוא מתחיל את תהליך ההרשאה. אם הפעולה בוצעה ללא שגיאות, התגובה של ה-API תוצג בדף.
  • בדיקת תהליך ההרשאה ישירות: הקישור הזה מפנה לדף שמנסה להעביר את המשתמש דרך תהליך ההרשאה. האפליקציה מבקשת הרשאה לשלוח בקשות מורשות ל-API בשם המשתמש.
  • ביטול האישורים הנוכחיים: הקישור הזה מוביל לדף שבו מבוטלות ההרשאות שהמשתמש כבר העניק לאפליקציה.
  • ניקוי פרטי הכניסה של סשן Flask: הקישור הזה מנקה את פרטי ההרשאה שמאוחסנים בסשן Flask. כך תוכלו לראות מה יקרה אם משתמש שכבר העניק הרשאה לאפליקציה ינסה להפעיל בקשת API בסשן חדש. בנוסף, תוכלו לראות את תגובת ה-API שהאפליקציה שלכם תקבל אם משתמש יבטל את ההרשאות שניתנו לאפליקציה, והאפליקציה עדיין תנסה לאשר בקשה עם טוקן גישה שבוטל.
# -*- coding: utf-8 -*-

import os
import flask
import requests

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

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

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

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

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

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

  features = flask.session['features']

  if features['drive']:
    # Load credentials from the session.
    credentials = google.oauth2.credentials.Credentials(
        **flask.session['credentials'])

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

    files = drive.files().list().execute()

    # Save credentials back to session in case access token was refreshed.
    # ACTION ITEM: In a production app, you likely want to save these
    #              credentials in a persistent database instead.
    flask.session['credentials'] = credentials_to_dict(credentials)

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

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

      features = flask.session['features']

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

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

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

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

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

  return flask.redirect(authorization_url)

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

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

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

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

  # Check which scopes user granted
  features = check_granted_scopes(credentials)
  flask.session['features'] = features
  return flask.redirect('/')
  

@app.route('/revoke')
def revoke():
  if 'credentials' not in flask.session:
    return ('You need to <a href="/authorize">authorize</a> before ' +
            'testing the code to revoke credentials.')

  credentials = google.oauth2.credentials.Credentials(
    **flask.session['credentials'])

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

  status_code = getattr(revoke, 'status_code')
  if status_code == 200:
    return('Credentials successfully revoked.' + print_index_table())
  else:
    return('An error occurred.' + print_index_table())

@app.route('/clear')
def clear_credentials():
  if 'credentials' in flask.session:
    del flask.session['credentials']
  return ('Credentials have been cleared.<br><br>' +
          print_index_table())

def credentials_to_dict(credentials):
  return {'token': credentials.token,
          'refresh_token': credentials.refresh_token,
          'token_uri': credentials.token_uri,
          'client_id': credentials.client_id,
          'client_secret': credentials.client_secret,
          'granted_scopes': credentials.granted_scopes}

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

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

  return features

def print_index_table():
  return ('<table>' +
          '<tr><td><a href="/test">Test an API request</a></td>' +
          '<td>Submit an API request and see a formatted JSON response. ' +
          '    Go through the authorization flow if there are no stored ' +
          '    credentials for the user.</td></tr>' +
          '<tr><td><a href="/authorize">Test the auth flow directly</a></td>' +
          '<td>Go directly to the authorization flow. If there are stored ' +
          '    credentials, you still might not be prompted to reauthorize ' +
          '    the application.</td></tr>' +
          '<tr><td><a href="/revoke">Revoke current credentials</a></td>' +
          '<td>Revoke the access token associated with the current user ' +
          '    session. After revoking credentials, if you go to the test ' +
          '    page, you should see an <code>invalid_grant</code> error.' +
          '</td></tr>' +
          '<tr><td><a href="/clear">Clear Flask session credentials</a></td>' +
          '<td>Clear the access token currently stored in the user session. ' +
          '    After clearing the token, if you <a href="/test">test the ' +
          '    API request</a> again, you should go back to the auth flow.' +
          '</td></tr></table>')

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

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

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

Ruby

בדוגמה הזו נעשה שימוש ב-framework‏ Sinatra.

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

require 'google/apis/drive_v3'
require 'google/apis/calendar_v3'

require 'sinatra'

configure do
  enable :sessions

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

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

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

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

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

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

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

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

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

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

Node.js

כדי להריץ את הדוגמה הזו:

  1. ב- API Console, מוסיפים את כתובת ה-URL של המכונה המקומית לרשימה של כתובות URL להפניה אוטומטית. לדוגמה, מוסיפים את http://localhost.
  2. צריך לוודא שיש לכם גרסת LTS לתחזוקה, גרסת LTS פעילה או גרסה נוכחית של Node.js.
  3. יוצרים ספרייה חדשה ועוברים אליה. לדוגמה:
    mkdir ~/nodejs-oauth2-example
    cd ~/nodejs-oauth2-example
  4. מתקינים את ספריית הלקוח של Google API ל-Node.js באמצעות npm:
    npm install googleapis
  5. יוצרים את הקבצים main.js עם התוכן הבא.
  6. מריצים את הדוגמה:
    node .\main.js

main.js

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

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

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

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

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

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

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

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

    res.redirect(authorizationUrl);
  });

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

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

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

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

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

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

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

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

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


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

HTTP/REST

בדוגמה הזו של Python נעשה שימוש ב-Flask framework ובספריית 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/drive.metadata.readonly https://www.googleapis.com/auth/calendar.readonly'

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

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

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

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

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

  return r

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

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

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

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

כללי אימות של URI להפניה

‫Google מחילה את כללי האימות הבאים על כתובות URI להפניה אוטומטית כדי לעזור למפתחים לשמור על האבטחה של האפליקציות שלהם. כתובות ה-URI להפניה אוטומטית חייבות לעמוד בכללים הבאים. ההגדרות של domain,‏ host,‏ path,‏ query,‏ scheme ו-userinfo שמוזכרות בהמשך מופיעות בסעיף 3 ב-RFC 3986.

כללי אימות
Scheme

מזהי URI להפניה אוטומטית חייבים להשתמש בסכימת HTTPS, ולא ב-HTTP רגיל. מזהי URI של localhost (כולל מזהי URI של כתובות IP של localhost) פטורים מהכלל הזה.

מארח

מארחים לא יכולים להיות כתובות IP גולמיות. כתובות IP של localhost פטורות מהכלל הזה.

דומיין
  • דומיינים ברמה העליונה (TLD) של המארח (Top Level Domains) צריכים להיות חלק מרשימת הסיומות הציבוריות.
  • דומיינים מארחים לא יכולים להיות “googleusercontent.com”.
  • כתובות URI להפניה מחדש לא יכולות להכיל דומיינים של כלי לקיצור כתובות URL (לדוגמה, goo.gl) אלא אם האפליקציה היא הבעלים של הדומיין. בנוסף, אם אפליקציה שבבעלותה דומיין לקיצור כתובות בוחרת להפנות לדומיין הזה, כתובת ה-URI להפניה חייבת להכיל “/google-callback/” בנתיב שלה או להסתיים ב-“/google-callback”.
  • Userinfo

    כתובות URI להפניה לא יכולות להכיל את רכיב המשנה userinfo.

    נתיב

    כתובות URI להפניה אוטומטית לא יכולות להכיל מעבר נתיב (שנקרא גם מעקב אחר ספריות), שמיוצג על ידי “/..” או “\..” או קידוד כתובת ה-URL שלהם.

    שאילתה

    כתובות URI להפניה אוטומטית לא יכולות להכיל הפניות אוטומטיות פתוחות.

    Fragment

    כתובות URI להפניה אוטומטית לא יכולות להכיל את רכיב המקטע.

    דמויות כתובות URI להפניה אוטומטית לא יכולות להכיל תווים מסוימים, כולל:
    • תווים כלליים לחיפוש ('*')
    • תווי ASCII שלא ניתן להדפיס
    • קידודים לא תקינים של אחוזים (כל קידוד של אחוזים שלא עומד בפורמט של קידוד URL של סימן אחוז ואחריו שתי ספרות הקסדצימליות)
    • תווים ריקים (תו NULL מקודד, למשל, %00, %C0%80)

    הרשאה מצטברת

    בפרוטוקול OAuth 2.0, האפליקציה שלכם מבקשת הרשאה לגשת למשאבים שמזוהים לפי היקפי הרשאות. השיטה המומלצת לשיפור חוויית המשתמש היא לבקש הרשאה למשאבים בזמן שאתם צריכים אותם. כדי לאפשר את השיטה הזו, שרת ההרשאות של Google תומך בהרשאה מצטברת. התכונה הזו מאפשרת לבקש היקפי הרשאות לפי הצורך, ואם המשתמש מעניק הרשאה להיקף החדש, היא מחזירה קוד הרשאה שאפשר להמיר לטוקן שמכיל את כל היקפי ההרשאות שהמשתמש העניק לפרויקט.

    לדוגמה, אפליקציה שמאפשרת לאנשים להאזין לדגימות של טראקים מוזיקליים וליצור מיקסים עשויה להזדקק למעט מאוד משאבים בזמן הכניסה, אולי רק לשם של האדם שנכנס. עם זאת, כדי לשמור מיקס שהושלם, נדרשת גישה ל-Google Drive שלהם. רוב האנשים יחשבו שזה הגיוני אם תתבקש מהם גישה ל-Google Drive רק כשהאפליקציה באמת צריכה אותה.

    במקרה כזה, בזמן הכניסה, האפליקציה עשויה לבקש את היקפי ההרשאות openid ו-profile כדי לבצע כניסה בסיסית, ואז לבקש את היקף ההרשאות https://www.googleapis.com/auth/drive.file בזמן הבקשה הראשונה לשמירת מיקס.

    כדי להטמיע הרשאה מצטברת, משלימים את התהליך הרגיל לבקשת טוקן גישה, אבל מוודאים שבקשת ההרשאה כוללת את ההיקפים שהוענקו קודם. הגישה הזו מאפשרת לאפליקציה שלכם להימנע מניהול של כמה אסימוני גישה.

    הכללים הבאים חלים על אסימון גישה שהתקבל מהרשאה מצטברת:

    • אפשר להשתמש באסימון כדי לגשת למשאבים שמתאימים לכל ההיקפים ששולבו בהרשאה החדשה.
    • כשמשתמשים באסימון הרענון לאישור המשולב כדי לקבל אסימון גישה, אסימון הגישה מייצג את האישור המשולב ואפשר להשתמש בו לכל אחד מהערכים scope שכלולים בתגובה.
    • ההרשאה המשולבת כוללת את כל ההיקפים שהמשתמש העניק לפרויקט ה-API, גם אם ההרשאות התבקשו מלקוחות שונים. לדוגמה, אם משתמש העניק גישה להיקף אחד באמצעות לקוח למחשב של אפליקציה, ולאחר מכן העניק גישה להיקף אחר לאותה אפליקציה באמצעות לקוח לנייד, ההרשאה המשולבת תכלול את שני ההיקפים.
    • אם מבטלים טוקן שמייצג הרשאה משולבת, הגישה לכל ההיקפים של ההרשאה הזו בשם המשתמש המשויך מבוטלת בו-זמנית.

    דוגמאות הקוד הספציפיות לשפה שמופיעות בשלב 1: הגדרת פרמטרים של הרשאה וכתובת ה-URL לדוגמה להפניה אוטומטית של HTTP/REST שמופיעה בשלב 2: הפניה אוטומטית לשרת OAuth 2.0 של Google, כולן משתמשות בהרשאה מצטברת. בדוגמאות הקוד שבהמשך מוצג גם הקוד שצריך להוסיף כדי להשתמש בהרשאה מצטברת.

    PHP

    $client->setIncludeGrantedScopes(true);

    Python

    ב-Python, מגדירים את ארגומנט מילת המפתח include_granted_scopes לערך true כדי לוודא שבקשת הרשאה כוללת היקפי הרשאה שניתנו בעבר. יכול להיות מאוד ש-include_granted_scopes לא יהיה ארגומנט מילת המפתח היחיד שתגדירו, כמו שמוצג בדוגמה שלמטה.

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

    Ruby

    auth_client.update!(
      :additional_parameters => {"include_granted_scopes" => "true"}
    )

    Node.js

    const authorizationUrl = oauth2Client.generateAuthUrl({
      // 'online' (default) or 'offline' (gets refresh_token)
      access_type: 'offline',
      /** Pass in the scopes array defined above.
        * Alternatively, if only one scope is needed, you can pass a scope URL as a string */
      scope: scopes,
      // Enable incremental authorization. Recommended as a best practice.
      include_granted_scopes: true
    });

    HTTP/REST

    GET https://accounts.google.com/o/oauth2/v2/auth?
      client_id=your_client_id&
      response_type=code&
      state=state_parameter_passthrough_value&
      scope=https%3A//www.googleapis.com/auth/drive.metadata.readonly%20https%3A//www.googleapis.com/auth/calendar.readonly&
      redirect_uri=https%3A//oauth2.example.com/code&
      prompt=consent&
      include_granted_scopes=true

    רענון של טוקן גישה (גישה במצב אופליין)

    התוקף של טוקנים לגישה פג מדי פעם, והם הופכים לפרטי כניסה לא תקינים לבקשת API קשורה. אתם יכולים לרענן טוקן גישה בלי לבקש מהמשתמש הרשאה (כולל כשהמשתמש לא נמצא), אם ביקשתם גישה אופליין להיקפי ההרשאות שמשויכים לטוקן.

    • אם אתם משתמשים בספריית לקוח של Google API, אובייקט הלקוח מרענן את אסימון הגישה לפי הצורך, כל עוד הגדרתם את האובייקט הזה לגישה אופליין.
    • אם אתם לא משתמשים בספריית לקוח, אתם צריכים להגדיר את פרמטר השאילתה access_type HTTP לערך offline כשאתם מפנים את המשתמש לשרת OAuth 2.0 של Google. במקרה כזה, שרת ההרשאות של Google מחזיר טוקן רענון כשמחליפים קוד הרשאה בטוקן גישה. לאחר מכן, אם יפוג התוקף של אסימון הגישה (או בכל זמן אחר), תוכלו להשתמש באסימון רענון כדי לקבל אסימון גישה חדש.

    בקשה לגישה אופליין היא דרישה לכל אפליקציה שצריכה לגשת ל-Google API כשהמשתמש לא נמצא. לדוגמה, אפליקציה שמבצעת שירותי גיבוי או מבצעת פעולות בזמנים שנקבעו מראש צריכה להיות מסוגלת לרענן את אסימון הגישה שלה כשהמשתמש לא נמצא. סגנון ברירת המחדל של הגישה נקרא online.

    אפליקציות אינטרנט בצד השרת, אפליקציות מותקנות ומכשירים מקבלים אסימוני רענון במהלך תהליך ההרשאה. בדרך כלל לא משתמשים בטוקנים לרענון באפליקציות אינטרנט מצד הלקוח (JavaScript).

    PHP

    אם האפליקציה שלכם צריכה גישה לא מקוונת ל-Google API, צריך להגדיר את סוג הגישה של לקוח ה-API ל-offline:

    $client->setAccessType("offline");

    אחרי שמשתמש מעניק גישה אופליין להיקפי ההרשאות המבוקשים, אפשר להמשיך להשתמש בלקוח ה-API כדי לגשת לממשקי Google API מטעם המשתמש כשהוא במצב אופליין. אובייקט הלקוח ירענן את אסימון הגישה לפי הצורך.

    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 API מטעם המשתמש כשהוא במצב אופליין. אובייקט הלקוח ירענן את אסימון הגישה לפי הצורך.

    Ruby

    אם האפליקציה שלכם צריכה גישה לא מקוונת ל-Google API, צריך להגדיר את סוג הגישה של לקוח ה-API ל-offline:

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

    אחרי שמשתמש מעניק גישה אופליין להיקפי ההרשאות המבוקשים, אפשר להמשיך להשתמש בלקוח ה-API כדי לגשת לממשקי Google API מטעם המשתמש כשהוא במצב אופליין. אובייקט הלקוח ירענן את אסימון הגישה לפי הצורך.

    Node.js

    אם האפליקציה שלכם צריכה גישה לא מקוונת ל-Google API, צריך להגדיר את סוג הגישה של לקוח ה-API ל-offline:

    const authorizationUrl = oauth2Client.generateAuthUrl({
      // 'online' (default) or 'offline' (gets refresh_token)
      access_type: 'offline',
      /** Pass in the scopes array defined above.
        * Alternatively, if only one scope is needed, you can pass a scope URL as a string */
      scope: scopes,
      // Enable incremental authorization. Recommended as a best practice.
      include_granted_scopes: true
    });

    אחרי שמשתמש מעניק גישה אופליין להיקפי ההרשאות המבוקשים, אפשר להמשיך להשתמש בלקוח ה-API כדי לגשת לממשקי Google API מטעם המשתמש כשהוא במצב אופליין. אובייקט הלקוח ירענן את אסימון הגישה לפי הצורך.

    תוקף הטוקנים של הגישה פג. הספרייה הזו תשתמש אוטומטית באסימון רענון כדי לקבל אסימון גישה חדש אם התוקף של אסימון הגישה עומד לפוג. דרך קלה לוודא שתמיד מאחסנים את האסימונים העדכניים ביותר היא להשתמש באירוע tokens:

    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 Console.
    client_secret סוד הלקוח שהתקבל מ- API Console.
    grant_type כפי שמוגדר במפרט של OAuth 2.0, הערך של השדה הזה חייב להיות refresh_token.
    refresh_token אסימון הרענון שמוחזר מהמרת קוד ההרשאה.

    בקטע הקוד הבא מוצגת בקשה לדוגמה:

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

    כל עוד המשתמש לא ביטל את הגישה שניתנה לאפליקציה, שרת הטוקנים מחזיר אובייקט JSON שמכיל טוקן גישה חדש. בקטע הקוד הבא מוצגת דוגמה לתשובה:

    {
      "access_token": "1/fFAGRNJru1FTz70BzhT3Zg",
      "expires_in": 3920,
      "scope": "https://www.googleapis.com/auth/drive.metadata.readonly https://www.googleapis.com/auth/calendar.readonly",
      "token_type": "Bearer"
    }

    חשוב לשים לב שיש מגבלות על מספר טוקני הרענון שיונפקו: מגבלה אחת לכל שילוב של לקוח/משתמש, ומגבלה נוספת לכל משתמש בכל הלקוחות. מומלץ לשמור אסימוני רענון באחסון לטווח ארוך ולהמשיך להשתמש בהם כל עוד הם בתוקף. אם האפליקציה שלכם מבקשת יותר מדי אסימוני רענון, היא עלולה לחרוג מהמגבלות האלה, ובמקרה כזה אסימוני רענון ישנים יותר יפסיקו לפעול.

    ביטול טוקן

    במקרים מסוימים, משתמשים רוצים לבטל את הגישה שניתנה לאפליקציה. משתמש יכול לבטל את הגישה דרך הגדרות החשבון. מידע נוסף זמין במאמר התמיכה בנושא אתרים ואפליקציות של צדדים שלישיים בעלי גישה לחשבון שלכם, בקטע 'הסרת גישה של אתר או אפליקציה'.

    אפליקציה יכולה גם לבטל את הגישה שניתנה לה באופן פרוגרמטי. ביטול הרשאה באמצעות תוכנה חשוב במקרים שבהם משתמש מבטל את המינוי, מסיר אפליקציה או שמשאבי ה-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

    מידע נוסף על הטמעה של הגנה על כל החשבונות ורשימה מלאה של האירועים הזמינים מופיע במאמר הגנה על חשבונות משתמשים באמצעות הגנה על כל החשבונות .