שימוש במודל הטוקן

ספריית JavaScript‏ google.accounts.oauth2 עוזרת לכם לבקש הסכמה מהמשתמשים ולקבל אסימון גישה כדי לעבוד עם נתוני משתמשים. הוא מבוסס על תהליך ההרשאה המרומזת של OAuth 2.0 ומיועד לאפשר לכם לקרוא ל-Google APIs ישירות באמצעות REST ו-CORS, או להשתמש בספריית הלקוח של Google APIs ל-JavaScript (שנקראת גם gapi.client) כדי לקבל גישה גמישה ל-APIs המורכבים יותר שלנו.

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

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

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

דרישות מוקדמות

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

אתחול של לקוח טוקן

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

const client = google.accounts.oauth2.initTokenClient({
  client_id: 'YOUR_GOOGLE_CLIENT_ID',
  scope: 'https://www.googleapis.com/auth/calendar.readonly',
  callback: (response) => {
    ...
  },
});

הפעלת תהליך יצירת טוקן OAuth 2.0

משתמשים ב-method ‏requestAccessToken() כדי להפעיל את תהליך חוויית המשתמש של האסימון ולקבל אסימון גישה. ‫Google מבקשת מהמשתמש:

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

תנועה של המשתמש מפעילה את תהליך הטוקן:

<button onclick="client.requestAccessToken();">Authorize me</button>

לאחר מכן, Google מחזירה ל-callback handler שלכם TokenResponse שמכיל טוקן גישה ורשימה של היקפי הרשאות שהמשתמש העניק גישה אליהם, או שגיאה.

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

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

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

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

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

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

הרשאה מצטברת

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

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

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

Ajax

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

אפליקציית Ajax
מאתחלים את לקוח הטוקן בטעינת הדף:
        const client = google.accounts.oauth2.initTokenClient({
          client_id: 'YOUR_GOOGLE_CLIENT_ID',
          callback: "onTokenResponse",
        });
      
בקשת הסכמה וקבלת אסימוני גישה באמצעות פעולות של המשתמש, לוחצים על '+' כדי לפתוח:

מסמכים לקריאה

הצגת מסמכים אחרונים

          client.requestAccessToken(
            overrideConfig = ({
               scope = 'https://www.googleapis.com/auth/documents.readonly'
             })
           );
        

אירועים בזמן הקרוב

הצגת פרטי היומן

          client.requestAccessToken(
            overrideConfig = ({
               scope = 'https://www.googleapis.com/auth/calendar.readonly'
             })
           );
        

הצגת תמונות

          client.requestAccessToken(
            overrideConfig = ({
               scope = 'https://www.googleapis.com/auth/photoslibrary.readonly'
             })
           );
        

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

מספר דפי אינטרנט

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

אפליקציה מרובת דפים
דף אינטרנט קוד
עמוד 1. מסמכים לקריאה
  const client = google.accounts.oauth2.initTokenClient({
    client_id: 'YOUR_GOOGLE_CLIENT_ID',
    callback: "onTokenResponse",
    scope: 'https://www.googleapis.com/auth/documents.readonly',
  });
  client.requestAccessToken();
          
דף 2. אירועים בזמן הקרוב
  const client = google.accounts.oauth2.initTokenClient({
    client_id: 'YOUR_GOOGLE_CLIENT_ID',
    callback: "onTokenResponse",
    scope: 'https://www.googleapis.com/auth/calendar.readonly',
  });
  client.requestAccessToken();
          
Page 3. קרוסלת תמונות
  const client = google.accounts.oauth2.initTokenClient({
    client_id: 'YOUR_GOOGLE_CLIENT_ID',
    callback: "onTokenResponse",
    scope: 'https://www.googleapis.com/auth/photoslibrary.readonly',
  });
  client.requestAccessToken();
          

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

הרשאות פרטניות

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

const client = google.accounts.oauth2.initTokenClient({
  client_id: 'YOUR_GOOGLE_CLIENT_ID',
  scope: 'https://www.googleapis.com/auth/calendar.readonly \
          https://www.googleapis.com/auth/documents.readonly \
          https://www.googleapis.com/auth/photoslibrary.readonly',
  callback: (tokenResponse) => {
    if (tokenResponse && tokenResponse.access_token) {
      if (google.accounts.oauth2.hasGrantedAnyScope(tokenResponse,
          'https://www.googleapis.com/auth/photoslibrary.readonly')) {
        // Look at pictures
        ...
      }
      if (google.accounts.oauth2.hasGrantedAllScopes(tokenResponse,
          'https://www.googleapis.com/auth/calendar.readonly',
          'https://www.googleapis.com/auth/documents.readonly')) {
        // Meeting planning and review documents
        ...
      }
    }
  },
});

כל המענקים שאושרו בעבר מפגישות או מבקשות קודמות ייכללו גם הם בתשובה. תיעוד של הסכמת המשתמש נשמר לכל משתמש ומזהה לקוח, והוא נשמר בכמה קריאות ל-initTokenClient() או ל-requestAccessToken(). כברירת מחדל, הסכמת המשתמש נדרשת רק בפעם הראשונה שבה המשתמש נכנס לאתר שלכם ושולח בקשה להיקף חדש, אבל אפשר לבקש אותה בכל טעינת דף באמצעות prompt=consent באובייקטים של הגדרות לקוח של Token.

עבודה עם טוקנים

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

שימוש ב-REST וב-CORS עם ממשקי API של Google

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

בדוגמה הזו, מוצגים אירועים קרובים ביומן של המשתמשים המחוברים באמצעות אסימון הגישה שמוחזר על ידי tokenRequest():

var xhr = new XMLHttpRequest();
xhr.open('GET', 'https://www.googleapis.com/calendar/v3/calendars/primary/events');
xhr.setRequestHeader('Authorization', 'Bearer ' + tokenResponse.access_token);
xhr.send();

‫Google APIs תומך ב-CORS כברירת מחדל. שליחת טוקן גישה בבקשת XMLHttpRequest או fetch מפעילה בדיקת קדם-הפעלה של CORS, כלומר בקשת OPTIONS לפני בקשת GET או POST.

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

עבודה עם ספריית JavaScript של Google APIs

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

const client = google.accounts.oauth2.initTokenClient({
  client_id: 'YOUR_GOOGLE_CLIENT_ID',
  scope: 'https://www.googleapis.com/auth/calendar.readonly',
  callback: (tokenResponse) => {
    if (tokenResponse && tokenResponse.access_token) {
      gapi.client.setApiKey('YOUR_API_KEY');
      gapi.client.load('calendar', 'v3', listUpcomingEvents);
    }
  },
});

function listUpcomingEvents() {
  gapi.client.calendar.events.list(...);
}

תוקף הטוקן

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

כדי להסיר את הסכמת המשתמש ואת הגישה למשאבים לכל היקפי ההרשאות שניתנו לאפליקציה, צריך לקרוא למתודה google.accounts.oauth2.revoke. כדי לבטל את ההרשאה הזו, נדרש טוקן גישה תקין:

google.accounts.oauth2.revoke('414a76cb127a7ece7ee4bf287602ca2b56f8fcbf7fcecc2cd4e0509268120bd7', done => {
    console.log(done);
    console.log(done.successful);
    console.log(done.error);
    console.log(done.error_description);
  });