מעבר אל Google Identity Services

סקירה כללית

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

במדריך הזה מפורטות הוראות להעברה מהספריות האלה לספרייה של Google Identity Services.

בעזרת המדריך הזה:

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

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

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

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

יש שני תהליכי הרשאה של משתמש: קוד הרשאה וקוד משתמע.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

כדי להוסיף את ספריית 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 שניתן לקרוא להן ממסמך Discovery, ואת קיבוץ הקריאות ל-API מרובות ואת פונקציונליות הניהול של CORS.

עוגיות

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

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

פרטי כניסה

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

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

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

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

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

שיטות

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

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

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

מצב הסשן

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

שיטות:

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

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

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

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

כניסת משתמש

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

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

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

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

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

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

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

בשיטה הישנה

ספריית לקוח 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 async/await

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

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

המשתמשים נדרשים ללחוץ על הלחצן 'Show Calendar' (הצגת היומן) אם אסימון הגישה חסר במהלך הטעינה הראשונה של הדף, או מאוחר יותר אחרי שהתוקף של אסימון הגישה פג.

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

בשיטה הישנה

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

כניסה באמצעות חשבון 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

בדוגמה הזו מוצגת רק ספריית ה-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

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

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

מה צריך לעשות כשעוברים ל-Identity Services:

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

התמצאות מהירה בספרייה

השוואה בין אובייקטים ושיטות בין ספריית לקוח JavaScript הישן עם כניסה באמצעות חשבון 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.OfflineAccessOptions הסרה
אובייקט gapi.auth2.SignInOptions הסרה
gapi.signin2 האובייקט והשיטות המשויכות:
gapi.signin2.render() הסרה. טעינת DOM של HTML של האלמנט g_id_signin או קריאה ל-JS אל google.accounts.id.renderButton גורמים לכניסת משתמש לחשבון Google.

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

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

ספריית הפלטפורמה לכניסה באמצעות חשבון Google, ספריית הלקוח של Google API עבור JavaScript או קריאות ישירות לנקודות הקצה של 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"
    }
  }