מעבר אל Google Identity Services

סקירה כללית

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

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

בעזרת המדריך הזה תוכלו:

  • להחליף את ספריית הפלטפורמה שהוצאה משימוש בספריית Identity Services, וגם
  • אם משתמשים בספריית הלקוח של API, מסירים את המודול gapi.auth2 שהוצא משימוש, את השיטות והאובייקטים שלה, ויחליפו אותם במקבילות של שירותי זהות.

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

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

זיהוי תהליך ההרשאה

יש שני תהליכי הרשאה אפשריים: הענקת הרשאה משתמעת והרשאה

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

סימנים שאפליקציית האינטרנט משתמשת בהם בזרם הענקת גישה משתמע:

  • אפליקציית האינטרנט מבוססת רק על דפדפן, ללא פלטפורמה לקצה העורפי.
  • המשתמש חייב להיות נוכח כדי להפעיל את Google APIs. האפליקציה משתמשת בהרשאת גישה בלבד ולא נדרשים אסימוני רענון.
  • אפליקציית האינטרנט שלך טוענת את apis.google.com/js/api.js.
  • ההטמעה מבוססת על OAuth 2.0 לאינטרנט בצד הלקוח אפליקציות.
  • האפליקציה שלך משתמשת במודולים gapi.client או gapi.auth2 שנמצאים ב- ספריית הלקוח של Google API ל-JavaScript.

סימנים שאפליקציית האינטרנט משתמשת בהם בתהליך קוד ההרשאה:

  • ההטמעה מבוססת על:

  • האפליקציה מופעלת גם בדפדפן של המשתמש וגם בפלטפורמת הקצה העורפי.

  • פלטפורמת הקצה העורפי מארחת נקודת קצה (endpoint) של קוד הרשאה.

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

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

במקרים מסוימים, ה-codebase עשוי לתמוך בשני התהליכים.

בחירת תהליך הרשאה

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

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

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

בוחרים תהליך הרשאה באמצעות הבוררים שבהמשך.

זרם הענקת גישה משתמע

קבלת אסימון גישה לשימוש בדפדפן בזמן שהמשתמש נמצא.

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

תהליך הרשאה באמצעות קוד

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

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

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

שינויים באפליקציית האינטרנט בדפדפן

בקטע הזה מתוארים השינויים שיתבצעו באפליקציית האינטרנט בדפדפן כאשר העברה לספריית ה-JavaScript של Google Identity Services.

זיהוי הקוד המושפע ובדיקה

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

באפליקציות גדולות או מורכבות, ייתכן שתתקשו למצוא את כל הקוד המושפע הוצאה משימוש של המודול gapi.auth2. כדי לתעד שימוש קיים ב- בקרוב שהוצאה משימוש במסוף, להגדיר את הערך קובץ Cookie של G_AUTH2_MIGRATION אל informational. (אופציונלי) מוסיפים נקודתיים ואחריהם לפי ערך מפתח, כדי לתעד גם את האחסון של הסשן. אחרי הכניסה לחשבון וקבלת פרטי כניסה, או שליחת יומנים שנאספו לקצה עורפי למועד מאוחר יותר. את הניתוח. לדוגמה, הפקודה informational:showauth2use שומרת את המקור ואת כתובת ה-URL ב מפתח אחסון לסשן בשם showauth2use.

כדי לאמת את התנהגות האפליקציה כשהמודול gapi.auth2 לא נטען יותר, יש להגדיר את של קובץ ה-cookie G_AUTH2_MIGRATION ל-enforced. כך אפשר לבצע בדיקה של התנהגות לאחר ההוצאה משימוש לפני תאריך האכיפה.

ערכים אפשריים של קובצי cookie מסוג G_AUTH2_MIGRATION:

  • enforced אין לטעון את המודול gapi.auth2.
  • informational לרשום במסוף JS שימוש בפונקציונליות שהוצאה משימוש. אני רוצה גם ביומן לאחסון סשנים, כשמוגדר שם מפתח אופציונלי: informational:key-name

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

ספריות ומודולים

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

להוסיף את ספריית שירותי הזהויות לאפליקציית האינטרנט שלכם. לשם כך, צריך לכלול אותה מסמך:

<script src="https://accounts.google.com/gsi/client" async defer></script>

מסירים מופעים של טעינת המודול auth2 באמצעות gapi.load('auth2', function).

ספריית Google Identity Services מחליפה את השימוש במודול gapi.auth2. אפשר להמשיך להשתמש במודול gapi.client בבטחה מ-Google API ספריית לקוח ל-JavaScript, ותוכלו להפיק ממנה תועלת של שיטות JS שניתן לקרוא להן ממסמך גילוי, באצווה של קריאות מרובות ל-API, ופונקציונליות של ניהול CORS.

עוגיות

הרשאת המשתמש לא מחייבת שימוש בקובצי cookie.

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

פרטי כניסה

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

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

זרם הענקת גישה משתמע

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

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

שיטות

  • GoogleUser.getBasicProfile()
  • GoogleUser.getId()

תהליך הרשאה באמצעות קוד

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

מצב הסשן

בעבר, התכונה 'כניסה באמצעות חשבון Google' עזרה לכם לנהל את סטטוס ההתחברות של המשתמשים באמצעות:

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

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

אובייקטים:

  • gapi.auth2.SignInOptions

שיטות:

  • GoogleAuth.attachClickHandler()
  • GoogleAuth.isSignedIn()
  • GoogleAuth.isSignedIn.get()
  • GoogleAuth.isSignedIn.listen()
  • GoogleAuth.signIn()
  • GoogleAuth.signOut()
  • GoogleAuth.currentUser.get()
  • GoogleAuth.currentUser.listen()
  • GoogleUser.isSignedIn()

