מערכת Google OAuth 2.0 תומכת באינטראקציות משרת-אל-שרת, כמו אלה שבין אפליקציית אינטרנט לבין שירות Google. במקרה הזה צריך חשבון שירות, שהוא חשבון ששייך לאפליקציה ולא למשתמש קצה ספציפי. האפליקציה שולחת קריאות ל-Google APIs בשם חשבון השירות, כך שהמשתמשים לא מעורבים באופן ישיר. התרחיש הזה נקרא לפעמים "OAuth עם שני רגליים" או "2LO". (המונח הקשור 'OAuth עם שלושה רגליים' מתייחס לתרחישים שבהם האפליקציה שלכם קוראת לממשקי Google API מטעם משתמשי קצה, ולתרחישים שבהם נדרשת הסכמת המשתמש).
בדרך כלל, אפליקציה משתמשת בחשבון שירות כשהיא משתמשת בממשקי Google API כדי לעבוד עם הנתונים שלה ולא עם נתוני משתמש. לדוגמה, אפליקציה שמשתמשת ב-Google Cloud Datastore כדי לשמור נתונים תשתמש בחשבון שירות כדי לאמת את הקריאות שלה ל-Google Cloud Datastore API.
אדמינים בדומיין 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. כדי ליצור פרטי כניסה לחשבון שירות או כדי לראות את פרטי הכניסה הציבוריים שכבר יצרתם, צריך לבצע את הפעולות הבאות:
ראשית, צור חשבון שירות:
- פתח את ה- Service accounts page.
- If prompted, select a project, or create a new one.
- לחץ על צור חשבון שירות .
- תחת פרטי חשבון שירות , הקלד שם, מזהה ותיאור עבור חשבון השירות ולאחר מכן לחץ על צור והמשך .
- אופציונלי: תחת הענק גישה לחשבון שירות זה לפרויקט , בחר את תפקידי IAM להעניק לחשבון השירות.
- לחץ על המשך .
- אופציונלי: תחת הענק למשתמשים גישה לחשבון שירות זה , הוסף את המשתמשים או הקבוצות המורשים להשתמש ולנהל את חשבון השירות.
- לחץ על סיום .
לאחר מכן, צור מפתח חשבון שירות:
- לחץ על כתובת הדוא"ל של חשבון השירות שיצרת.
- לחץ על הכרטיסייה מפתחות .
- ברשימה הנפתחת הוסף מפתח , בחר צור מפתח חדש .
- לחץ על צור .
זוג המפתחות הציבורי/פרטי החדש שלך נוצר ומוריד למחשב שלך; הוא משמש כעותק היחיד של המפתח הפרטי. אתה אחראי לאחסן אותו בצורה מאובטחת. אם תאבד את צמד המפתחות הזה, תצטרך ליצור אחד חדש.
תמיד אפשר לחזור אל API Console כדי לראות את כתובת האימייל, את טביעות האצבע של המפתחות הציבוריים ומידע נוסף, או כדי ליצור עוד צמדים של מפתחות ציבוריים/פרטיים. לפרטים נוספים על פרטי הכניסה של חשבון שירות ב- API Console, אפשר לעיין במאמר חשבונות שירות בקובץ העזרה של API Console.
רושמים את כתובת האימייל של חשבון השירות ושומרים את קובץ המפתח הפרטי של חשבון השירות במיקום שהאפליקציה יכולה לגשת אליו. האפליקציה שלכם צריכה אותם כדי לבצע קריאות מורשות ל-API.
הענקת הרשאה ברמת הדומיין לחשבון השירות
אדמינים ב-Workspace יכולים להשתמש בחשבון Google Workspace כדי לתת לאפליקציה הרשאה לגשת לנתוני משתמשים ב-Workspace בשם המשתמשים בדומיין Google Workspace. לדוגמה, אפליקציה שמשתמשת ב-Google Calendar API כדי להוסיף אירועים ליומנים של כל המשתמשים בדומיין Google Workspace, תשתמש בחשבון שירות כדי לגשת ל-Google Calendar API בשם המשתמשים. מתן הרשאה לחשבון שירות לגשת לנתונים בשם משתמשים בדומיין נקרא לפעמים "הענקת הרשאות גישה ברמת הדומיין" לחשבון שירות.
כדי להעניק הרשאות גישה ברמת הדומיין לחשבון שירות, סופר-אדמין בדומיין Google Workspace צריך לבצע את השלבים הבאים:
- ב מסוף Admin של הדומיין ב-Google Workspace, עוברים אל התפריט הראשי > אבטחה > שליטה בגישה ובנתונים > אמצעי בקרה של API.
- בחלונית Domain wide delegation (הענקת גישה ברמת הדומיין), בוחרים באפשרות Manage Domain Wide Delegation (ניהול של הענקת גישה ברמת הדומיין).
- לוחצים על הוספת חדש.
- בשדה Client ID (מזהה הלקוח), מזינים את מזהה הלקוח של חשבון השירות. אפשר למצוא את מזהה הלקוח של חשבון השירות ב- Service accounts page.
- בשדה היקפי הרשאות OAuth (מופרדים בפסיקים), מזינים את רשימת היקפי ההרשאות שהאפליקציה צריכה לקבל גישה אליהם. לדוגמה, אם לאפליקציה שלכם נדרשת גישה מלאה ל-Google Drive API ול-Google Calendar API בכל הדומיין, מזינים: https://www.googleapis.com/auth/drive, https://www.googleapis.com/auth/calendar.
- לוחצים על Authorize.
מעכשיו לאפליקציה יש הרשאה לשלוח קריאות ל-API בתור משתמשים בדומיין Workspace (כלומר, לבצע פעולות בשם המשתמשים). כשמתכוננים לבצע קריאות ל-API עם הרשאה, מציינים במפורש את המשתמש שרוצים להתחזות אליו.
הכנה לביצוע קריאה ל-API עם הרשאת גישה
Java
אחרי שמקבלים את כתובת האימייל של הלקוח ואת המפתח הפרטי מ- API Console, משתמשים ב-Google Auth Library for Java כדי ליצור אובייקט GoogleCredentials
מפרטי הכניסה של חשבון השירות ומאזורי ההרשאות שהאפליקציה צריכה לגשת אליהם. לדוגמה:
import com.google.auth.oauth2.GoogleCredentials; import com.google.api.services.sqladmin.SQLAdminScopes; // ... GoogleCredentials credentials = GoogleCredentials.fromStream(new FileInputStream("MyProject-1234.json")) .createScoped(Collections.singleton(SQLAdminScopes.SQLSERVICE_ADMIN));
אם אתם מפתחים אפליקציה ב-Google Cloud Platform, אתם יכולים להשתמש בפרטי כניסה שמוגדרים כברירת מחדל לאפליקציה במקום זאת, כדי לפשט את התהליך.
הענקת הרשאה ברמת הדומיין
אם הענקתם לחשבון השירות הרשאות גישה ברמת הדומיין ואתם רוצים להתחזות לחשבון משתמש, צריך לציין את כתובת האימייל של חשבון המשתמש באמצעות ה-method createDelegated
של האובייקט GoogleCredentials
. לדוגמה:
GoogleCredentials credentials = GoogleCredentials.fromStream(new FileInputStream("MyProject-1234.json")) .createScoped(Collections.singleton(SQLAdminScopes.SQLSERVICE_ADMIN)) .createDelegated("workspace-user@example.com");
הקוד שלמעלה משתמש באובייקט GoogleCredentials
כדי להפעיל את השיטה createDelegated()
שלו. הארגומנט של שיטת createDelegated()
חייב להיות משתמש ששייך לחשבון Workspace שלכם. הקוד ששולח את הבקשה ישתמש בפרטי הכניסה האלה כדי לקרוא ל-Google APIs באמצעות חשבון השירות שלכם.
Python
אחרי שמקבלים את כתובת האימייל של הלקוח ואת המפתח הפרטי מ- API Console, משתמשים בספריית הלקוח של Google APIs ל-Python כדי לבצע את השלבים הבאים:
- יוצרים אובייקט
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, אתם יכולים להשתמש בפרטי כניסה שמוגדרים כברירת מחדל לאפליקציה במקום זאת, כדי לפשט את התהליך.
- הענקת הרשאה ברמת הדומיין
אם הענקתם לחשבון השירות גישה ברמת הדומיין ואתם רוצים להתחזות לחשבון משתמש, אתם יכולים להשתמש בשיטה
with_subject
של אובייקטServiceAccountCredentials
קיים. לדוגמה:delegated_credentials = credentials.with_subject('user@example.org')
משתמשים באובייקט Credentials כדי לשלוח קריאות ל-Google APIs באפליקציה.
HTTP/REST
אחרי שמקבלים את מזהה הלקוח ואת המפתח הפרטי מ- API Console, האפליקציה צריכה לבצע את השלבים הבאים:
- יוצרים JSON Web Token (JWT, 'ג'וט') שכולל כותרת, קבוצת הצהרות וחתימה.
- שולחים בקשה לאסימון גישה משרת ההרשאות של Google OAuth 2.0.
- מטפלים בתגובת ה-JSON שמוחזרת משרת ההרשאות.
בקטעים הבאים מוסבר איך לבצע את השלבים האלה.
אם התגובה כוללת אסימון גישה, אפשר להשתמש באסימון הגישה כדי לקרוא ל-Google API. (אם התגובה לא כוללת אסימון גישה, יכול להיות ש-JWT ובקשת האסימון לא נוצרו בצורה תקינה, או שחשבון השירות לא קיבל הרשאה לגשת להיקפי ההרשאות המבוקשים).
כשתוקף אסימון הגישה פג, האפליקציה שלכם יוצרת עוד אסימון JWT, חותמת עליו ומבקשת עוד אסימון גישה.

בהמשך הקטע הזה מוסבר איך ליצור JWT, לחתום על JWT, ליצור את בקשת אסימון הגישה ולטפל בתגובה.
יצירת JWT
אסימון JWT מורכב משלושה חלקים: כותרת, קבוצת טענות וחתימה. הכותרת וקבוצת הטענות הם אובייקטים של JSON. אובייקטי ה-JSON האלה עוברים סריאליזציה לבייטים בפורמט UTF-8, ואז מקודדים באמצעות קידוד Base64url. הקידוד הזה מספק עמידות בפני שינויים בקידוד כתוצאה מפעולות קידוד חוזרות. הכותרת, קבוצת התלונות והחתימה מחוברים יחד באמצעות נקודה (.
).
מבנה של JWT:
{Base64url encoded header}.{Base64url encoded claim set}.{Base64url encoded signature}
מחרוזת הבסיס לחתימה היא:
{Base64url encoded header}.{Base64url encoded claim set}
יצירת כותרת ה-JWT
הכותרת מורכבת משלושה שדות שמציינים את אלגוריתם החתימה, את הפורמט של הטענה ואת [מזהה המפתח של מפתח חשבון השירות](https://cloud.google.com/iam/docs/reference/rest/v1/projects.serviceAccounts.keys) ששימש לחתימה על ה-JWT. חובה לציין אלגוריתם ופורמט, ולכל שדה יכול להיות רק ערך אחד. ככל שנוסיף אלגוריתמים ופורמטים, הכותרת הזו תשתנה בהתאם. מזהה המפתח הוא אופציונלי, ואם מציינים מזהה מפתח שגוי, GCP ינסה לאמת את הטוקן באמצעות כל המפתחות שמשויכים לחשבון השירות, וידחה את הטוקן אם לא יימצא מפתח תקין. Google שומרת לעצמה את הזכות לדחות בעתיד טוקנים עם מזהי מפתח שגויים.
חשבונות שירות מסתמכים על אלגוריתם RSA SHA-256 ועל פורמט אסימון JWT. כתוצאה מכך, ייצוג ה-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 |
זמן התפוגה של הטענה, שצוין בשניות מאז 00:00:00 UTC, 1 בינואר 1970. הערך הזה יכול להיות עד שעה אחרי שעת ההנפקה. |
iat |
השעה שבה הונפקת הטענה, שצוינה בשניות מאז 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. בהמשך מוצגת דוגמה לייצוג 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 עם פונקציית הגיבוב SHA-256) עם המפתח הפרטי שהתקבל מ Google API Console. הפלט יהיה מערך בייטים.
לאחר מכן צריך לקודד את החתימה בקידוד Base64url. הכותרת, קבוצת התלונות והחתימה מחוברים יחד באמצעות נקודה (.
). התוצאה היא ה-JWT. It
should be the following (line breaks added for clarity):
{Base64url encoded header}. {Base64url encoded claim set}. {Base64url encoded signature}
דוגמה ל-JWT לפני קידוד Base64url:
{"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 החתום, אפשר להשתמש בו באפליקציה כדי לבקש אסימון גישה.
בקשת האסימון לגישה היא בקשת HTTPS POST
, והגוף שלה מקודד בכתובת URL. כתובת ה-URL מוצגת בהמשך:
https://oauth2.googleapis.com/token
חובה לציין את הפרמטרים הבאים בבקשת ה-HTTPS POST
:
שם | תיאור |
---|---|
grant_type |
משתמשים במחרוזת הבאה, עם קידוד URL לפי הצורך:
urn:ietf:params:oauth:grant-type:jwt-bearer |
assertion |
אסימון ה-JWT, כולל החתימה. |
למטה מוצג dump גולמי של בקשת ה-HTTPS POST
שנעשה בה שימוש בבקשה של טוקן גישה:
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
כדי לקרוא לממשקי Google API באמצעות האובייקט GoogleCredentials
, צריך לבצע את השלבים הבאים:
- יוצרים אובייקט שירות עבור ה-API שרוצים להפעיל באמצעות האובייקט
GoogleCredentials
. לדוגמה:SQLAdmin sqladmin = new SQLAdmin.Builder(httpTransport, JSON_FACTORY, credentials).build();
- שולחים בקשות לשירות ה-API באמצעות הממשק שמסופק על ידי אובייקט השירות.
לדוגמה, כדי להציג את רשימת המכונות של מסדי נתונים ב-Cloud SQL בפרויקט exciting-example-123:
SQLAdmin.Instances.List instances = sqladmin.instances().list("exciting-example-123").execute();
Python
כדי להשתמש באובייקט המורשה Credentials
כדי לקרוא לממשקי Google API, צריך לבצע את השלבים הבאים:
- יוצרים אובייקט שירות עבור ה-API שרוצים להפעיל. יוצרים אובייקט שירות על ידי קריאה לפונקציה
build
עם השם והגרסה של ה-API והאובייקט המורשהCredentials
. לדוגמה, כדי להפעיל את גרסה 1beta3 של Cloud SQL Administration API:import googleapiclient.discovery sqladmin = googleapiclient.discovery.build('sqladmin', 'v1beta3', credentials=credentials)
- שולחים בקשות לשירות ה-API באמצעות הממשק שמסופק על ידי אובייקט השירות.
לדוגמה, כדי להציג את רשימת המכונות של מסדי נתונים ב-Cloud SQL בפרויקט exciting-example-123:
response = sqladmin.instances().list(project='exciting-example-123').execute()
HTTP/REST
אחרי שהאפליקציה מקבלת אסימון גישה, אפשר להשתמש באסימון כדי לבצע קריאות ל-Google API מטעם חשבון שירות או חשבון משתמש מסוים, אם הוענקו היקפי הגישה שנדרשים על ידי ה-API. כדי לעשות את זה, צריך לכלול את אסימון הגישה בבקשה ל-API באמצעות פרמטר access_token
של שאילתה או ערך של Authorization
כותרת HTTP Bearer
. כשניתן, עדיף להשתמש בכותרת HTTP, כי מחרוזות שאילתה נוטות להיות גלויות ביומני השרת. ברוב המקרים, אפשר להשתמש בספריית לקוח כדי להגדיר את הקריאות ל-Google APIs (לדוגמה, כשקוראים ל-Drive Files API).
אתם יכולים להתנסות בכל ממשקי Google APIs ולראות את היקפי ההרשאות שלהם ב-OAuth 2.0 Playground.
דוגמאות ל-HTTP GET
קריאה לנקודת הקצה
drive.files
(ה-API של קובצי Drive) באמצעות כותרת ה-HTTP Authorization: Bearer
עשויה להיראות כך: שימו לב: צריך לציין טוקן גישה משלכם:
GET /drive/v2/files HTTP/1.1 Host: www.googleapis.com Authorization: Bearer access_token
זוהי קריאה לאותו API עבור המשתמש המאומת באמצעות פרמטר מחרוזת השאילתה access_token
:
GET https://www.googleapis.com/drive/v2/files?access_token=access_token
curl
דוגמאות
אפשר לבדוק את הפקודות האלה באמצעות אפליקציית שורת הפקודה curl
. הנה דוגמה לשימוש באפשרות של כותרת HTTP (מומלץ):
curl -H "Authorization: Bearer access_token" https://www.googleapis.com/drive/v2/files
או לחלופין, האפשרות של פרמטר מחרוזת השאילתה:
curl https://www.googleapis.com/drive/v2/files?access_token=access_token
מתי פג התוקף של טוקנים של גישה
התוקף של אסימוני גישה שהונפקו על ידי שרת ההרשאות של Google OAuth 2.0 יפוג אחרי משך הזמן שמוגדר בערך expires_in
. כשפג התוקף של אסימון גישה, האפליקציה צריכה ליצור עוד JWT, לחתום עליו ולבקש עוד אסימון גישה.
קודי שגיאה של JWT
שדה error |
שדה error_description |
משמעות | איך פותרים את הבעיה |
---|---|---|---|
unauthorized_client |
Unauthorized client or scope in request. |
אם אתם מנסים להשתמש בהענקת הרשאות גישה ברמת הדומיין, חשבון השירות לא מורשה במסוף Admin של הדומיין של המשתמש. |
מוודאים שחשבון השירות מורשה בדף
הענקת הרשאות גישה ברמת הדומיין במסוף Admin עבור המשתמש בטענת (שדה) בדרך כלל האישור מתעדכן אצל כל המשתמשים בחשבון Google תוך כמה דקות, אבל יכול להיות שיחלפו עד 24 שעות. |
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 עבור המשתמש בטענת בדרך כלל האישור מתעדכן אצל כל המשתמשים בחשבון Google תוך כמה דקות, אבל יכול להיות שיחלפו עד 24 שעות. |
admin_policy_enforced |
(כל ערך) | לא ניתן לאשר את חשבון Google לאחת או יותר מההרשאות המבוקשות בגלל המדיניות של האדמין ב-Google Workspace. |
מידע נוסף על האופן שבו אדמין יכול להגביל את הגישה לכל היקפי ההרשאות או להיקפי הרשאות רגישים ומוגבלים עד למתן גישה מפורשת למזהה לקוח OAuth זמין במאמר שליטה בגישה של אפליקציות של צד שלישי ואפליקציות פנימיות לנתונים ב-Google Workspace במרכז העזרה לאדמינים של Google Workspace. |
invalid_client |
(כל ערך) |
לקוח OAuth או טוקן JWT לא תקינים או שההגדרה שלהם שגויה. פרטים נוספים מופיעים בתיאור השגיאה. |
מוודאים שטוקן ה-JWT תקף ומכיל הצהרות נכונות. צריך לוודא שלקוח OAuth וחשבון השירות מוגדרים בצורה נכונה ושאתם משתמשים בכתובת האימייל הנכונה. צריך לוודא שטוקן ה-JWT נכון והונפק עבור מזהה הלקוח בבקשה. |
deleted_client |
(כל ערך) |
לקוח ה-OAuth שמשמש לשליחת הבקשה נמחק. המחיקה יכולה להתבצע באופן ידני או אוטומטי במקרה של לקוחות שלא נעשה בהם שימוש . אפשר לשחזר לקוחות שנמחקו תוך 30 יום ממועד המחיקה. מידע נוסף |
משתמשים במזהה לקוח שעדיין פעיל. |
invalid_grant |
Not a valid email. |
המשתמש לא קיים. | בודקים שכתובת האימייל בsub הצהרה (שדה) נכונה. |
invalid_grant |
|
בדרך כלל, המשמעות היא שהשעה המקומית במערכת לא נכונה. זה יכול לקרות גם אם הערך של exp הוא יותר מ-65 דקות אחרי הערך של iat , או אם הערך של exp נמוך מהערך של iat . |
מוודאים שהשעון במערכת שבה נוצר ה-JWT נכון. אם צריך, מסנכרנים את השעה עם Google NTP. |
invalid_grant |
Invalid JWT Signature. |
הצהרת ה-JWT חתומה באמצעות מפתח פרטי שלא משויך לחשבון השירות שמזוהה באמצעות כתובת האימייל של הלקוח, או שהמפתח שבו נעשה שימוש נמחק, הושבת או שתוקפו פג. לחלופין, יכול להיות שטענת הנכוֹנוּת של JWT מקודדת בצורה שגויה – היא חייבת להיות בקידוד Base64, ללא שורות חדשות או סימני ריפוד של שוויון. |
מפענחים את קבוצת הטענות של ה-JWT ומוודאים שהמפתח שחתם על הטענה משויך לחשבון השירות. נסו להשתמש בספריית OAuth שסופקה על ידי Google כדי לוודא שטוקן ה-JWT נוצר בצורה נכונה. |
invalid_scope |
Invalid OAuth scope or ID token audience provided. |
לא נשלחה בקשה להיקפי הרשאות (רשימה ריקה של היקפי הרשאות), או שאחד מהיקפי ההרשאות המבוקשים לא קיים (כלומר, לא תקין). |
צריך לוודא שההצהרה (השדה) שימו לב: הרשימה של היקפי ההרשאות בטענה |
disabled_client |
The OAuth client was disabled. |
המפתח שמשמש לחתימה על טענת הנכוֹנוּת (assertion) של JWT מושבת. |
עוברים אל Google API Console, ובקטע IAM & Admin (ניהול זהויות והרשאות גישה) > Service Accounts (חשבונות שירות), מפעילים את חשבון השירות שמכיל את מזהה המפתח שמשמש לחתימה על הטענה. |
org_internal |
This client is restricted to users within its organization. |
מזהה לקוח OAuth בבקשה הוא חלק מפרויקט שמגביל את הגישה לחשבונות Google ב ארגון ספציפי ב-Google Cloud. |
משתמשים בחשבון שירות מהארגון כדי לבצע אימות. מאשרים את ההגדרה של סוג המשתמש באפליקציית OAuth. |
נספח: הרשאה באמצעות חשבון שירות ללא OAuth
בחלק מממשקי ה-API של Google, אפשר לבצע קריאות מורשות ל-API באמצעות JWT חתום ישירות כאסימון bearer, במקום כאסימון גישה מסוג OAuth 2.0. כשזה אפשרי, אתם יכולים להימנע משליחת בקשה ברשת לשרת ההרשאות של Google לפני ביצוע קריאה ל-API.
אם ל-API שאליו רוצים להתקשר יש הגדרת שירות שפורסמה במאגר Google APIs ב-GitHub, אפשר לבצע קריאות מורשות ל-API באמצעות JWT במקום אסימון גישה. לשם כך:
- יוצרים חשבון שירות כמו שמתואר למעלה. חשוב לשמור את קובץ ה-JSON שמקבלים כשיוצרים את החשבון.
- באמצעות ספריית 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
בכותרת, מציינים את המזהה של המפתח הפרטי של חשבון השירות. אפשר למצוא את הערך הזה בשדהprivate_key_id
בקובץ ה-JSON של חשבון השירות. - בשדות
iss
ו-sub
, מציינים את כתובת האימייל של חשבון השירות. אפשר למצוא את הערך הזה בשדהclient_email
בקובץ ה-JSON של חשבון השירות. - בשדה
aud
, מציינים את נקודת הקצה של ה-API. לדוגמה:https://SERVICE.googleapis.com/
. - בשדה
iat
מציינים את חותמת הזמן הנוכחית של מערכת Unix, ובשדהexp
מציינים את השעה בדיוק 3,600 שניות מאוחר יותר, שבה יפוג תוקף ה-JWT.
חותמים על ה-JWT באמצעות RSA-256 עם המפתח הפרטי שנמצא בקובץ ה-JSON של חשבון השירות.
לדוגמה:
Java
שימוש ב-google-auth-library-java וב-java-jwt:
import com.google.auth.oauth2.ServiceAccountCredentials; ... GoogleCredentials credentials = GoogleCredentials.fromStream(new FileInputStream("MyProject-1234.json")); PrivateKey privateKey = ((ServiceAccountCredentials) credentials).getPrivateKey(); String privateKeyId = ((ServiceAccountCredentials) credentials).getPrivateKeyId(); 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')
- קוראים ל-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
מידע נוסף על הטמעה של הגנה על כל החשבונות ורשימה מלאה של האירועים הזמינים מופיע במאמר הגנה על חשבונות משתמשים באמצעות הגנה על כל החשבונות .