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

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

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

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

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

ספריות לקוח

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

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

ספריות לקוח של 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. בדף ספרייה אפשר למצוא את ממשק YouTube Data API ולהפעיל אותו. צריך לחפש ממשקי API אחרים שהאפליקציה תשתמש בהם ולהפעיל גם אותם.

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

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

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

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

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

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

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

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

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

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

ממשק YouTube Data API v3 משתמש בהיקפים הבאים:

טווחים
https://www.googleapis.com/auth/youtubeניהול חשבון YouTube שלך
https://www.googleapis.com/auth/youtube.channel-memberships.creatorהצגת רשימה מעודכנת של החברים הפעילים במועדון החברים של הערוץ, הרמה הנוכחית שלהם והתאריך שבו הם הצטרפו למועדון
https://www.googleapis.com/auth/youtube.force-sslהצגה, עריכה ומחיקה לצמיתות של סרטונים, דירוגים, תגובות וכתוביות ב-YouTube
https://www.googleapis.com/auth/youtube.readonlyהצגת חשבון YouTube שלך
https://www.googleapis.com/auth/youtube.uploadניהול הסרטונים שלך ב-YouTube
https://www.googleapis.com/auth/youtubepartnerהצגה וניהול של הנכסים והתכנים הקשורים שלך ב-YouTube
https://www.googleapis.com/auth/youtubepartner-channel-auditהצגת מידע פרטי של ערוץ YouTube שלך הרלוונטי בתהליך הביקורת של שותף YouTube.

המסמך היקפי 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.
  • לקוח Node.js של Google APIs:

    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.

לדוגמה, הקוד הזה מבקש גישה אופליין כדי לנהל חשבון YouTube של משתמש:

$client = new Google\Client();

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

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

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

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

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

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

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

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

Python

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

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

לדוגמה, הקוד הזה מבקש גישה אופליין כדי לנהל חשבון YouTube של משתמש:

import google.oauth2.credentials
import google_auth_oauthlib.flow

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

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

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

Ruby

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

לדוגמה, הקוד הזה מבקש גישה אופליין כדי לנהל חשבון YouTube של משתמש:

require 'google/apis/youtube_v3'
require "googleauth"
require 'googleauth/stores/redis_token_store'

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

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

Node.js

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

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

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

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

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

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

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

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

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

HTTP/REST

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

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

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

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

redirect_uri חובה

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

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

response_type חובה

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

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

scope חובה

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

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

ממשק YouTube Data API v3 משתמש בהיקפים הבאים:

טווחים
https://www.googleapis.com/auth/youtubeניהול חשבון YouTube שלך
https://www.googleapis.com/auth/youtube.channel-memberships.creatorהצגת רשימה מעודכנת של החברים הפעילים במועדון החברים של הערוץ, הרמה הנוכחית שלהם והתאריך שבו הם הצטרפו למועדון
https://www.googleapis.com/auth/youtube.force-sslהצגה, עריכה ומחיקה לצמיתות של סרטונים, דירוגים, תגובות וכתוביות ב-YouTube
https://www.googleapis.com/auth/youtube.readonlyהצגת חשבון YouTube שלך
https://www.googleapis.com/auth/youtube.uploadניהול הסרטונים שלך ב-YouTube
https://www.googleapis.com/auth/youtubepartnerהצגה וניהול של הנכסים והתכנים הקשורים שלך ב-YouTube
https://www.googleapis.com/auth/youtubepartner-channel-auditהצגת מידע פרטי של ערוץ YouTube שלך הרלוונטי בתהליך הביקורת של שותף YouTube.

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

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

access_type המלצות

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

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

state המלצות

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

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

include_granted_scopes אופציונלי

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

login_hint אופציונלי

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

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

prompt אופציונלי

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

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

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

שלב 2: הפניה אוטומטית לשרת OAuth 2.0 של Google

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

PHP

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

Python

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

return flask.redirect(authorization_url)

Ruby

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

Node.js

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

HTTP/REST

Sample redirect to Google's authorization server

The sample URL below requests offline access (access_type=offline) to a scope that permits access to view the user's YouTube account. It uses incremental authorization to ensure that the new access token covers any scopes to which the user previously granted the application access. The URL also sets values for the required redirect_uri, response_type, and client_id parameters as well as for the state parameter. The URL contains line breaks and spaces for readability.

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

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

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

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

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

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

שגיאות

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

admin_policy_enforced

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

disallowed_useragent

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

Android

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

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

iOS

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

יכול להיות שמפתחי אתרים ייתקלו בשגיאה הזו כשאפליקציה ל-iOS או ל-macOS פותחת קישור כללי לאינטרנט בסוכן משתמש מוטמע, כשמשתמש יעבור מהאתר לנקודת הקצה (endpoint) של הרשאת 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%2F%2Fwww.googleapis.com%2Fauth%2Fyoutube.readonly&
 access_type=offline&
 include_granted_scopes=true&
 state=state_parameter_passthrough_value&
 redirect_uri=http%3A%2F%2Flocalhost%2Foauth2callback&
 response_type=code&
 client_id=client_id

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

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

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

