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

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

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

מנהלי דומיין ב-Google Workspace יכולים גם הענקת הרשאה ברמת הדומיין לחשבונות שירות לגשת למשתמש בשם משתמשים בדומיין.

במסמך הזה מוסבר איך אפליקציה יכולה להשלים את זרימת OAuth 2.0 משרת לשרת באמצעות באמצעות ספריית לקוח של Google APIs (מומלץ) או HTTP.

סקירה כללית

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

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

לבסוף, האפליקציה יכולה להשתמש באסימון הגישה כדי לקרוא ל-Google APIs.

יצירת חשבון שירות

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

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

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

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

首先,创建一个服务帐户:

  1. 打开 Service accounts page
  2. If prompted, select a project, or create a new one.
  3. 单击创建服务帐户
  4. Service account details下,键入服务帐户的名称、ID 和描述,然后点击Create and continue
  5. 可选:在Grant this service account access to project下,选择要授予服务帐户的 IAM 角色。
  6. 单击继续
  7. 可选:在Grant users access to this service account下,添加允许使用和管理服务帐户的用户或组。
  8. 单击完成

接下来,创建一个服务帐户密钥:

  1. 单击您创建的服务帐户的电子邮件地址。
  2. 单击密钥选项卡。
  3. 添加密钥下拉列表中,选择创建新密钥
  4. 单击创建

您的新公钥/私钥对已生成并下载到您的机器上;它作为私钥的唯一副本。您有责任安全地存储它。如果您丢失了这个密钥对,您将需要生成一个新的。

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

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

האצלת הרשאה ברמת הדומיין לחשבון השירות

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

להאציל סמכות ברמת הדומיין לחשבון שירות, סופר-אדמין בחשבון Google צריך להשלים את השלבים הבאים בדומיין של Workspace:

  1. מה-של הדומיין שלך ב-Google Workspace מסוף Admin, עוברים אל התפריט הראשי > אבטחה > שליטה בגישה ובנתונים > בקרות API.
  2. בחלונית הענקת גישה ברמת הדומיין, בוחרים באפשרות ניהול הענקת גישה ברמת הדומיין.
  3. לוחצים על חדש.
  4. בשדה Client ID, מזינים את Client ID של חשבון השירות. טיפים נוספים לאופטימיזציה מפורטים את מזהה הלקוח של חשבון השירות שלכם Service accounts page
  5. בשדה היקפי הרשאות OAuth (מופרדים בפסיקים), מזינים את רשימת היקפי ההרשאות האפליקציה צריכה לקבל גישה אל. לדוגמה, אם לאפליקציה שלכם נדרשת גישה ברמת הדומיין גישה מלאה ל-Google Drive API ול-Google Calendar API, צריך להזין: https://www.googleapis.com/auth/drive, https://www.googleapis.com/auth/calendar.
  6. לוחצים על Authorize.

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

בהכנה לשליחת קריאה ל-API שהוענקה הרשאה

Java

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

import com.google.api.client.googleapis.auth.oauth2.GoogleCredential;
import com.google.api.services.sqladmin.SQLAdminScopes;

// ...

GoogleCredential credential = GoogleCredential.fromStream(new FileInputStream("MyProject-1234.json"))
    .createScoped(Collections.singleton(SQLAdminScopes.SQLSERVICE_ADMIN));

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

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

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

GoogleCredential credential = GoogleCredential.fromStream(new FileInputStream("MyProject-1234.json"))
    .createScoped(Collections.singleton(SQLAdminScopes.SQLSERVICE_ADMIN))
    .createDelegated("workspace-user@example.com");

הקוד שלמעלה משתמש באובייקט GoogleCredential כדי לקרוא ל-createDelegated() שלו . הארגומנט של השיטה createDelegated() חייב להיות משתמש ששייך ל- חשבון Workspace. הקוד שממנו נשלחה הבקשה ישתמש בפרטי הכניסה האלה כדי להתקשר ל-Google ממשקי API שמשתמשים בחשבון השירות שלכם.

Python