הגדרת לקוח

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

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

אובייקטים:

  • gapi.auth2.ClientConfig
  • gapi.auth2.OfflineAccessOptions

שיטות:

  • gapi.auth2.getAuthInstance()
  • GoogleUser.grant()

זרם הענקת גישה משתמע

הוספת אובייקט TokenClientConfig וקריאה ל-initTokenClient() אל להגדיר את אפליקציית האינטרנט, לפי הדוגמה באתחול אסימון הלקוח.

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

אובייקטים:

  • gapi.auth2.AuthorizeConfig עם TokenClientConfig

שיטות:

  • gapi.auth2.init() עם google.accounts.oauth2.initTokenClient()

פרמטרים:

  • gapi.auth2.AuthorizeConfig.login_hint עם TokenClientConfig.login_hint.
  • gapi.auth2.GoogleUser.getHostedDomain() עם TokenClientConfig.hd.

תהליך הרשאה באמצעות קוד

מוסיפים אובייקט CodeClientConfig וקריאה ל-initCodeClient() להגדרה את אפליקציית האינטרנט שלכם, לפי הדוגמה באתחול לקוח קוד.

במעבר מזרם הענקת גישה משתמע לקוד הרשאה:

הסרת הפניות לקוח של JavaScript לכניסה באמצעות חשבון Google

אובייקטים:

  • gapi.auth2.AuthorizeConfig

שיטות:

  • gapi.auth2.init()

פרמטרים:

  • gapi.auth2.AuthorizeConfig.login_hint
  • gapi.auth2.GoogleUser.getHostedDomain()

בקשה לאסימון

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

זרם הענקת גישה משתמע

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

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

שיטות:

  • gapi.auth2.authorize() עם TokenClient.requestAccessToken()
  • GoogleUser.reloadAuthResponse() עם TokenClient.requestAccessToken()

יש להוסיף קישור או לחצן כדי להתקשר אל requestAccessToken() ולבצע את ההעברה חלון קופץ של חוויית המשתמש כדי לבקש אסימון גישה או לקבל אסימון חדש כאשר האסימון הקיים יפוג.

מעדכנים את ה-codebase ל:

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

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

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

תהליך הרשאה באמצעות קוד

כדאי להוסיף קישור או לחצן כדי להתקשר אל requestCode() ולבקש הרשאה מ-Google. ראו דוגמה במאמר Trigger OAuth 2.0 Code Flow.

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

טיפול באסימון

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

קוד מצב HTTP של 401 Unauthorized ו-invalid_token הוא הודעת שגיאה מוחזרים על ידי Google APIs כשמשתמשים באסימון גישה שפג תוקפו או שבוטל. עבור לדוגמה, ראה תגובה לא חוקית לא חוקית.

אסימונים שפג תוקפם

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

ביטול אסימון

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

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

שיטות:

  • getAuthInstance().disconnect() עם google.accounts.oauth2.revoke()
  • GoogleUser.disconnect() עם google.accounts.oauth2.revoke()

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

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

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

כניסה של משתמש

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

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

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

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

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

זרם הענקת גישה משתמע

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

אובייקטים:

  • gapi.auth2.AuthorizeResponse עם TokenClient.TokenResponse
  • gapi.auth2.AuthResponse עם TokenClient.TokenResponse

שיטות:

  • GoogleUser.hasGrantedScopes() עם google.accounts.oauth2.hasGrantedAllScopes()
  • GoogleUser.getGrantedScopes() עם google.accounts.oauth2.hasGrantedAllScopes()

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

שיטות:

  • GoogleUser.getAuthResponse()

עדכון אפליקציית האינטרנט בעזרת hasGrantedAllScopes() וגם hasGrantedAnyScope() בעזרת הדוגמה הזו של הרשאות מפורטות.

תהליך הרשאה באמצעות קוד

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

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

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

דוגמאות לזרימה משתמעת

הדרך הישנה

ספריית הלקוח של GAPI

דוגמה לספריית הלקוח של Google API ל-JavaScript פועלת בדפדפן באמצעות תיבת דו-שיח קופצת להסכמת המשתמש.

המודול gapi.auth2 נטען באופן אוטומטי ונמצא בשימוש על ידי gapi.client.init(), וכך הוא מוסתר.

<!DOCTYPE html>
  <html>
    <head>
      <script src="https://apis.google.com/js/api.js"></script>
      <script>
        function start() {
          gapi.client.init({
            'apiKey': 'YOUR_API_KEY',
            'clientId': 'YOUR_CLIENT_ID',
            'scope': 'https://www.googleapis.com/auth/cloud-translation',
            'discoveryDocs': ['https://www.googleapis.com/discovery/v1/apis/translate/v2/rest'],
          }).then(function() {
            // Execute an API request which is returned as a Promise.
            // The method name language.translations.list comes from the API discovery.
            return gapi.client.language.translations.list({
              q: 'hello world',
              source: 'en',
              target: 'de',
            });
          }).then(function(response) {
            console.log(response.result.data.translations[0].translatedText);
          }, function(reason) {
            console.log('Error: ' + reason.result.error.message);
          });
        };

        // Load the JavaScript client library and invoke start afterwards.
        gapi.load('client', start);
      </script>
    </head>
    <body>
      <div id="results"></div>
    </body>
  </html>

ספריית לקוח של JS

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

המודול gapi.auth2 נטען באופן ידני.

