שימוש במודל האסימונים

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

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

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

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

Setup (הגדרה)

במדריך קבלת מזהה לקוח ב-Google API מוסבר איך למצוא או ליצור מזהה לקוח. לאחר מכן מוסיפים את ספריית הלקוח לדפים באתר שיבצעו קריאה ל-Google APIs. לבסוף, מאתחלים את לקוח האסימון. בדרך כלל, עושים זאת בתוך ה-handler של onload של ספריית הלקוח.

אתחול לקוח אסימון

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

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

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

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

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

הרשאה מצטברת

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

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

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

אייאקס

אפשר להוסיף תמיכה בהרשאה מצטברת לאפליקציה על ידי ביצוע קריאות מרובות אל 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();
          
עמוד 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
        ...
      }
    }
  },
});

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

עבודה עם אסימונים

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

שימוש ב-REST וב-CORS עם Google APIs

אפשר להשתמש באסימון גישה כדי לשלוח בקשות מאומתות לממשקי API של Google באמצעות 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();

מידע נוסף זמין במאמר איך להשתמש ב-CORS כדי לגשת ל-Google APIs.

בקטע הבא מוסבר איך לשלב בקלות ממשקי 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);
  });