אחרי שתקבלו את כתובת האימייל ואת המפתח הפרטי של הלקוח API Console, משתמשים ב ספריית הלקוח של Google APIs ל-Python כדי להשלים את השלבים הבאים:

  1. יוצרים אובייקט Credentials דרך פרטי הכניסה של חשבון השירות ו את היקפי ההרשאות שהאפליקציה צריכה גישה אליהם. מוצרים לדוגמה:
    from google.oauth2 import service_account
    
    SCOPES = ['https://www.googleapis.com/auth/sqlservice.admin']
    SERVICE_ACCOUNT_FILE = '/path/to/service.json'
    
    credentials = service_account.Credentials.from_service_account_file(
            SERVICE_ACCOUNT_FILE, scopes=SCOPES)

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

  2. הענקת גישה לסמכות ברמת הדומיין

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

    delegated_credentials = credentials.with_subject('user@example.org')

משתמשים באובייקט Credentials כדי לקרוא ל-Google APIs באפליקציה.

HTTP/REST

אחרי שמקבלים את מזהה הלקוח והמפתח הפרטי API Console, הבקשה שלך צריכה להשלים את את השלבים הבאים:

  1. ליצור אסימון אינטרנט מסוג JSON (JWT, מבוטא, 'jot') שכולל כותרת, קבוצת הצהרה, וחתימה.
  2. מבקשים אסימון גישה משרת ההרשאות של Google OAuth 2.0.
  3. לטפל בתגובת ה-JSON ששרת ההרשאות מחזיר.

בסעיפים הבאים מתואר איך להשלים את השלבים האלה.

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

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

אפליקציית השרת שלכם משתמשת ב-JWT כדי לבקש אסימון מ-Google
                  שרת ההרשאות משתמש באסימון כדי לקרוא לנקודת קצה (endpoint) של Google API. לא
                  משתמש קצה מעורב.

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

יצירת JWT

JWT מורכב משלושה חלקים: כותרת, קבוצת הצהרות לחתימה. הכותרת וקבוצת התלונות הם אובייקטים של JSON. האובייקטים של ה-JSON עוברים סריאליזציה ל- בייטים מסוג UTF-8, ולאחר מכן מקודדים באמצעות קידוד כתובת URL מסוג Base64. הקידוד הזה מספק עמידות מפני שינויים בקידוד בגלל פעולות קידוד חוזרות. הכותרת, קבוצת התלונות וכן החתימה משורשרות יחד עם תו (.).

JWT מורכב באופן הבא:

{Base64url encoded header}.{Base64url encoded claim set}.{Base64url encoded signature}

מחרוזת הבסיס לחתימה היא:

{Base64url encoded header}.{Base64url encoded claim set}
יצירת הכותרת של ה-JWT