<!DOCTYPE html>
<html><head></head><body>
<script>
  var GoogleAuth;
  var SCOPE = 'https://www.googleapis.com/auth/drive.metadata.readonly';
  function handleClientLoad() {
    // Load the API's client and auth2 modules.
    // Call the initClient function after the modules load.
    gapi.load('client:auth2', initClient);
  }

  function initClient() {
    // In practice, your app can retrieve one or more discovery documents.
    var discoveryUrl = 'https://www.googleapis.com/discovery/v1/apis/drive/v3/rest';

    // Initialize the gapi.client object, which app uses to make API requests.
    // Get API key and client ID from API Console.
    // 'scope' field specifies space-delimited list of access scopes.
    gapi.client.init({
        'apiKey': 'YOUR_API_KEY',
        'clientId': 'YOUR_CLIENT_ID',
        'discoveryDocs': [discoveryUrl],
        'scope': SCOPE
    }).then(function () {
      GoogleAuth = gapi.auth2.getAuthInstance();

      // Listen for sign-in state changes.
      GoogleAuth.isSignedIn.listen(updateSigninStatus);

      // Handle initial sign-in state. (Determine if user is already signed in.)
      var user = GoogleAuth.currentUser.get();
      setSigninStatus();

      // Call handleAuthClick function when user clicks on
      //      "Sign In/Authorize" button.
      $('#sign-in-or-out-button').click(function() {
        handleAuthClick();
      });
      $('#revoke-access-button').click(function() {
        revokeAccess();
      });
    });
  }

  function handleAuthClick() {
    if (GoogleAuth.isSignedIn.get()) {
      // User is authorized and has clicked "Sign out" button.
      GoogleAuth.signOut();
    } else {
      // User is not signed in. Start Google auth flow.
      GoogleAuth.signIn();
    }
  }

  function revokeAccess() {
    GoogleAuth.disconnect();
  }

  function setSigninStatus() {
    var user = GoogleAuth.currentUser.get();
    var isAuthorized = user.hasGrantedScopes(SCOPE);
    if (isAuthorized) {
      $('#sign-in-or-out-button').html('Sign out');
      $('#revoke-access-button').css('display', 'inline-block');
      $('#auth-status').html('You are currently signed in and have granted ' +
          'access to this app.');
    } else {
      $('#sign-in-or-out-button').html('Sign In/Authorize');
      $('#revoke-access-button').css('display', 'none');
      $('#auth-status').html('You have not authorized this app or you are ' +
          'signed out.');
    }
  }

  function updateSigninStatus() {
    setSigninStatus();
  }
</script>

<button id="sign-in-or-out-button"
        style="margin-left: 25px">Sign In/Authorize</button>
<button id="revoke-access-button"
        style="display: none; margin-left: 25px">Revoke access</button>

<div id="auth-status" style="display: inline; padding-left: 25px"></div><hr>

<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
<script async defer src="https://apis.google.com/js/api.js"
        onload="this.onload=function(){};handleClientLoad()"
        onreadystatechange="if (this.readyState === 'complete') this.onload()">
</script>
</body></html>

נקודות קצה ב-OAuth 2.0

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

בדוגמה הזו מוצגות קריאות ישירות לנקודות הקצה מסוג OAuth 2.0 של Google בדפדפן של המשתמש ולא נעשה שימוש במודול gapi.auth2 או ב-JavaScript לספרייה.

<!DOCTYPE html>
<html><head></head><body>
<script>
  var YOUR_CLIENT_ID = 'REPLACE_THIS_VALUE';
  var YOUR_REDIRECT_URI = 'REPLACE_THIS_VALUE';
  var fragmentString = location.hash.substring(1);

  // Parse query string to see if page request is coming from OAuth 2.0 server.
  var params = {};
  var regex = /([^&=]+)=([^&]*)/g, m;
  while (m = regex.exec(fragmentString)) {
    params[decodeURIComponent(m[1])] = decodeURIComponent(m[2]);
  }
  if (Object.keys(params).length > 0) {
    localStorage.setItem('oauth2-test-params', JSON.stringify(params) );
    if (params['state'] && params['state'] == 'try_sample_request') {
      trySampleRequest();
    }
  }

  // If there's an access token, try an API request.
  // Otherwise, start OAuth 2.0 flow.
  function trySampleRequest() {
    var params = JSON.parse(localStorage.getItem('oauth2-test-params'));
    if (params && params['access_token']) {
      var xhr = new XMLHttpRequest();
      xhr.open('GET',
          'https://www.googleapis.com/drive/v3/about?fields=user&' +
          'access_token=' + params['access_token']);
      xhr.onreadystatechange = function (e) {
        if (xhr.readyState === 4 && xhr.status === 200) {
          console.log(xhr.response);
        } else if (xhr.readyState === 4 && xhr.status === 401) {
          // Token invalid, so prompt for user permission.
          oauth2SignIn();
        }
      };
      xhr.send(null);
    } else {
      oauth2SignIn();
    }
  }

  /*

    *   Create form to request access token from Google's OAuth 2.0 server.
 */
function oauth2SignIn() {
  // Google's OAuth 2.0 endpoint for requesting an access token
  var oauth2Endpoint = 'https://accounts.google.com/o/oauth2/v2/auth';

    // Create element to open OAuth 2.0 endpoint in new window.
    var form = document.createElement('form');
    form.setAttribute('method', 'GET'); // Send as a GET request.
    form.setAttribute('action', oauth2Endpoint);

    // Parameters to pass to OAuth 2.0 endpoint.
    var params = {'client_id': YOUR_CLIENT_ID,
                  'redirect_uri': YOUR_REDIRECT_URI,
                  'scope': 'https://www.googleapis.com/auth/drive.metadata.readonly',
                  'state': 'try_sample_request',
                  'include_granted_scopes': 'true',
                  'response_type': 'token'};

    // Add form parameters as hidden input values.
    for (var p in params) {
      var input = document.createElement('input');
      input.setAttribute('type', 'hidden');
      input.setAttribute('name', p);
      input.setAttribute('value', params[p]);
      form.appendChild(input);
    }

    // Add form to page and submit it to open the OAuth 2.0 endpoint.
    document.body.appendChild(form);
    form.submit();
  }
