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

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

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

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

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

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

ספריות לקוח

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

PHP

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

  • PHP 5.6 ומעלה עם ממשק שורת פקודה (CLI) ותוסף JSON מותקנים.
  • הכלי לניהול תלות במלחין.
  • ספריית הלקוחות של 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
  • המסגרת של אפליקציית האינטרנט של Flask Python.
    pip install --upgrade flask
  • ספריית requests ב-HTTP.
    pip install --upgrade requests

Ruby

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

  • Ruby 2.2.2 ואילך
  • ספריית הלקוח של Google APIs עבור Ruby:

    gem install google-api-client
  • Framework של אפליקציית האינטרנט סינטרה רובי.

    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, עליך ליצור ולהגדיר אובייקט המגדיר את הפרמטרים האלה.
  • אם מתקשרים ישירות לנקודת הקצה 2.0 של Google OAuth, יוצרים כתובת URL ומגדירים את הפרמטרים בכתובת ה-URL הזו.

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

PHP

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

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

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

$client = new Google\Client();
$client->setAuthConfig('client_secret.json');
$client->addScope(Google\Service\Drive::DRIVE_METADATA_READONLY);
$client->setRedirectUri('http://' . $_SERVER['HTTP_HOST'] . '/oauth2callback.php');
// 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');
// Using "consent" ensures that your application always receives a refresh token.
// If you are not using offline access, you can omit this.
$client->setApprovalPrompt('consent');
$client->setIncludeGrantedScopes(true);   // incremental auth

בבקשה מצוין המידע הבא:

פרמטרים
client_id נדרש

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

ב-PHP, יש לקרוא לפונקציה setAuthConfig כדי לטעון פרטי כניסה מהקובץ client_Secret.json.

$client = new Google\Client();
$client->setAuthConfig('client_secret.json');
redirect_uri נדרש

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

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

כדי להגדיר את הערך הזה ב-PHP, צריך לקרוא לפונקציה setRedirectUri. לתשומת ליבך, יש לציין כתובת URL חוקית להפניה מחדש עבור client_id שצוינה.

$client->setRedirectUri('https://oauth2.example.com/code');
scope נדרש

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

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

כדי להגדיר את הערך הזה ב-PHP, צריך לקרוא לפונקציה addScope:

$client->addScope(Google\Service\Drive::DRIVE_METADATA_READONLY);

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

access_type מומלץ

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

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

כדי להגדיר את הערך הזה ב-PHP, צריך לקרוא לפונקציה setAccessType:

$client->setAccessType('offline');
state מומלץ

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

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

כדי להגדיר את הערך הזה ב-PHP, צריך לקרוא לפונקציה setState:

$client->setState($sample_passthrough_value);
include_granted_scopes אופציונלי

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

כדי להגדיר את הערך הזה ב-PHP, צריך לקרוא לפונקציה setIncludeGrantedScopes:

$client->setIncludeGrantedScopes(true);
login_hint אופציונלי

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

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

כדי להגדיר את הערך הזה ב-PHP, צריך לקרוא לפונקציה setLoginHint:

$client->setLoginHint('None');
prompt אופציונלי

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

כדי להגדיר את הערך הזה ב-PHP, צריך לקרוא לפונקציה setApprovalPrompt:

$client->setApprovalPrompt('consent');

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

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

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

# Use the client_secret.json file to identify the application requesting
# authorization. The client ID (from that file) and access scopes are required.
flow = google_auth_oauthlib.flow.Flow.from_client_secrets_file(
    'client_secret.json',
    scopes=['https://www.googleapis.com/auth/drive.metadata.readonly'])