הכותרת מורכבת משלושה שדות שמציינים את אלגוריתם החתימה, את הפורמט של טענת הנכוֹנוּת (assertion) ו[מזהה המפתח של חשבון השירות] key](https://cloud.google.com/iam/docs/reference/rest/v1/projects.serviceAccounts.keys) ששימש לחתימה על ה-JWT. האלגוריתם והפורמט הם שדות חובה, ובכל שדה יש רק בערך אחד. ככל שנוסיף עוד אלגוריתמים ופורמטים, הכותרת הזו תשתנה בהתאם. מזהה המפתח הוא אופציונלי. אם צוין מזהה מפתח שגוי, GCP ינסה את כל המפתחות שמשויכים לחשבון השירות כדי לאמת את האסימון ולדחות את האסימון אם לא נמצא מפתח חוקי. Google שומרת לעצמה את הזכות לדחות אסימונים עם מזהי מפתח שגויים הוא בעתיד.

חשבונות שירות מסתמכים על האלגוריתם SHA-256 של RSA ועל הפורמט של אסימון JWT. כתוצאה מכך, ייצוג ה-JSON של הכותרת ב-JSON:

{"alg":"RS256","typ":"JWT", "kid":"370ab79b4513eb9bad7c9bd16a95cb76b5b2a56a"}

ייצוג Base64url של זה הוא:

          eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsICJraWQiOiIzNzBhYjc5YjQ1MTNlYjliYWQ3YzliZDE2YTk1Y2I3NmI1YjJhNTZhIn0=
יצירת קבוצת הצהרות ה-JWT

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

תלונות נדרשות

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

שם תיאור
iss כתובת האימייל של חשבון השירות.
scope רשימה מופרדת ברווחים של ההרשאות שהאפליקציה מבקשת.
aud מתאר של היעד המיועד של טענת הנכוֹנוּת. כשיוצרים אסימון גישה בקשה שהערך הזה הוא תמיד https://oauth2.googleapis.com/token.
exp זמן התפוגה של טענת הנכוֹנוּת (assertion), שמצוין בשניות החל מ-00:00:00 UTC, 1 בינואר 1970. אפשר להגדיר את הערך הזה עד שעה אחת אחרי מועד ההנפקה.
iat השעה שבה נשלחה טענת הנכוֹנוּת (assertion), שצוינה בשניות החל מ-00:00:00 (שעון UTC), 1 בינואר 1970.

הייצוג ב-JSON של שדות החובה בקבוצת הצהרות של JWT מוצג כאן:

{
  "iss": "761326798069-r5mljlln1rd4lrbhg75efgigp36m78j5@developer.gserviceaccount.com",
  "scope": "https://www.googleapis.com/auth/devstorage.read_only",
  "aud": "https://oauth2.googleapis.com/token",
  "exp": 1328554385,
  "iat": 1328550785
}
תלונות נוספות

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

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

שם תיאור
sub כתובת האימייל של המשתמש שעבורו האפליקציה מבקשת הרשאה גישה.

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

מוצגת דוגמה לקבוצת הצהרות JWT שכוללת את השדה sub למטה:

{
  "iss": "761326798069-r5mljlln1rd4lrbhg75efgigp36m78j5@developer.gserviceaccount.com",
  "sub": "some.user@example.com",
  "scope": "https://www.googleapis.com/auth/prediction",
  "aud": "https://oauth2.googleapis.com/token",
  "exp": 1328554385,
  "iat": 1328550785
}
קידוד קבוצת הצהרות ה-JWT

בדומה לכותרת ה-JWT, צריך לבצע סריאליזציה של קבוצת הצהרות ה-JWT ל-UTF-8 ול-Base64url-safe באמצעות קידוד. בהמשך מוצגת דוגמה לייצוג JSON של קבוצת הצהרות JWT:

{
  "iss": "761326798069-r5mljlln1rd4lrbhg75efgigp36m78j5@developer.gserviceaccount.com",
  "scope": "https://www.googleapis.com/auth/prediction",
  "aud": "https://oauth2.googleapis.com/token",
  "exp": 1328554385,
  "iat": 1328550785
}
חישוב החתימה

חתימת אינטרנט בפורמט JSON (JWS) הוא המפרט שמנחה את המכניקה של יצירת החתימה עבור JWT. הקלט לחתימה הוא מערך הבייטים של התוכן הבא:

{Base64url encoded header}.{Base64url encoded claim set}

צריך להשתמש באלגוריתם החתימה בכותרת ה-JWT בזמן חישוב החתימה. רק אלגוריתם החתימה שנתמך על ידי שרת ההרשאות של Google OAuth 2.0 משתמש ב-RSA אלגוריתם לגיבוב SHA-256. יש לציין זאת כ-RS256 בalg בכותרת ה-JWT.

חותמים על ייצוג UTF-8 של הקלט באמצעות SHA256withRSA (שנקרא גם RSASSA-PKCS1-V1_5-SIGN עם פונקציית הגיבוב (hash) SHA-256) עם המפתח הפרטי שמתקבל מ- Google API Console. הפלט יהיה מערך בייטים.

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

{Base64url encoded header}.
{Base64url encoded claim set}.
{Base64url encoded signature}

בהמשך מוצגת דוגמה של JWT לפני קידוד כתובת URL מסוג Base64:

{"alg":"RS256","typ":"JWT"}.
{
"iss":"761326798069-r5mljlln1rd4lrbhg75efgigp36m78j5@developer.gserviceaccount.com",
"scope":"https://www.googleapis.com/auth/prediction",
"aud":"https://oauth2.googleapis.com/token",
"exp":1328554385,
"iat":1328550785
}.
[signature bytes]

לפניכם דוגמה של אסימון JWT שנחתם ומוכן להעברה:

eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiI3NjEzMjY3OTgwNjktcjVtbGpsbG4xcmQ0bHJiaGc3NWVmZ2lncDM2bTc4ajVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJzY29wZSI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL2F1dGgvcHJlZGljdGlvbiIsImF1ZCI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL29hdXRoMi92NC90b2tlbiIsImV4cCI6MTMyODU1NDM4NSwiaWF0IjoxMzI4NTUwNzg1fQ.UFUt59SUM2_AW4cRU8Y0BYVQsNTo4n7AFsNrqOpYiICDu37vVt-tw38UKzjmUKtcRsLLjrR3gFW3dNDMx_pL9DVjgVHDdYirtrCekUHOYoa1CMR66nxep5q5cBQ4y4u2kIgSvChCTc9pmLLNoIem-ruCecAJYgI9Ks7pTnW1gkOKs0x3YpiLpzplVHAkkHztaXiJdtpBcY1OXyo6jTQCa3Lk2Q3va1dPkh_d--GU2M5flgd8xNBPYw4vxyt0mP59XZlHMpztZt0soSgObf7G3GXArreF_6tpbFsS3z2t5zkEiHuWJXpzcYr5zWTRPDEHsejeBSG8EgpLDce2380ROQ

ביצוע הבקשה לאסימון הגישה

אחרי היצירה של ה-JWT החתום, אפליקציה יכולה להשתמש בו כדי לבקש אסימון גישה. הבקשה הזו לאסימון הגישה היא בקשת POST מסוג HTTPS, והגוף הוא כתובת URL באמצעות קידוד. כתובת ה-URL מוצגת למטה:

https://oauth2.googleapis.com/token

הפרמטרים הבאים נדרשים בבקשת POST מסוג HTTPS:

שם תיאור
grant_type משתמשים במחרוזת הבאה, בקידודי תווים שמתאימים לכתובות URL לפי הצורך: urn:ietf:params:oauth:grant-type:jwt-bearer
assertion ה-JWT, כולל החתימה.

בהמשך מופיעה תמונת מצב גולמית של בקשת POST מסוג HTTPS שבה נעשה שימוש באסימון גישה בקשה:

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

grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Ajwt-bearer&assertion=eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiI3NjEzMjY3OTgwNjktcjVtbGpsbG4xcmQ0bHJiaGc3NWVmZ2lncDM2bTc4ajVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJzY29wZSI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL2F1dGgvcHJlZGljdGlvbiIsImF1ZCI6Imh0dHBzOi8vYWNjb3VudHMuZ29vZ2xlLmNvbS9vL29hdXRoMi90b2tlbiIsImV4cCI6MTMyODU3MzM4MSwiaWF0IjoxMzI4NTY5NzgxfQ.ixOUGehweEVX_UKXv5BbbwVEdcz6AYS-6uQV6fGorGKrHf3LIJnyREw9evE-gs2bmMaQI5_UbabvI4k-mQE4kBqtmSpTzxYBL1TCd7Kv5nTZoUC1CmwmWCFqT9RE6D7XSgPUh_jF1qskLa2w0rxMSjwruNKbysgRNctZPln7cqQ

בהמשך מופיעה אותה בקשה, באמצעות curl:

curl -d 'grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Ajwt-bearer&assertion=eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiI3NjEzMjY3OTgwNjktcjVtbGpsbG4xcmQ0bHJiaGc3NWVmZ2lncDM2bTc4ajVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJzY29wZSI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL2F1dGgvcHJlZGljdGlvbiIsImF1ZCI6Imh0dHBzOi8vYWNjb3VudHMuZ29vZ2xlLmNvbS9vL29hdXRoMi90b2tlbiIsImV4cCI6MTMyODU3MzM4MSwiaWF0IjoxMzI4NTY5NzgxfQ.RZVpzWygMLuL-n3GwjW1_yhQhrqDacyvaXkuf8HcJl8EtXYjGjMaW5oiM5cgAaIorrqgYlp4DPF_GuncFqg9uDZrx7pMmCZ_yHfxhSCXru3gbXrZvAIicNQZMFxrEEn4REVuq7DjkTMyCMGCY1dpMa8aWfTQFt3Eh7smLchaZsU
' https://oauth2.googleapis.com/token

טיפול בתגובה

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

{
  "access_token": "1/8xbJqaOZXSUZbHLl5EOtu1pxz3fmmetKx9W8CV4t79M",
  "scope": "https://www.googleapis.com/auth/prediction"
  "token_type": "Bearer",
  "expires_in": 3600
}

אפשר לעשות שימוש חוזר באסימוני גישה במהלך חלון הזמן שצוין על ידי ערך של expires_in.

קריאה ל-Google APIs

Java

משתמשים באובייקט GoogleCredential כדי לקרוא ל-Google APIs. לשם כך מבצעים את הפעולות הבאות את השלבים הבאים:

  1. יוצרים אובייקט שירות ל-API שאליו רוצים לקרוא באמצעות אובייקט GoogleCredential. מוצרים לדוגמה:
    SQLAdmin sqladmin =
        new SQLAdmin.Builder(httpTransport, JSON_FACTORY, credential).build();
  2. שולחים בקשות לשירות ה-API באמצעות הממשק שסופק על ידי אובייקט השירות. לדוגמה, כדי להציג רשימה של המופעים של מסדי נתונים של Cloud SQL project:
    SQLAdmin.Instances.List instances =
        sqladmin.instances().list("exciting-example-123").execute();

Python

משתמשים באובייקט Credentials המורשה כדי לקרוא ל-Google APIs. לשם כך צריך להשלים את את השלבים הבאים:

  1. יוצרים אובייקט שירות ל-API שאליו רוצים לקרוא. פיתוח אובייקט שירות באמצעות קריאה לפונקציה build עם השם והגרסה של ה-API, אובייקט Credentials מורשה. לדוגמה, כדי לקרוא לגרסה 1beta3 של Cloud SQL Administration API:
    import googleapiclient.discovery
    
    sqladmin = googleapiclient.discovery.build('sqladmin', 'v1beta3', credentials=credentials)
  2. שולחים בקשות לשירות ה-API באמצעות הממשק שסופק על ידי אובייקט השירות. לדוגמה, כדי להציג רשימה של המופעים של מסדי נתונים של Cloud SQL project:
    response = sqladmin.instances().list(project='exciting-example-123').execute()

HTTP/REST

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

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

דוגמאות ל-HTTP GET

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

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

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

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

curl דוגמאות

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

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

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

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

כשהתוקף של אסימוני הגישה פג

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

קודי שגיאה של JWT

השדה error השדה error_description משמעות איך פותרים את הבעיה
unauthorized_client Unauthorized client or scope in request. אם ניסית להשתמש בהענקת גישה ברמת הדומיין, חשבון השירות לא מורשה מסוף Admin בדומיין של המשתמש.

מוודאים שחשבון השירות מורשה הדף 'הענקת גישה ברמת הדומיין במסוף Admin עבור המשתמש sub הצהרה (שדה).

בדרך כלל תהליך ההרשאה נמשך כמה דקות, אבל הוא עשוי להימשך עד 24 שעות להפיץ לכל המשתמשים בחשבון Google שלך.

unauthorized_client Client is unauthorized to retrieve access tokens using this method, or client not authorized for any of the scopes requested. חשבון שירות אושר באמצעות כתובת האימייל של הלקוח ולא באמצעות מזהה הלקוח (מספרי) במסוף Admin. ב בדף 'הענקת גישה ברמת הדומיין' במסוף Admin, מסירים את הלקוח ומוסיפים אותו מחדש עם המזהה המספרי.
access_denied (כל ערך) אם משתמשים בהענקת גישה ברמת הדומיין, אחד או יותר מההיקפים המבוקשים לא מורשים במסוף Admin.

מוודאים שחשבון השירות מורשה הדף 'הענקת גישה ברמת הדומיין במסוף Admin עבור המשתמש הצהרה sub (שדה), ושהיא כוללת את כל היקפי ההרשאות שביקשת בהצהרה scope של ה-JWT שלך.

בדרך כלל תהליך ההרשאה נמשך כמה דקות, אבל הוא עשוי להימשך עד 24 שעות להפיץ לכל המשתמשים בחשבון Google שלך.

admin_policy_enforced (כל ערך) חשבון Google לא יכול לתת הרשאה להיקף בקשה אחד או יותר, עקב של האדמין ב-Google Workspace.

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

invalid_client (כל ערך)

לקוח OAuth או אסימון JWT לא חוקי או שהוגדר באופן שגוי.

פרטים נוספים זמינים בתיאור השגיאה.

צריך לוודא שאסימון ה-JWT תקין ומכיל הצהרות נכונות.

בודקים שהלקוח וחשבון השירות ב-OAuth עומדים בתנאים. מוגדרת כראוי ושאתם משתמשים בכתובת האימייל הנכונה.

צריך לוודא שאסימון ה-JWT נכון ושהונפק עבור מזהה הלקוח ב בקשה.

invalid_grant Not a valid email. המשתמש לא קיים. צריך לוודא שכתובת האימייל שצוינה בהצהרה sub (בשדה) נכונה.
invalid_grant

Invalid JWT: Token must be a short-lived token (60 minutes) and in a reasonable timeframe. Check your 'iat' and 'exp' values and use a clock with skew to account for clock differences between systems.

בדרך כלל המשמעות היא ששעון המערכת המקומי שגוי. יכול להיות גם אם הערך של exp יהיה בעוד יותר מ-65 דקות בעתיד מהערך iat, או הערך exp נמוך מהערך של iat.

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

invalid_grant Invalid JWT Signature.

טענת הנכוֹנוּת (assertion) של ה-JWT חתומה באמצעות מפתח פרטי שלא משויך לחשבון השירות שמזוהה לפי האימייל של הלקוח או שהמפתח שנעשה בו שימוש נמחק, הושבת או פג תוקף.

לחלופין, טענת הנכוֹנוּת (assertion) של ה-JWT עשויה להיות מקודדת באופן שגוי – בקידוד Base64, ללא שורות חדשות או מרווח פנימי שווה.

מפענחים את קבוצת ההצהרה של JWT ומאמתים שהמפתח שחתום על טענת הנכוֹנוּת (assertion) משויך עם חשבון השירות.

כדאי לנסות להשתמש בספריית OAuth ש-Google מספקת כדי לוודא שה-JWT נוצר בצורה תקינה.

invalid_scope Invalid OAuth scope or ID token audience provided. לא נשלחו בקשות להיקפים (רשימה ריקה של היקפים), או שאחד מההיקפים המבוקשים לא קיים (כלומר, לא חוקי).

צריך לוודא שהשדה scope (השדה) של ה-JWT מאוכלס, ולהשוות אותו את היקפי ההרשאות שהוא מכיל, עם היקפי ההרשאות המתועדים של ממשקי ה-API שבהם אתם רוצים להשתמש, כדי ולוודא שאין שגיאות או שגיאות הקלדה.

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

disabled_client The OAuth client was disabled. המפתח שמשמש לחתימה על טענת הנכוֹנוּת (assertion) של JWT מושבת.

עוברים אל Google API Console, ובקטע IAM & Admin (אדמין) > חשבונות שירות, מפעילים את חשבון השירות שמכיל את 'מזהה מפתח'. בשימוש כדי לחתום על הטענה.

org_internal This client is restricted to users within its organization. מזהה הלקוח של OAuth שצוין בבקשה הוא חלק מפרויקט שמגביל את הגישה ל-Google חשבונות במסגרת ארגון ב-Google Cloud.

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

נספח: הרשאה באמצעות חשבון שירות ללא OAuth

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

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

  1. יוצרים חשבון שירות כמו שמתואר למעלה. חשוב לשמור את קובץ ה-JSON שקיבלתם כשיוצרים את החשבון.
  2. באמצעות ספריית JWT רגילה, כמו הספרייה שנמצאת בכתובת jwt.io, יצירת JWT עם כותרת ומטען ייעודי (payload), כמו בדוגמה הבאה:
    {
      "alg": "RS256",
      "typ": "JWT",
      "kid": "abcdef1234567890"
    }
    .
    {
      "iss": "123456-compute@developer.gserviceaccount.com",
      "sub": "123456-compute@developer.gserviceaccount.com",
      "aud": "https://firestore.googleapis.com/",
      "iat": 1511900000,
      "exp": 1511903600
    }
    • בשדה kid שבכותרת, מציינים את המפתח הפרטי של חשבון השירות ID. אפשר למצוא את הערך הזה בשדה private_key_id בחשבון השירות קובץ JSON.
    • בשדות iss ו-sub, צריך לציין את כתובת האימייל של חשבון השירות address. אפשר למצוא את הערך הזה בשדה client_email של השירות קובץ JSON של החשבון.
    • בשדה aud מציינים את נקודת הקצה ל-API. מוצרים לדוגמה: https://SERVICE.googleapis.com/
    • בשדה iat, מציינים את זמן ה-Unix הנוכחי. exp, מציינים את השעה בדיוק 3,600 שניות מאוחר יותר, שבו ה-JWT שפג תוקפן.

חותמים על ה-JWT עם RSA-256 באמצעות המפתח הפרטי שנמצא בקובץ JSON של חשבון השירות.

לדוגמה:

Java

באמצעות google-api-java-client וגם java-jwt:

GoogleCredential credential =
        GoogleCredential.fromStream(new FileInputStream("MyProject-1234.json"));
PrivateKey privateKey = credential.getServiceAccountPrivateKey();
String privateKeyId = credential.getServiceAccountPrivateKeyId();

long now = System.currentTimeMillis();

try {
    Algorithm algorithm = Algorithm.RSA256(null, privateKey);
    String signedJwt = JWT.create()
        .withKeyId(privateKeyId)
        .withIssuer("123456-compute@developer.gserviceaccount.com")
        .withSubject("123456-compute@developer.gserviceaccount.com")
        .withAudience("https://firestore.googleapis.com/")
        .withIssuedAt(new Date(now))
        .withExpiresAt(new Date(now + 3600 * 1000L))
        .sign(algorithm);
} catch ...

Python

באמצעות PyJWT:

iat = time.time()
exp = iat + 3600
payload = {'iss': '123456-compute@developer.gserviceaccount.com',
           'sub': '123456-compute@developer.gserviceaccount.com',
           'aud': 'https://firestore.googleapis.com/',
           'iat': iat,
           'exp': exp}
additional_headers = {'kid': PRIVATE_KEY_ID_FROM_JSON}
signed_jwt = jwt.encode(payload, PRIVATE_KEY_FROM_JSON, headers=additional_headers,
                       algorithm='RS256')
  1. קוראים ל-API תוך שימוש ב-JWT החתום כאסימון למוכ"ז:
    GET /v1/projects/abc/databases/123/indexes HTTP/1.1
    Authorization: Bearer SIGNED_JWT
    Host: firestore.googleapis.com

יישום הגנה על כל החשבונות

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

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

  • https://schemas.openid.net/secevent/risc/event-type/sessions-revoked
  • https://schemas.openid.net/secevent/oauth/event-type/token-revoked
  • https://schemas.openid.net/secevent/risc/event-type/account-disabled

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