</script>

<button onclick="trySampleRequest();">Try sample request</button>
</body></html>

הדרך החדשה

GIS בלבד

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

<!DOCTYPE html>
<html>
  <head>
    <script src="https://accounts.google.com/gsi/client" onload="initClient()" async defer></script>
  </head>
  <body>
    <script>
      var client;
      var access_token;

      function initClient() {
        client = google.accounts.oauth2.initTokenClient({
          client_id: 'YOUR_CLIENT_ID',
          scope: 'https://www.googleapis.com/auth/calendar.readonly \
                  https://www.googleapis.com/auth/contacts.readonly',
          callback: (tokenResponse) => {
            access_token = tokenResponse.access_token;
          },
        });
      }
      function getToken() {
        client.requestAccessToken();
      }
      function revokeToken() {
        google.accounts.oauth2.revoke(access_token, () => {console.log('access token revoked')});
      }
      function loadCalendar() {
        var xhr = new XMLHttpRequest();
        xhr.open('GET', 'https://www.googleapis.com/calendar/v3/calendars/primary/events');
        xhr.setRequestHeader('Authorization', 'Bearer ' + access_token);
        xhr.send();
      }
    </script>
    <h1>Google Identity Services Authorization Token model</h1>
    <button onclick="getToken();">Get access token</button><br><br>
    <button onclick="loadCalendar();">Load Calendar</button><br><br>
    <button onclick="revokeToken();">Revoke token</button>
  </body>
</html>

אסינכרוני/בהמתנה של GAPI

בדוגמה זו ניתן לראות איך להוסיף את ספריית Google Identity Service באמצעות מודל אסימון, מסירים את המודול gapi.auth2 וקוראים ל-API באמצעות ספריית הלקוח של Google API ל-JavaScript.

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

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

<!DOCTYPE html>
<html>
<head></head>
<body>
  <h1>GAPI with GIS async/await</h1>
  <button id="showEventsBtn" onclick="showEvents();">Show Calendar</button><br><br>
  <button id="revokeBtn" onclick="revokeToken();">Revoke access token</button>

  <script>

    const gapiLoadPromise = new Promise((resolve, reject) => {
      gapiLoadOkay = resolve;
      gapiLoadFail = reject;
    });
    const gisLoadPromise = new Promise((resolve, reject) => {
      gisLoadOkay = resolve;
      gisLoadFail = reject;
    });

    var tokenClient;

    (async () => {
      document.getElementById("showEventsBtn").style.visibility="hidden";
      document.getElementById("revokeBtn").style.visibility="hidden";

      // First, load and initialize the gapi.client
      await gapiLoadPromise;
      await new Promise((resolve, reject) => {
        // NOTE: the 'auth2' module is no longer loaded.
        gapi.load('client', {callback: resolve, onerror: reject});
      });
      await gapi.client.init({
        // NOTE: OAuth2 'scope' and 'client_id' parameters have moved to initTokenClient().
      })
      .then(function() {  // Load the Calendar API discovery document.
        gapi.client.load('https://www.googleapis.com/discovery/v1/apis/calendar/v3/rest');
      });

      // Now load the GIS client
      await gisLoadPromise;
      await new Promise((resolve, reject) => {
        try {
          tokenClient = google.accounts.oauth2.initTokenClient({
              client_id: 'YOUR_CLIENT_ID',
              scope: 'https://www.googleapis.com/auth/calendar.readonly',
              prompt: 'consent',
              callback: '',  // defined at request time in await/promise scope.
          });
          resolve();
        } catch (err) {
          reject(err);
        }
      });

      document.getElementById("showEventsBtn").style.visibility="visible";
      document.getElementById("revokeBtn").style.visibility="visible";
    })();

    async function getToken(err) {

      if (err.result.error.code == 401 || (err.result.error.code == 403) &&
          (err.result.error.status == "PERMISSION_DENIED")) {

        // The access token is missing, invalid, or expired, prompt for user consent to obtain one.
        await new Promise((resolve, reject) => {
          try {
            // Settle this promise in the response callback for requestAccessToken()
            tokenClient.callback = (resp) => {
              if (resp.error !== undefined) {
                reject(resp);
              }
              // GIS has automatically updated gapi.client with the newly issued access token.
              console.log('gapi.client access token: ' + JSON.stringify(gapi.client.getToken()));
              resolve(resp);
            };
            tokenClient.requestAccessToken();
          } catch (err) {
            console.log(err)
          }
        });
      } else {
        // Errors unrelated to authorization: server errors, exceeding quota, bad requests, and so on.
        throw new Error(err);
      }
    }

    function showEvents() {

      // Try to fetch a list of Calendar events. If a valid access token is needed,
      // prompt to obtain one and then retry the original request.
      gapi.client.calendar.events.list({ 'calendarId': 'primary' })
      .then(calendarAPIResponse => console.log(JSON.stringify(calendarAPIResponse)))
      .catch(err  => getToken(err))  // for authorization errors obtain an access token
      .then(retry => gapi.client.calendar.events.list({ 'calendarId': 'primary' }))
      .then(calendarAPIResponse => console.log(JSON.stringify(calendarAPIResponse)))
      .catch(err  => console.log(err)); // cancelled by user, timeout, etc.
    }

    function revokeToken() {
      let cred = gapi.client.getToken();
      if (cred !== null) {
        google.accounts.oauth2.revoke(cred.access_token, () => {console.log('Revoked: ' + cred.access_token)});
        gapi.client.setToken('');
      }
    }

  </script>

  <script async defer src="https://apis.google.com/js/api.js" onload="gapiLoadOkay()" onerror="gapiLoadFail(event)"></script>
  <script async defer src="https://accounts.google.com/gsi/client" onload="gisLoadOkay()" onerror="gisLoadFail(event)"></script>