# Indicate where the API server will redirect the user after the user completes
# the authorization flow. The redirect URI is required. The value must exactly
# match one of the authorized redirect URIs for the OAuth 2.0 client, which you
# configured in the API Console. If this value doesn't match an authorized URI,
# you will get a 'redirect_uri_mismatch' error.
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(
    # 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')

בבקשה מצוין המידע הבא:

פרמטרים
client_id נדרש

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

ב-Python, מתקשרים לשיטה from_client_secrets_file כדי לאחזר את מזהה הלקוח מקובץ client_Secret.json. (ניתן גם להשתמש בשיטה from_client_config, שעוברת את תצורת הלקוח כפי שהיא הופיעה במקור בקובץ Secret של הלקוח, אך אין לה גישה לקובץ עצמו.)

flow = google_auth_oauthlib.flow.Flow.from_client_secrets_file(
    'client_secret.json',
    scopes=['https://www.googleapis.com/auth/drive.metadata.readonly'])
redirect_uri נדרש

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

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

כדי להגדיר את הערך הזה ב-Python, מגדירים את המאפיין redirect_uri של האובייקט flow

flow.redirect_uri = 'https://oauth2.example.com/code'
scope נדרש

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

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

ב-Python, משתמשים באותה שיטה שבה משתמשים כדי להגדיר את client_id כדי לציין את רשימת ההיקפים.

flow = google_auth_oauthlib.flow.Flow.from_client_secrets_file(
    'client_secret.json',
    scopes=['https://www.googleapis.com/auth/drive.metadata.readonly'])

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

access_type מומלץ

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

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

ב-Python, מגדירים את הפרמטר access_type. לשם כך מציינים את access_type כארגומנט של מילת מפתח כשמפעילים את השיטה flow.authorization_url:

authorization_url, state = flow.authorization_url(
    access_type='offline',
    include_granted_scopes='true')
state מומלץ

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

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

ב-Python, מגדירים את הפרמטר state על ידי ציון state כארגומנט של מילת מפתח כשמתקשרים לשיטת flow.authorization_url:

authorization_url, state = flow.authorization_url(
    access_type='offline',
    state=sample_passthrough_value,
    include_granted_scopes='true')
include_granted_scopes אופציונלי

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

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

authorization_url, state = flow.authorization_url(
    access_type='offline',
    include_granted_scopes='true')
login_hint אופציונלי

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

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

ב-Python, מגדירים את הפרמטר login_hint. לשם כך מציינים את login_hint כארגומנט של מילת מפתח כשמפעילים את השיטה flow.authorization_url:

authorization_url, state = flow.authorization_url(
    access_type='offline',
    login_hint='None',
    include_granted_scopes='true')
prompt אופציונלי

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

ב-Python, מגדירים את הפרמטר prompt על ידי ציון prompt כארגומנט של מילת מפתח כשמתקשרים לשיטת flow.authorization_url:

authorization_url, state = flow.authorization_url(
      access_type='offline',
      prompt='consent',
      include_granted_scopes='true')

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

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

Ruby

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

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

require 'google/apis/drive_v2'
require 'google/api_client/client_secrets'

client_secrets = Google::APIClient::ClientSecrets.load
auth_client = client_secrets.to_authorization
auth_client.update!(
  :scope => 'https://www.googleapis.com/auth/drive.metadata.readonly',
  :redirect_uri => 'http://www.example.com/oauth2callback',
  :additional_parameters => {
    "access_type" => "offline",         # offline access
    "include_granted_scopes" => "true"  # incremental auth
  }
)

האפליקציה שלך משתמשת באובייקט הלקוח כדי לבצע פעולות 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

נקודת הקצה 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 נדרש

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

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

scope נדרש

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

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

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

access_type מומלץ

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

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

state מומלץ

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

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

return flask.redirect(authorization_url)

Ruby

  1. יוצרים כתובת URL כדי לבקש גישה משרת OAuth 2.0 של Google:
    auth_uri = auth_client.authorization_uri.to_s
  2. הפניית המשתמש מחדש אל auth_uri.

Node.js

  1. כדי לבקש גישה משרת OAuth 2.0 של Google, יש להשתמש בכתובת ה-URL שנוצרה authorizationUrl משלב 1 generateAuthUrl.
  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 מאמת את המשתמש ומקבל את הסכמתו לאפליקציה שלך כדי לגשת להיקפים המבוקשים. התשובה תישלח בחזרה לאפליקציה שלך באמצעות כתובת האתר להפניה מחדש שציינת.

שלב 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 או OpenID Foundation's AppAuth ל-Android.

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

iOS

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

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

org_internal

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

redirect_uri_mismatch

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

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

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

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

תגובת שגיאה:

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

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

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

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

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

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: קוד הרשאה ל-Exchange עבור אסימוני רענון וגישה

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

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

כדי להחליף קוד הרשאה לאסימון גישה, צריך להשתמש בשיטה fetch_access_token!:

auth_client.code = auth_code
auth_client.fetch_access_token!

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"
}

