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

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

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

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

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

ספריות לקוח

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

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

ספריות הלקוח של 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 שרוצים להפעיל ולוחצים על הלחצן Enable (הפעלה).
  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. לוחצים על יצירת פרטי כניסה > מזהה לקוח OAuth.
  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, מומלץ לזהות את ההיקפים שאליהם האפליקציה תצטרך הרשאה כדי לגשת.

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

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

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

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

PHP

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

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

    composer require google/apiclient:^2.10

Python

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

  • Python 2.6 ואילך
  • הכלי לניהול חבילות pip.
  • ספריית הלקוח של Google APIs ל-Python:
    pip install --upgrade google-api-python-client
  • google-auth, google-auth-oauthlib ו-google-auth-httplib2 של הרשאת משתמש.
    pip install --upgrade google-auth google-auth-oauthlib google-auth-httplib2
  • framework של אפליקציית האינטרנט Flask Python.
    pip install --upgrade flask
  • ספריית ה-HTTP של requests.
    pip install --upgrade requests

Ruby

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

  • Ruby 2.6 ומעלה
  • ספריית Google Auth ל-Ruby:

    gem install googleauth
  • מסגרת אפליקציית האינטרנט של Sinatra Ruby

    gem install sinatra

Node.js

כדי להריץ את דוגמאות הקוד של Node.js במסמך הזה, צריך:

  • גרסת ה-LTS לתחזוקה, מערכת ה-LTS הפעילה או הגרסה הנוכחית של Node.js.
  • לקוח Google APIs Node.js:

    npm install googleapis

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 של המשתמש:

$client = new Google\Client();

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