</body>
</html>

קריאה חוזרת (callback) של GAPI

בדוגמה זו ניתן לראות איך להוסיף את ספריית Google Identity Service באמצעות מודל אסימון, מסירים את המודול gapi.auth2 וקוראים ל-API באמצעות ספריית הלקוח של Google API ל-JavaScript.

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

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

<!DOCTYPE html>
<html>
<head>
  <script async defer src="https://apis.google.com/js/api.js" onload="gapiLoad()"></script>
  <script async defer src="https://accounts.google.com/gsi/client" onload="gisInit()"></script>
</head>
<body>
  <h1>GAPI with GIS callbacks</h1>
  <button id="showEventsBtn" onclick="showEvents();">Show Calendar</button><br><br>
  <button id="revokeBtn" onclick="revokeToken();">Revoke access token</button>
  <script>
    let tokenClient;
    let gapiInited;
    let gisInited;

    document.getElementById("showEventsBtn").style.visibility="hidden";
    document.getElementById("revokeBtn").style.visibility="hidden";

    function checkBeforeStart() {
       if (gapiInited && gisInited){
          // Start only when both gapi and gis are initialized.
          document.getElementById("showEventsBtn").style.visibility="visible";
          document.getElementById("revokeBtn").style.visibility="visible";
       }
    }

    function gapiInit() {
      gapi.client.init({
        // NOTE: OAuth2 'scope' and 'client_id' parameters have moved to initTokenClient().
      })
      .then(function() {  // Load the Calendar API discovery document.
        gapi.client.load('https://www.googleapis.com/discovery/v1/apis/calendar/v3/rest');
        gapiInited = true;
        checkBeforeStart();
      });
    }

    function gapiLoad() {
        gapi.load('client', gapiInit)
    }

    function gisInit() {
     tokenClient = google.accounts.oauth2.initTokenClient({
                client_id: 'YOUR_CLIENT_ID',
                scope: 'https://www.googleapis.com/auth/calendar.readonly',
                callback: '',  // defined at request time
            });
      gisInited = true;
      checkBeforeStart();
    }

    function showEvents() {

      tokenClient.callback = (resp) => {
        if (resp.error !== undefined) {
          throw(resp);
        }
        // GIS has automatically updated gapi.client with the newly issued access token.
        console.log('gapi.client access token: ' + JSON.stringify(gapi.client.getToken()));

        gapi.client.calendar.events.list({ 'calendarId': 'primary' })
        .then(calendarAPIResponse => console.log(JSON.stringify(calendarAPIResponse)))
        .catch(err => console.log(err));

        document.getElementById("showEventsBtn").innerText = "Refresh Calendar";
      }

      // Conditionally ask users to select the Google Account they'd like to use,
      // and explicitly obtain their consent to fetch their Calendar.
      // NOTE: To request an access token a user gesture is necessary.
      if (gapi.client.getToken() === null) {
        // Prompt the user to select a Google Account and asked for consent to share their data
        // when establishing a new session.
        tokenClient.requestAccessToken({prompt: 'consent'});
      } else {
        // Skip display of account chooser and consent dialog for an existing session.
        tokenClient.requestAccessToken({prompt: ''});
      }
    }

    function revokeToken() {
      let cred = gapi.client.getToken();
      if (cred !== null) {
        google.accounts.oauth2.revoke(cred.access_token, () => {console.log('Revoked: ' + cred.access_token)});
        gapi.client.setToken('');
        document.getElementById("showEventsBtn").innerText = "Show Calendar";
      }
    }
  </script>
</body>
</html>

דוגמאות לתהליך של קוד הרשאה

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

הדרך הישנה

אפליקציות אינטרנט בצד השרת

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

<!DOCTYPE html>
<html>
  <head>
    <script src="//ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js"></script>
    <script src="https://apis.google.com/js/client:platform.js?onload=start" async defer></script>
    <script>
      function start() {
        gapi.load('auth2', function() {
          auth2 = gapi.auth2.init({
            client_id: 'YOUR_CLIENT_ID',
            api_key: 'YOUR_API_KEY',
            discovery_docs: ['https://www.googleapis.com/discovery/v1/apis/translate/v2/rest'],
            // Scopes to request in addition to 'profile' and 'email'
            scope: 'https://www.googleapis.com/auth/cloud-translation',
          });
        });
      }
      function signInCallback(authResult) {
        if (authResult['code']) {
          console.log("sending AJAX request");
          // Send authorization code obtained from Google to backend platform
          $.ajax({
            type: 'POST',
            url: 'YOUR_AUTHORIZATION_CODE_ENDPOINT_URL',
            // Always include an X-Requested-With header to protect against CSRF attacks.
            headers: {
              'X-Requested-With': 'XMLHttpRequest'
            },
            contentType: 'application/octet-stream; charset=utf-8',
            success: function(result) {
              console.log(result);
            },
            processData: false,
            data: authResult['code']
          });
        } else {
          console.log('error: failed to obtain authorization code')
        }
      }
    </script>
  </head>
  <body>
    <button id="signinButton">Sign In With Google</button>
    <script>
      $('#signinButton').click(function() {
        // Obtain an authorization code from Google
        auth2.grantOfflineAccess().then(signInCallback);
      });
    </script>
  </body>
</html>