קריאה ל-Google APIs

PHP

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

  1. אם ברצונך להחיל אסימון גישה על אובייקט Google\Client חדש – לדוגמה, אם שמרת את אסימון הגישה בסשן של משתמש – יש להשתמש בשיטה setAccessToken:
    $client->setAccessToken($access_token);
  2. יוצרים אובייקט שירות עבור ה-API שאליו רוצים להפעיל. כדי ליצור אובייקט שירות, עליך לספק לאובייקט ה-API אובייקט Google\Client מורשה ולהפעיל אותו. לדוגמה, כדי להפעיל את 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 ופרטי הכניסה של המשתמש: לדוגמה, כדי לקרוא לגרסה 2 של Drive API:
    from googleapiclient.discovery import build
    
    drive = build('drive', 'v2', credentials=credentials)
  2. שולחים בקשות לשירות ה-API באמצעות הממשק שסופק על ידי האובייקט של השירות. למשל, כדי לרשום את הקבצים ב-Google Drive של המשתמש המאומת:
    files = drive.files().list().execute()

Ruby

כדי להתקשר ל-Google APIs באמצעות האובייקט auth_client, יש לבצע את השלבים הבאים:

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

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

files = drive.list_files(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

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

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

דוגמאות ל-HTTP GET

קריאה לנקודת הקצה drive.files (ב-Drive Files API) באמצעות כותרת ה-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 require google/apiclient:^2.10
  4. יש ליצור את הקבצים index.php ו-oauth2callback.php עם התוכן שבהמשך.
  5. הרצת הדוגמה עם שרת אינטרנט המוגדר להצגת PHP. אם משתמשים ב-PHP 5.6 ואילך, אפשר להשתמש בשרת האינטרנט המובנה של PHP&#39:
    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 מורשות בשם המשתמש.
  • ביטול פרטי הכניסה הנוכחיים: הקישור מוביל לדף ש מבטל הרשאות שהמשתמש כבר העניק לאפליקציה.
  • ניקוי פרטי הכניסה ל-Flass:הקישור הזה מנקה פרטי כניסה להרשאות השמורים בסשן של 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_v2'
require 'google/api_client/client_secrets'
require 'json'
require 'sinatra'

enable :sessions
set :session_secret, 'setme'

get '/' do
  unless session.has_key?(:credentials)
    redirect to('/oauth2callback')
  end
  client_opts = JSON.parse(session[:credentials])
  auth_client = Signet::OAuth2::Client.new(client_opts)
  drive = Google::Apis::DriveV2::DriveService.new
  files = drive.list_files(options: { authorization: auth_client })
  "<pre>#{JSON.pretty_generate(files.to_h)}</pre>"
end

get '/oauth2callback' do
  client_secrets = Google::APIClient::ClientSecrets.load
  auth_client = client_secrets.to_authorization
  auth_client.update!(
    :scope => 'https://www.googleapis.com/auth/drive.metadata.readonly',
    :redirect_uri => url('/oauth2callback'))
  if request['code'] == nil
    auth_uri = auth_client.authorization_uri.to_s
    redirect to(auth_uri)
  else
    auth_client.code = request['code']
    auth_client.fetch_access_token!
    auth_client.client_secret = nil
    session[:credentials] = auth_client.to_json
    redirect to('/')
  end
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

primary.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 כן כוללת את ספריית הלקוח.)

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 של מארח מקומי פטורות מהכלל הזה.

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

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

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