PHP

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

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

אפשר לאחזר את אסימון הגישה באמצעות ה-method getAccessToken:

$access_token = $client->getAccessToken();

Python

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

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

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

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

Ruby

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

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

Node.js

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

const url = require('url');

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

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

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

HTTP/REST

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

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

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

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

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

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

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

שדות
access_token האסימון שהאפליקציה שלכם שולחת כדי לאשר בקשת Google 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/youtube.force-ssl",
  "refresh_token": "1//xEoDL4iW3cxlI7yDbSRFYNG01kVKM2C-259HOF2aQbI"
}

שגיאות

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

invalid_grant

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

קריאה ל-Google APIs

PHP

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

  1. אם צריך להחיל אסימון גישה על אובייקט Google\Client חדש – לדוגמה, אם אחסנתם את אסימון הגישה בסשן של משתמש – משתמשים ב-method setAccessToken:
    $client->setAccessToken($access_token);
  2. יוצרים אובייקט שירות ל-API שאליו רוצים לקרוא. כדי ליצור אובייקט שירות, מספקים ל-constructor של אובייקט השירות אובייקט Google\Client מורשה של ה-API שרוצים לקרוא אליו. לדוגמה, כדי לשלוח קריאה ל-YouTube Data API:
    $youtube = new Google_Service_YouTube($client);
  3. שולחים בקשות לשירות ה-API באמצעות הממשק של אובייקט השירות. לדוגמה, כדי לאחזר נתונים על ערוץ YouTube של המשתמש המורשה:
    $channel = $youtube->channels->listChannels('snippet', array('mine' => $mine));

Python

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

  1. יוצרים אובייקט שירות ל-API שאליו רוצים לקרוא. כדי ליצור אובייקט שירות, שולחים קריאה ל-method build של הספרייה googleapiclient.discovery עם השם והגרסה של ה-API ועם פרטי הכניסה של המשתמש: לדוגמה, כדי להפעיל את גרסה 3 של YouTube Data API:
    from googleapiclient.discovery import build
    
    youtube = build('youtube', 'v3', credentials=credentials)
  2. שולחים בקשות לשירות ה-API באמצעות הממשק של אובייקט השירות. לדוגמה, כדי לאחזר נתונים על ערוץ YouTube של המשתמש המורשה:
    channel = youtube.channels().list(mine=True, part='snippet').execute()

Ruby

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

  1. יוצרים אובייקט שירות ל-API שאליו רוצים לקרוא. לדוגמה, כדי להפעיל את גרסה 3 של YouTube Data API:
    youtube = Google::Apis::YoutubeV3::YouTubeService.new
  2. מגדירים את פרטי הכניסה בשירות:
    youtube.authorization = credentials
  3. שולחים בקשות לשירות ה-API באמצעות הממשק של אובייקט השירות. לדוגמה, כדי לאחזר נתונים על ערוץ YouTube של המשתמש המורשה:
    channel = youtube.list_channels(part, :mine => mine)

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

channel = youtube.list_channels(part, :mine => mine, options: { authorization: auth_client })

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

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

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

דוגמאות ל-HTTP GET

קריאה לנקודת הקצה ( youtube.channels) (YouTube Data API) באמצעות כותרת ה-HTTP Authorization: Bearer עשויה להיראות כך. שימו לב שתצטרכו לציין אסימון גישה משלכם:

GET /youtube/v3/channels?part=snippet&mine=true HTTP/1.1
Host: www.googleapis.com
Authorization: Bearer access_token

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

GET https://www.googleapis.com/youtube/v3/channels?access_token=access_token&part=snippet&mine=true

curl דוגמאות

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

curl -H "Authorization: Bearer access_token" https://www.googleapis.com/youtube/v3/channels?part=snippet&mine=true

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

curl https://www.googleapis.com/youtube/v3/channels?access_token=access_token&part=snippet&mine=true

דוגמה מלאה

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

PHP

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

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

index.php

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

session_start();

$client = new Google\Client();
$client->setAuthConfig('client_secrets.json');
$client->addScope(GOOGLE_SERVICE_YOUTUBE::YOUTUBE_FORCE_SSL);

if (isset($_SESSION['access_token']) && $_SESSION['access_token']) {
  $client->setAccessToken($_SESSION['access_token']);
  $youtube = new Google_Service_YouTube($client);
  $channel = $youtube->channels->listChannels('snippet', array('mine' => $mine));
  echo json_encode($channel);
} else {
  $redirect_uri = 'http://' . $_SERVER['HTTP_HOST'] . '/oauth2callback.php';
  header('Location: ' . filter_var($redirect_uri, FILTER_SANITIZE_URL));
}

oauth2callback.php

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

session_start();

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