HTTP/REST עם הפניה אוטומטית

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

/\*
 \* Create form to request access token from Google's OAuth 2.0 server.
 \*/
function oauthSignIn() {
  // Google's OAuth 2.0 endpoint for requesting an access token
  var oauth2Endpoint = 'https://accounts.google.com/o/oauth2/v2/auth';
  // Create &lt;form> element to submit parameters to OAuth 2.0 endpoint.
  var form = document.createElement('form');
  form.setAttribute('method', 'GET'); // Send as a GET request.
  form.setAttribute('action', oauth2Endpoint);
  // Parameters to pass to OAuth 2.0 endpoint.
  var params = {'client\_id': 'YOUR_CLIENT_ID',
                'redirect\_uri': 'YOUR_AUTHORIZATION_CODE_ENDPOINT_URL',
                'response\_type': 'token',
                'scope': 'https://www.googleapis.com/auth/drive.metadata.readonly',
                'include\_granted\_scopes': 'true',
                'state': 'pass-through value'};
  // Add form parameters as hidden input values.
  for (var p in params) {
    var input = document.createElement('input');
    input.setAttribute('type', 'hidden');
    input.setAttribute('name', p);
    input.setAttribute('value', params[p]);
    form.appendChild(input);
  }

  // Add form to page and submit it to open the OAuth 2.0 endpoint.
  document.body.appendChild(form);
  form.submit();
}

הדרך החדשה

GIS חלון קופץ UX

בדוגמה הזו מוצגת רק ספריית ה-JavaScript של Google Identity Service. באמצעות מודל קוד ההרשאה, תיבת דו-שיח קופצת להסכמת המשתמשים ה-handler של הקריאה החוזרת (callback) כדי לקבל את קוד ההרשאה מ-Google. זה כן שממחישה את מספר השלבים המינימלי שנדרש כדי להגדיר לקוח, לקבל הסכמה ולשלוח קוד הרשאה לקצה העורפי שלך הפלטפורמה.

<!DOCTYPE html>
<html>
  <head>
    <script src="https://accounts.google.com/gsi/client" onload="initClient()" async defer></script>
  </head>
  <body>
    <script>
      var client;
      function initClient() {
        client = google.accounts.oauth2.initCodeClient({
          client_id: 'YOUR_CLIENT_ID',
          scope: 'https://www.googleapis.com/auth/calendar.readonly',
          ux_mode: 'popup',
          callback: (response) => {
            var code_receiver_uri = 'YOUR_AUTHORIZATION_CODE_ENDPOINT_URI',
            // Send auth code to your backend platform
            const xhr = new XMLHttpRequest();
            xhr.open('POST', code_receiver_uri, true);
            xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
            xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
            xhr.onload = function() {
              console.log('Signed in as: ' + xhr.responseText);
            };
            xhr.send('code=' + response.code);
            // After receipt, the code is exchanged for an access token and
            // refresh token, and the platform then updates this web app
            // running in user's browser with the requested calendar info.
          },
        });
      }
      function getAuthCode() {
        // Request authorization code and obtain user consent
        client.requestCode();
      }
    </script>
    <button onclick="getAuthCode();">Load Your Calendar</button>
  </body>
</html>

חוויית המשתמש להפניה מחדש של GIS

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

<!DOCTYPE html>
<html>
  <head>
    <script src="https://accounts.google.com/gsi/client" onload="initClient()" async defer></script>
  </head>
  <body>
    <script>
      var client;
      function initClient() {
        client = google.accounts.oauth2.initCodeClient({
          client_id: 'YOUR_CLIENT_ID',
          scope: 'https://www.googleapis.com/auth/calendar.readonly \
                  https://www.googleapis.com/auth/photoslibrary.readonly',
          ux_mode: 'redirect',
          redirect_uri: 'YOUR_AUTHORIZATION_CODE_ENDPOINT_URI'
        });
      }
      // Request an access token
      function getAuthCode() {
        // Request authorization code and obtain user consent
        client.requestCode();
      }
    </script>
    <button onclick="getAuthCode();">Load Your Calendar</button>
  </body>
</html>

ספריות JavaScript

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

פעולות שיש לבצע כשעוברים לשירותי זהויות:

ספריית JS קיימת ספריית JS חדשה הערות
apis.google.com/js/api.js accounts.google.com/gsi/client מוסיפים ספרייה חדשה ועוקבים אחר הזרימה המשתמעת.
apis.google.com/js/client.js accounts.google.com/gsi/client מוסיפים ספרייה חדשה ואת התהליך של קוד ההרשאה.

מדריך מקוצר לספרייה

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