// Required, to set the scope value, call the addScope function
$client->addScope(Google\Service\Drive::DRIVE_METADATA_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'])

# 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',
    # Recommended, state value can increase your assurance that an incoming connection is the result
    # of an authentication request.
    state=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.
    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 'google/apis/drive_v3'
require "googleauth"
require 'googleauth/stores/redis_token_store'

client_id = Google::Auth::ClientId.from_file('/path/to/client_secret.json')
scope = 'https://www.googleapis.com/auth/drive.metadata.readonly'
token_store = Google::Auth::Stores::RedisTokenStore.new(redis: Redis.new)
authorizer = Google::Auth::WebUserAuthorizer.new(client_id, scope, token_store, '/oauth2callback')

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

Node.js

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

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

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

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

// Access scopes for read-only Drive activity.
const scopes = [
  'https://www.googleapis.com/auth/drive.metadata.readonly'
];

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

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

HTTP/REST

נקודת הקצה (endpoint) OAuth 2.0 של Google נמצאת בכתובת https://accounts.google.com/o/oauth2/v2/auth. אפשר לגשת לנקודת הקצה הזו רק ב-HTTPS. המערכת דוחה חיבורי HTTP פשוטים.

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

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

מזהה הלקוח באפליקציה שלכם. הערך הזה מופיע ב Credentials page API Console.

redirect_uri חובה

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

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

response_type חובה

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

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

scope חובה

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

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

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

access_type המלצות

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

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

state המלצות

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

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

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 להרשאה באמצעות framework של אפליקציית האינטרנט של Flask:

return flask.redirect(authorization_url)

Ruby

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

Node.js

  1. משתמשים בכתובת ה-URL שנוצרה authorizationUrl משיטת שלב 1 generateAuthUrl כדי לבקש גישה משרת OAuth 2.0 של Google.
  2. עליך להפנות את המשתמש אל authorizationUrl.
    res.writeHead(301, { "Location": authorizationUrl });

HTTP/REST

Sample redirect to Google's authorization server

An example URL is shown below, with line breaks and spaces for readability.

https://accounts.google.com/o/oauth2/v2/auth?
 scope=https%3A//www.googleapis.com/auth/drive.metadata.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. במאמר העזרה לאדמינים ב-Google Workspace מוסבר איך לקבוע לאילו אפליקציות של צד שלישי ואפליקציות פנימיות תהיה גישה לנתונים של Google Workspace למידע נוסף על האופן שבו האדמין יכול להגביל את הגישה לכל ההיקפים או להיקפים הרגישים והמוגבלים, עד שניתנת גישה מפורשת למזהה הלקוח ב-OAuth.

disallowed_useragent

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

Android

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

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

iOS

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

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

org_internal

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

invalid_client

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

invalid_grant

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

redirect_uri_mismatch

הערך redirect_uri שהועבר בבקשת ההרשאה לא תואם ל-URI מורשה של הפניה אוטומטית עבור מזהה הלקוח ב-OAuth. יש לבדוק מזהי URI מורשים להפניה אוטומטית ב- Google API Console Credentials page.

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

invalid_request

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

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

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

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

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

תגובת שגיאה:

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

תגובה של קוד הרשאה:

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

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

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

https://accounts.google.com/o/oauth2/v2/auth?
 scope=https%3A//www.googleapis.com/auth/drive.metadata.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

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

$client->authenticate($_GET['code']);

ניתן לאחזר את אסימון הגישה באמצעות השיטה getAccessToken:

$access_token = $client->getAccessToken();

Python

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

state = flask.session['state']
flow = google_auth_oauthlib.flow.Flow.from_client_secrets_file(
    'client_secret.json',
    scopes=['https://www.googleapis.com/auth/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,
    'scopes': credentials.scopes}

Ruby

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

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

Node.js

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

const url = require('url');

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

  // Get access and refresh tokens (if access_type is offline)
  let { tokens } = await oauth2Client.getToken(q.code);
  oauth2Client.setCredentials(tokens);
}

HTTP/REST

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

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

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

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

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

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

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

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

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

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

שגיאות

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

invalid_grant

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

קריאה ל-Google APIs

PHP

כך משתמשים באסימון הגישה כדי לקרוא ל-Google APIs:

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

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 שרוצים לקרוא לו.

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

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

דוגמאות GET של HTTP

קריאה לנקודת הקצה drive.files (ה-API של Drive Files) באמצעות כותרת ה-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

דוגמה מלאה

בדוגמה הבאה מדפיסים רשימת קבצים בפורמט JSON ב-Google Drive של המשתמש, אחרי שהמשתמש מבצע אימות ומאשר את הגישה של האפליקציה למטא-נתונים של המשתמש ב-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.10
  4. יוצרים את הקבצים index.php ו-oauth2callback.php עם התוכן שלמטה.
  5. מריצים את הדוגמה עם שרת אינטרנט שמוגדר לשרת PHP. אם משתמשים ב-PHP 5.6 ואילך, אפשר להשתמש בשרת הבדיקה המובנה של PHP:
    php -S localhost:8080 ~/php-oauth2-example

index.php

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

session_start();

$client = new Google\Client();
$client->setAuthConfig('client_secrets.json');
$client->addScope(Google\Service\Drive::DRIVE_METADATA_READONLY);

if (isset($_SESSION['access_token']) && $_SESSION['access_token']) {
  $client->setAccessToken($_SESSION['access_token']);
  $drive = new Google\Service\Drive($client);
  $files = $drive->files->listFiles(array())->getItems();
  echo json_encode($files);
} else {
  $redirect_uri = 'http://' . $_SERVER['HTTP_HOST'] . '/oauth2callback.php';
  header('Location: ' . filter_var($redirect_uri, FILTER_SANITIZE_URL));
}

oauth2callback.php

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

session_start();

$client = new Google\Client();
$client->setAuthConfigFile('client_secrets.json');
$client->setRedirectUri('http://' . $_SERVER['HTTP_HOST'] . '/oauth2callback.php');
$client->addScope(Google\Service\Drive::DRIVE_METADATA_READONLY);

if (! isset($_GET['code'])) {
  $auth_url = $client->createAuthUrl();
  header('Location: ' . filter_var($auth_url, FILTER_SANITIZE_URL));
} else {
  $client->authenticate($_GET['code']);
  $_SESSION['access_token'] = $client->getAccessToken();
  $redirect_uri = 'http://' . $_SERVER['HTTP_HOST'] . '/';
  header('Location: ' . filter_var($redirect_uri, FILTER_SANITIZE_URL));
}

Python

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

  • בדיקה של בקשת API: הקישור הזה מפנה לדף שמנסה לבצע בקשת 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"

# This OAuth 2.0 access scope allows for full read/write access to the
# authenticated user's account and requires requests to use an SSL connection.
SCOPES = ['https://www.googleapis.com/auth/drive.metadata.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('/test')
def test_api_request():
  if 'credentials' not in flask.session:
    return flask.redirect('authorize')

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

  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)


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

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

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

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

  return flask.redirect(authorization_url)


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

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

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

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

  return flask.redirect(flask.url_for('test_api_request'))


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

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

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

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


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


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

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


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

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

Ruby

בדוגמה הזו נשתמש במסגרת Sinatra.

require 'google/apis/drive_v3'
require 'sinatra'
require 'googleauth'
require 'googleauth/stores/redis_token_store'

configure do
  enable :sessions

  set :client_id, Google::Auth::ClientId.from_file('/path/to/client_secret.json')
  set :scope, Google::Apis::DriveV3::AUTH_DRIVE_METADATA_READONLY
  set :token_store, Google::Auth::Stores::RedisTokenStore.new(redis: Redis.new)
  set :authorizer, Google::Auth::WebUserAuthorizer.new(settings.client_id, settings.scope, settings.token_store, '/oauth2callback')
end

get '/' do
  user_id = settings.client_id.id
  credentials = settings.authorizer.get_credentials(user_id, request)
  if credentials.nil?
    redirect settings.authorizer.get_authorization_url(login_hint: user_id, request: request)
  end
  drive = Google::Apis::DriveV3::DriveService.new
  files = drive.list_files(options: { authorization: credentials })
  "<pre>#{JSON.pretty_generate(files.to_h)}</pre>"
end

get '/oauth2callback' do
  target_url = Google::Auth::WebUserAuthorizer.handle_auth_callback_deferred(request)
  redirect target_url
end

Node.js

כדי להפעיל את הדוגמה הזו:

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

main.js

const http = require('http');
const https = require('https');
const url = require('url');
const { google } = require('googleapis');

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

// Access scopes for read-only Drive activity.
const scopes = [
  'https://www.googleapis.com/auth/drive.metadata.readonly'
];

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

/* 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 server = http.createServer(async function (req, res) {
    // Example on redirecting user to Google's OAuth 2.0 server.
    if (req.url == '/') {
      res.writeHead(301, { "Location": authorizationUrl });
    }

    // Receive the callback from Google's OAuth 2.0 server.
    if (req.url.startsWith('/oauth2callback')) {
      // 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 { // Get access and refresh tokens (if access_type is offline)
        let { tokens } = await oauth2Client.getToken(q.code);
        oauth2Client.setCredentials(tokens);

        /** Save credential to the global variable in case access token was refreshed.
          * ACTION ITEM: In a production app, you likely want to save the refresh token
          *              in a secure persistent database instead. */
        userCredential = tokens;

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

    // Example on revoking a token
    if (req.url == '/revoke') {
      // 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();
    }
    res.end();
  }).listen(80);
}
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__)

