מעבר אל 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.

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

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

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

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

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

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

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

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

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

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

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

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

עוגיות

להרשאת המשתמש לא נדרש שימוש בקובצי Cookie.

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

פרטי כניסה

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

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

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

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

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

שיטות

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

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

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

מצב הסשן

בעבר, הכניסה באמצעות חשבון 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 Sign-In ב-Google Identity Services:

אובייקטים:

  • 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 Sign-In: ב-Google Identity Services:

שיטות:

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

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

מעדכנים את קוד המקור כך:

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

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

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

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

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

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

טיפול בטוקנים

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

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

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

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

ביטול אסימון

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

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

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

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

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

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

מחליפים את ההפניות ללקוח JavaScript של Google Sign-In ב-Google Identity Services:

אובייקטים:

  • 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() לפי הדוגמה הזו להרשאות מפורטות.

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

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

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

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

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

הדרך הישנה

ספריית הלקוח של 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.

Promises, ‏ async ו-await משמשים לאכיפת סדר טעינת הספריות ולתפיסת שגיאות הרשאה ולניסיון חוזר. קריאה ל-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 Services יכול להשתמש בהפניה אוטומטית של כתובת URL כדי להחזיר קוד הרשאה ישירות לנקודת הקצה של אסימון הקצה העורפי, או בטיפול בקריאה חוזרת (callback) של 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 חלון קופץ UX

בדוגמה הזו מוצגת רק ספריית JavaScript של Google Identity Service באמצעות מודל של קוד הרשאה, תיבת דו-שיח קופצת לקבלת הסכמה מהמשתמש ומטפל בקריאה חוזרת (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 מוצג כאן:

<!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() הסרה. טעינת HTML DOM של הרכיב 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"
    }
  }