ישן חדש הערות
אובייקט GoogleAuth והשיטות המשויכות אליו:
GoogleAuth.attachClickHandler() הסרה
GoogleAuth.currentUser.get() הסרה
GoogleAuth.currentUser.listen() הסרה
GoogleAuth.disconnect() google.accounts.oauth2.revoke מחליפים את הישן בחדש. תהליך הביטול עשוי להתבצע גם בכתובת https://myaccount.google.com/permissions.
GoogleAuth.grantOfflineAccess() מסירים אותו, ופועלים לפי התהליך של קוד ההרשאה.
GoogleAuth.isSignedIn.get() הסרה
GoogleAuth.isSignedIn.listen() הסרה
GoogleAuth.signIn() הסרה
GoogleAuth.signOut() הסרה
GoogleAuth.then() הסרה
אובייקט GoogleUser והשיטות המשויכות אליו:
GoogleUser.disconnect() google.accounts.id.revoke מחליפים את הישן בחדש. תהליך הביטול עשוי להתבצע גם בכתובת https://myaccount.google.com/permissions.
GoogleUser.getAuthResponse() requestCode() or requestAccessToken() החלפה של הישן בחדש
GoogleUser.getBasicProfile() הסרה. במקום זאת, אפשר להשתמש באסימון המזהה במאמר מעבר מכניסה באמצעות חשבון Google.
GoogleUser.getGrantedScopes() hasGrantedAnyScope() החלפה של הישן בחדש
GoogleUser.getHostedDomain() הסרה
GoogleUser.getId() הסרה
GoogleUser.grantOfflineAccess() מסירים אותו, ופועלים לפי התהליך של קוד ההרשאה.
GoogleUser.grant() הסרה
GoogleUser.hasGrantedScopes() hasGrantedAnyScope() החלפה של הישן בחדש
GoogleUser.isSignedIn() הסרה
GoogleUser.reloadAuthResponse() requestAccessToken() צריך להסיר את אסימון הגישה הישן ('קריאה חדשה') כדי להחליף את אסימון הגישה שתוקפו פג או בוטל.
האובייקט gapi.auth2 והשיטות המשויכות אליו:
אובייקט gapi.auth2.AuthorizeConfig TokenClientConfig או CodeClientConfig החלפה של הישן בחדש
אובייקט gapi.auth2.AuthorizeResponse הסרה
אובייקט gapi.auth2.AuthResponse הסרה
gapi.auth2.authorize() requestCode() or requestAccessToken() החלפה של הישן בחדש
gapi.auth2.ClientConfig() TokenClientConfig או CodeClientConfig החלפה של הישן בחדש
gapi.auth2.getAuthInstance() הסרה
gapi.auth2.init() initTokenClient() or initCodeClient() החלפה של הישן בחדש
אובייקט gapi.auth2.אופלייןAccessOptions הסרה
אובייקט gapi.auth2.SignInOptions הסרה
אובייקט gapi.signin2 ובשיטות המשויכות:
gapi.signin2.render() הסרה. טעינת DOM של HTML g_id_signin או קריאה ל-JS אל google.accounts.id.renderButton מפעיל את האפשרות להיכנס לחשבון Google.

פרטי כניסה לדוגמה

פרטי הכניסה הקיימים

ספריית הפלטפורמה של 'כניסה באמצעות חשבון Google', ספריית הלקוח של Google API עבור JavaScript, או קריאות ישירות לנקודות קצה (endpoints) של Google Auth 2.0 גם אסימון גישה מסוג OAuth 2.0 וגם אסימון מזהה של OpenID Connect תשובה.

דוגמה לתשובה שמכילה גם את access_token וגם את id_token:

  {
    "token_type": "Bearer",
    "access_token": "ya29.A0ARrdaM-SmArZaCIh68qXsZSzyeU-8mxhQERHrP2EXtxpUuZ-3oW8IW7a6D2J6lRnZrRj8S6-ZcIl5XVEqnqxq5fuMeDDH_6MZgQ5dgP7moY-yTiKR5kdPm-LkuPM-mOtUsylWPd1wpRmvw_AGOZ1UUCa6UD5Hg",
    "scope": "https://www.googleapis.com/auth/calendar.readonly",
    "login_hint": "AJDLj6I2d1RH77cgpe__DdEree1zxHjZJr4Q7yOisoumTZUmo5W2ZmVFHyAomUYzLkrluG-hqt4RnNxrPhArd5y6p8kzO0t8xIfMAe6yhztt6v2E-_Bb4Ec3GLFKikHSXNh5bI-gPrsI",
    "expires_in": 3599,
    "id_token": "eyJhbGciOiJSUzI1NiIsImtpZCI6IjkzNDFhYmM0MDkyYjZmYzAzOGU0MDNjOTEwMjJkZDNlNDQ1MzliNTYiLCJ0eXAiOiJKV1QifQ.eyJpc3MiOiJhY2NvdW50cy5nb29nbGUuY29tIiwiYXpwIjoiNTM4MzQ0NjUzMjU1LTc1OGM1aDVpc2M0NXZnazI3ZDhoOGRlYWJvdnBnNnRvLmFwcHMuZ29vZ2xldXNlcmNvbnRlbnQuY29tIiwiYXVkIjoiNTM4MzQ0NjUzMjU1LTc1OGM1aDVpc2M0NXZnazI3ZDhoOGRlYWJvdnBnNnRvLmFwcHMuZ29vZ2xldXNlcmNvbnRlbnQuY29tIiwic3ViIjoiMTE3NzI2NDMxNjUxOTQzNjk4NjAwIiwiaGQiOiJnb29nbGUuY29tIiwiZW1haWwiOiJkYWJyaWFuQGdvb2dsZS5jb20iLCJlbWFpbF92ZXJpZmllZCI6dHJ1ZSwiYXRfaGFzaCI6IkJBSW55TjN2MS1ZejNLQnJUMVo0ckEiLCJuYW1lIjoiQnJpYW4gRGF1Z2hlcnR5IiwicGljdHVyZSI6Imh0dHBzOi8vbGgzLmdvb2dsZXVzZXJjb250ZW50LmNvbS9hLS9BT2gxNEdnenAyTXNGRGZvbVdMX3VDemRYUWNzeVM3ZGtxTE5ybk90S0QzVXNRPXM5Ni1jIiwiZ2l2ZW5fbmFtZSI6IkJyaWFuIiwiZmFtaWx5X25hbWUiOiJEYXVnaGVydHkiLCJsb2NhbGUiOiJlbiIsImlhdCI6MTYzODk5MTYzOCwiZXhwIjoxNjM4OTk1MjM4LCJqdGkiOiI5YmRkZjE1YWFiNzE2ZDhjYmJmNDYwMmM1YWM3YzViN2VhMDQ5OTA5In0.K3EA-3Adw5HA7O8nJVCsX1HmGWxWzYk3P7ViVBb4H4BoT2-HIgxKlx1mi6jSxIUJGEekjw9MC-nL1B9Asgv1vXTMgoGaNna0UoEHYitySI23E5jaMkExkTSLtxI-ih2tJrA2ggfA9Ekj-JFiMc6MuJnwcfBTlsYWRcZOYVw3QpdTZ_VYfhUu-yERAElZCjaAyEXLtVQegRe-ymScra3r9S92TA33ylMb3WDTlfmDpWL0CDdDzby2asXYpl6GQ7SdSj64s49Yw6mdGELZn5WoJqG7Zr2KwIGXJuSxEo-wGbzxNK-mKAiABcFpYP4KHPEUgYyz3n9Vqn2Tfrgp-g65BQ",
    "session_state": {
      "extraQueryParams": {
        "authuser": "0"
      }
    },
    "first_issued_at": 1638991637982,
    "expires_at": 1638995236982,
    "idpId": "google"
  }