CLIENT_ID = '123456789.apps.googleusercontent.com'
CLIENT_SECRET = 'abc123'  # Read from a file or environmental variable in a real app
SCOPE = 'https://www.googleapis.com/auth/drive.metadata.readonly'
REDIRECT_URI = 'http://example.com/oauth2callback'


@app.route('/')
def index():
  if 'credentials' not in flask.session:
    return flask.redirect(flask.url_for('oauth2callback'))
  credentials = json.loads(flask.session['credentials'])
  if credentials['expires_in'] <= 0:
    return flask.redirect(flask.url_for('oauth2callback'))
  else:
    headers = {'Authorization': 'Bearer {}'.format(credentials['access_token'])}
    req_uri = 'https://www.googleapis.com/drive/v2/files'
    r = requests.get(req_uri, headers=headers)
    return r.text


@app.route('/oauth2callback')
def oauth2callback():
  if 'code' not in flask.request.args:
    auth_uri = ('https://accounts.google.com/o/oauth2/v2/auth?response_type=code'
                '&client_id={}&redirect_uri={}&scope={}').format(CLIENT_ID, REDIRECT_URI, SCOPE)
    return flask.redirect(auth_uri)
  else:
    auth_code = flask.request.args.get('code')
    data = {'code': auth_code,
            'client_id': CLIENT_ID,
            'client_secret': CLIENT_SECRET,
            'redirect_uri': REDIRECT_URI,
            'grant_type': 'authorization_code'}
    r = requests.post('https://oauth2.googleapis.com/token', data=data)
    flask.session['credentials'] = r.text
    return flask.redirect(flask.url_for('index'))


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

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

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

כללי אימות
סכמה

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

מארח

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

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

    מזהי URI של הפניות אוטומטיות לא יכולים להכיל את רכיב המשנה של פרטי המשתמש.

    נתיב

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

    שאילתה

    מזהי URI של הפניות אוטומטיות לא יכולים להכיל הפניות אוטומטיות פתוחות.

    קטע

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

    תווים כתובות URI של הפניות אוטומטיות לא יכולות להכיל תווים מסוימים, כולל:
    • תווים כלליים לחיפוש ('*')
    • תווי ASCII שאינם ניתנים להדפסה
    • קידודי אחוזים לא חוקיים (כל קידוד באחוזים שאינו תואם לצורת קידוד של כתובות URL של סימן אחוז ואחריו שתי ספרות הקסדצימליות)
    • תווי null (תו 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.file&
      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 APIs בשמו של המשתמש, גם במצב אופליין. אובייקט הלקוח ירענן את אסימון הגישה לפי הצורך.

    Python

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

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

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

    Ruby

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

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

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

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

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

    oauth2Client.on('tokens', (tokens) => {
      if (tokens.refresh_token) {
        // store the refresh_token in your secure persistent database
        console.log(tokens.refresh_token);
      }
      console.log(tokens.access_token);
    });

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

    כדי להגדיר את refresh_token במועד מאוחר יותר, אפשר להשתמש בשיטה setCredentials:

    oauth2Client.setCredentials({
      refresh_token: `STORED_REFRESH_TOKEN`
    });
    

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

    HTTP/REST

    כדי לרענן אסימון גישה, האפליקציה שלך שולחת בקשת POST מסוג HTTPS לשרת ההרשאות של Google (https://oauth2.googleapis.com/token) שכוללת את הפרמטרים הבאים:

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

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

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

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

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

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

    ביטול אסימון

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

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