if (! isset($_GET['code'])) {
  // Generate and set state value
  $state = bin2hex(random_bytes(16));
  $client->setState($state);
  $_SESSION['state'] = $state;

  $auth_url = $client->createAuthUrl();
  header('Location: ' . filter_var($auth_url, FILTER_SANITIZE_URL));
} else {
  // Check the state value
  if (!isset($_GET['state']) || $_GET['state'] !== $_SESSION['state']) {
    die('State mismatch. Possible CSRF attack.');
  }
  $client->authenticate($_GET['code']);
  $_SESSION['access_token'] = $client->getAccessToken();
  $redirect_uri = 'http://' . $_SERVER['HTTP_HOST'] . '/';
  header('Location: ' . filter_var($redirect_uri, FILTER_SANITIZE_URL));
}

Python

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

  • בדיקה של בקשת 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/youtube.force-ssl']
API_SERVICE_NAME = 'youtube'
API_VERSION = 'v3'

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


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


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

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

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

  channel = youtube.channels().list(mine=True, part='snippet').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(**channel)


@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

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

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

configure do
  enable :sessions

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

get '/' do
  user_id = settings.client_id.id
  credentials = settings.authorizer.get_credentials(user_id, request)
  if credentials.nil?
    redirect settings.authorizer.get_authorization_url(login_hint: user_id, request: request)
  end
  youtube = Google::Apis::YoutubeV3::YouTubeService.new
  channel = youtube.list_channels(part, :mine => mine, options: { authorization: auth_client })
  
  "<pre>#{JSON.pretty_generate(channel.to_h)}</pre>"
end

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

Node.js

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

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

main.js

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

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

// Access scopes for read-only Drive activity.
const scopes = [
  'https://www.googleapis.com/auth/drive.metadata.readonly'
];
/* Global variable that stores user credential in this code example.
 * ACTION ITEM for developers:
 *   Store user's refresh token in your data store if
 *   incorporating this code into your real app.
 *   For more information on handling refresh tokens,
 *   see https://github.com/googleapis/google-api-nodejs-client#handling-refresh-tokens
 */
let userCredential = null;

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

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

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

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

    res.redirect(authorizationUrl);
  });

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

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

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

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

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

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

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

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

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


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

HTTP/REST

הדוגמה הזו של Python משתמשת ב-framework של 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/youtube.force-ssl'
REDIRECT_URI = 'http://example.com/oauth2callback'


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


@app.route('/oauth2callback')
def oauth2callback():
  if 'code' not in flask.request.args:
    state = str(uuid.uuid4())
    flask.session['state'] = state
    auth_uri = ('https://accounts.google.com/o/oauth2/v2/auth?response_type=code'
                '&client_id={}&redirect_uri={}&scope={}&state={}').format(CLIENT_ID, REDIRECT_URI,
                                                                          SCOPE, state)
    return flask.redirect(auth_uri)
  else:
    if 'state' not in flask.request.args or flask.request.args['state'] != flask.session['state']:
      return 'State mismatch. Possible CSRF attack.', 400

    auth_code = flask.request.args.get('code')
    data = {'code': auth_code,
            'client_id': CLIENT_ID,
            'client_secret': CLIENT_SECRET,
            'redirect_uri': REDIRECT_URI,
            'grant_type': 'authorization_code'}
    r = requests.post('https://oauth2.googleapis.com/token', data=data)
    flask.session['credentials'] = r.text
    return flask.redirect(flask.url_for('index'))


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

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

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

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

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

מארח

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

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

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

    נתיב

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

    שאילתה

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

    מקטע

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

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

    הרשאה מצטברת

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

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

    במקרה כזה, בזמן הכניסה, יכול להיות שהאפליקציה לא תצטרך גישה להיקפים כלשהם או לא תבקש גישה אליהם. עם זאת, אם המשתמש ניסה לסווג סרטון, להוסיף סרטון לפלייליסט או לבצע פעולה אחרת ב-YouTube, האפליקציה תוכל לבקש גישה להיקף ההרשאות https://www.googleapis.com/auth/youtube.force-ssl. באופן דומה, האפליקציה יכולה לבקש גישה להיקף https://www.googleapis.com/auth/calendar אם המשתמש ניסה להוסיף אירוע ביומן.

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

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

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

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

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

    Refreshing an access token (offline access)

    Access tokens periodically expire and become invalid credentials for a related API request. You can refresh an access token without prompting the user for permission (including when the user is not present) if you requested offline access to the scopes associated with the token.

    • If you use a Google API Client Library, the client object refreshes the access token as needed as long as you configure that object for offline access.
    • If you are not using a client library, you need to set the access_type HTTP query parameter to offline when redirecting the user to Google's OAuth 2.0 server. In that case, Google's authorization server returns a refresh token when you exchange an authorization code for an access token. Then, if the access token expires (or at any other time), you can use a refresh token to obtain a new access token.

    Requesting offline access is a requirement for any application that needs to access a Google API when the user is not present. For example, an app that performs backup services or executes actions at predetermined times needs to be able to refresh its access token when the user is not present. The default style of access is called online.

    Server-side web applications, installed applications, and devices all obtain refresh tokens during the authorization process. Refresh tokens are not typically used in client-side (JavaScript) web applications.

    PHP

    If your application needs offline access to a Google API, set the API client's access type to offline:

    $client->setAccessType("offline");

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