פרטי הכניסה ל-Google Identity Services

ספריית Google Identity Services מחזירה:

  • אסימון גישה שמשמש לצורך הרשאה:

    {
      "access_token": "ya29.A0ARrdaM_LWSO-uckLj7IJVNSfnUityT0Xj-UCCrGxFQdxmLiWuAosnAKMVQ2Z0LLqeZdeJii3TgULp6hR_PJxnInBOl8UoUwWoqsrGQ7-swxgy97E8_hnzfhrOWyQBmH6zs0_sUCzwzhEr_FAVqf92sZZHphr0g",
      "token_type": "Bearer",
      "expires_in": 3599,
      "scope": "https://www.googleapis.com/auth/calendar.readonly"
    }
    
  • או אסימון מזהה שמשמש לאימות:

    {
      "clientId": "538344653255-758c5h5isc45vgk27d8h8deabovpg6to.apps.googleusercontent.com",
      "credential": "eyJhbGciOiJSUzI1NiIsImtpZCI6ImMxODkyZWI0OWQ3ZWY5YWRmOGIyZTE0YzA1Y2EwZDAzMjcxNGEyMzciLCJ0eXAiOiJKV1QifQ.eyJpc3MiOiJodHRwczovL2FjY291bnRzLmdvb2dsZS5jb20iLCJuYmYiOjE2MzkxNTcyNjQsImF1ZCI6IjUzODM0NDY1MzI1NS03NThjNWg1aXNjNDV2Z2syN2Q4aDhkZWFib3ZwZzZ0by5hcHBzLmdvb2dsZXVzZXJjb250ZW50LmNvbSIsInN1YiI6IjExNzcyNjQzMTY1MTk0MzY5ODYwMCIsIm5vbmNlIjoiZm9vYmFyIiwiaGQiOiJnb29nbGUuY29tIiwiZW1haWwiOiJkYWJyaWFuQGdvb2dsZS5jb20iLCJlbWFpbF92ZXJpZmllZCI6dHJ1ZSwiYXpwIjoiNTM4MzQ0NjUzMjU1LTc1OGM1aDVpc2M0NXZnazI3ZDhoOGRlYWJvdnBnNnRvLmFwcHMuZ29vZ2xldXNlcmNvbnRlbnQuY29tIiwibmFtZSI6IkJyaWFuIERhdWdoZXJ0eSIsInBpY3R1cmUiOiJodHRwczovL2xoMy5nb29nbGV1c2VyY29udGVudC5jb20vYS0vQU9oMTRHZ3pwMk1zRkRmb21XTF91Q3pkWFFjc3lTN2RrcUxOcm5PdEtEM1VzUT1zOTYtYyIsImdpdmVuX25hbWUiOiJCcmlhbiIsImZhbWlseV9uYW1lIjoiRGF1Z2hlcnR5IiwiaWF0IjoxNjM5MTU3NTY0LCJleHAiOjE2MzkxNjExNjQsImp0aSI6IjRiOTVkYjAyZjU4NDczMmUxZGJkOTY2NWJiMWYzY2VhYzgyMmI0NjUifQ.Cr-AgMsLFeLurnqyGpw0hSomjOCU4S3cU669Hyi4VsbqnAV11zc_z73o6ahe9Nqc26kPVCNRGSqYrDZPfRyTnV6g1PIgc4Zvl-JBuy6O9HhClAK1HhMwh1FpgeYwXqrng1tifmuotuLQnZAiQJM73Gl-J_6s86Buo_1AIx5YAKCucYDUYYdXBIHLxrbALsA5W6pZCqqkMbqpTWteix-G5Q5T8LNsfqIu_uMBUGceqZWFJALhS9ieaDqoxhIqpx_89QAr1YlGu_UO6R6FYl0wDT-nzjyeF5tonSs3FHN0iNIiR3AMOHZu7KUwZaUdHg4eYkU-sQ01QNY_11keHROCRQ",
      "select_by": "user"
    }
    

תגובה לא חוקית לאסימון

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

כותרות של תגובת HTTP

  www-authenticate: Bearer realm="https://accounts.google.com/", error="invalid_token"

גוף התשובה

  {
    "error": {
      "code": 401,
      "message": "Request had invalid authentication credentials. Expected OAuth 2 access token, login cookie or other valid authentication credential. See https://developers.google.com/identity/sign-in/web/devconsole-project.",
      "errors": [
        {
          "message": "Invalid Credentials",
          "domain": "global",
          "reason": "authError",
          "location": "Authorization",
          "locationType": "header"
        }
      ],
      "status": "UNAUTHENTICATED"
    }
  }