OAuth 2.0 לאפליקציות אינטרנט בצד הלקוח

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

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

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

ספריית הלקוח של Google APIs ו-Google Identity Services

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

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

הפעלת ממשקי API בפרויקט

כל אפליקציה שקוראת ל-Google APIs צריכה להפעיל את ממשקי ה-API האלה ב- API Console.

כדי להפעיל API לפרויקט:

  1. Open the API Library ב Google API Console.
  2. If prompted, select a project, or create a new one.
  3. ב API Library מפורטים כל ממשקי ה-API הזמינים, מקובצים לפי משפחת המוצרים והפופולריות שלה. אם ממשק ה-API שרוצים להפעיל לא מופיע ברשימה, אפשר להשתמש בחיפוש כדי למצוא אותו או ללחוץ על הצגת הכול במשפחת המוצרים שאליה הוא שייך.
  4. בוחרים את ממשק ה-API שרוצים להפעיל ולוחצים על הלחצן הפעלה.
  5. If prompted, enable billing.
  6. If prompted, read and accept the API's Terms of Service.

יצירת פרטי כניסה להרשאה

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

  1. Go to the Credentials page.
  2. לוחצים על יצירת פרטי כניסה > מזהה לקוח OAuth.
  3. בוחרים את סוג האפליקציה אפליקציית אינטרנט.
  4. ממלאים את הטופס. באפליקציות שמשתמשות ב-JavaScript כדי לשלוח בקשות מורשות של Google API, חובה לציין מקורות JavaScript מורשים. המקורות מזהים את הדומיינים שמהם האפליקציה שלך יכולה לשלוח בקשות לשרת OAuth 2.0. המקורות האלה חייבים לעמוד בכללי האימות של Google.

זיהוי היקפי גישה

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

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

המסמך OAuth 2.0 API Scopes כולל רשימה מלאה של היקפים שתוכלו להשתמש בהם כדי לגשת ל-Google APIs.

קבלת אסימוני גישה מסוג OAuth 2.0

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

שלב 1: הפניה אוטומטית לשרת OAuth 2.0 של Google

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

נקודות קצה של OAuth 2.0

אפשר ליצור כתובת URL כדי לבקש גישה מנקודת הקצה של OAuth 2.0 של Google בכתובת https://accounts.google.com/o/oauth2/v2/auth. אפשר לגשת לנקודת הקצה הזו דרך HTTPS. חיבורי HTTP רגילים נדחות.

שרת ההרשאות של Google תומך בפרמטרים הבאים של מחרוזת שאילתה עבור אפליקציות של שרת אינטרנט:

פרמטרים
client_id חובה

מזהה הלקוח של האפליקציה. אפשר למצוא את הערך הזה ב Credentials page API Console.

redirect_uri חובה

המדיניות הזו קובעת לאן שרת ה-API יפנה את המשתמש אוטומטית אחרי שהוא סיים את תהליך ההרשאה. הערך חייב להתאים בדיוק לאחד ממזהי ה-URI המורשים להפניה אוטומטית בלקוח OAuth 2.0 שהגדרת ב- Credentials page API Console של הלקוח. אם הערך הזה לא תואם ל-URI מורשה להפניה אוטומטית עבור client_id שצוין, תתקבל הודעת השגיאה redirect_uri_mismatch.

לתשומת ליבך: התבנית http או https, האותיות הרישיות והקו הנטוי העוקב ('/') חייבים כולם להיות תואמים.

response_type חובה

אפליקציות JavaScript צריכות להגדיר את ערך הפרמטר הזה ל-token. הערך הזה מורה לשרת ההרשאות של Google להחזיר את אסימון הגישה כצמד name=value במזהה המקטע של ה-URI (#) שאליו המשתמש מופנה אחרי השלמת תהליך ההרשאה.

scope חובה

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

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

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

state מומלץ

המדיניות מציינת כל ערך מחרוזת שבו האפליקציה משתמשת כדי לשמור על המצב בין בקשת ההרשאה לבין התגובה של שרת ההרשאות. השרת מחזיר את הערך המדויק ששלחת בתור צמד name=value במזהה המקטע של כתובת ה-URL (#) של redirect_uri, אחרי שהמשתמש מסכים לבקשת הגישה של האפליקציה או דחה אותה.

אפשר להשתמש בפרמטר הזה לכמה מטרות, כמו הפניית המשתמש למשאב הנכון באפליקציה, שליחת חד-פעמיים חד-פעמיים וצמצום זיוף בקשות בין אתרים. מכיוון שאפשר לנחש את redirect_uri, שימוש בערך state יכול להגביר את הביטחון שחיבור נכנס הוא תוצאה של בקשת אימות. אם יוצרים מחרוזת אקראית או מקודדים גיבוב (hash) של קובץ cookie או של ערך אחר שמתעד את המצב של הלקוח, אפשר לאמת את התגובה כדי לוודא גם שהבקשה והתגובה הגיעו מאותו דפדפן, וכך לספק הגנה מפני מתקפות כמו זיוף בקשות בין אתרים. במסמכי התיעוד של OpenID Connect אפשר לראות דוגמה ליצירה ולאישור של אסימון state.

include_granted_scopes אופציונלי

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

login_hint אופציונלי

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

מגדירים את ערך הפרמטר לכתובת אימייל או למזהה sub, שזהה למזהה Google של המשתמש.

prompt אופציונלי

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

הערכים האפשריים הם:

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

דוגמה של הפניה אוטומטית לשרת ההרשאות של Google

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

https://accounts.google.com/o/oauth2/v2/auth?
 scope=https%3A//www.googleapis.com/auth/drive.metadata.readonly&
 include_granted_scopes=true&
 response_type=token&
 state=state_parameter_passthrough_value&
 redirect_uri=https%3A//oauth2.example.com/code&
 client_id=client_id

אחרי שיוצרים את כתובת ה-URL של הבקשה, יש להפנות את המשתמש אליה.

קוד לדוגמה של JavaScript

קטע הקוד של JavaScript הבא מראה איך להתחיל את תהליך ההרשאה ב-JavaScript בלי להשתמש בספריית הלקוח של Google APIs עבור JavaScript. נקודת הקצה (endpoint) הזו של OAuth 2.0 לא תומכת בשיתוף משאבים בין מקורות (CORS), ולכן קטע הקוד יוצר טופס שפותח את הבקשה לנקודת הקצה הזאת.

/*
 * 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 <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_REDIRECT_URI',
                '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();
}

שלב 2: Google מבקשת את הסכמת המשתמש

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

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

שגיאות

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

admin_policy_enforced

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

disallowed_useragent

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

Android

מפתחי Android עשויים להיתקל בהודעת השגיאה הזו כאשר הם פותחים בקשות הרשאה ב-android.webkit.WebView. במקום זאת, מפתחים צריכים להשתמש בספריות ל-Android, כמו כניסה באמצעות חשבון Google ל-Android או AppAuth ל-Android של OpenID Foundation.

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

iOS

מפתחים של iOS ו-macOS עשויים להיתקל בשגיאה הזו כשהם פותחים בקשות הרשאה ב-WKWebView. במקום זאת, מפתחים צריכים להשתמש בספריות ל-iOS, כמו כניסה באמצעות חשבון Google ל-iOS או AppAuth for iOS של OpenID Foundation.

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

org_internal

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

invalid_client

המקור שממנו נשלחה הבקשה לא מורשה עבור הלקוח הזה. למידע נוסף: origin_mismatch.

invalid_grant

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

origin_mismatch

הסכמה, הדומיין ו/או היציאה של ה-JavaScript שממנו הגיעה בקשת ההרשאה לא יכולים להתאים ל-URI מקור של JavaScript מורשה שרשום למזהה הלקוח של OAuth. יש לבדוק מקורות מורשים של JavaScript ב- Google API Console Credentials page.

redirect_uri_mismatch

הערך redirect_uri שהועבר בבקשת ההרשאה לא תואם ל-URI מורשה להפניה אוטומטית עבור מזהה הלקוח של OAuth. יש לבדוק מזהי URI מורשים להפניה אוטומטית ב- Google API Console Credentials page.

הסכמה, הדומיין ו/או היציאה של ה-JavaScript שממנו הגיעה בקשת ההרשאה לא יכולים להתאים ל-URI מקור של JavaScript מורשה שרשום למזהה הלקוח של OAuth. יש לבדוק מקורות מורשים של JavaScript ב- Google API Console Credentials page.

הפרמטר redirect_uri עשוי להתייחס לתהליך של OAuth מחוץ למסגרת (OOB) שהוצאה משימוש וכבר לא נתמכת. כדי לעדכן את השילוב, אפשר לעיין במדריך להעברת נתונים (מיגרציה).

invalid_request

משהו לא בסדר בבקשה ששלחת. יכולות להיות לכך כמה סיבות:

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

שלב 3: טיפול בתגובת שרת OAuth 2.0

נקודות קצה של OAuth 2.0

שרת OAuth 2.0 שולח תגובה ל-redirect_uri שצוין בבקשה של אסימון הגישה.

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

  • תגובה של אסימון גישה:

    https://oauth2.example.com/callback#access_token=4/P7q7W91&token_type=Bearer&expires_in=3600

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

  • הודעת שגיאה:
    https://oauth2.example.com/callback#error=access_denied

דוגמה לתגובת שרת OAuth 2.0

כדי לבדוק את התהליך, לוחצים על כתובת ה-URL לדוגמה הבאה, שמבקשת גישה לקריאה בלבד להצגת מטא-נתונים של קבצים ב-Google Drive:

https://accounts.google.com/o/oauth2/v2/auth?
 scope=https%3A//www.googleapis.com/auth/drive.metadata.readonly&
 include_granted_scopes=true&
 response_type=token&
 state=state_parameter_passthrough_value&
 redirect_uri=https%3A//oauth2.example.com/code&
 client_id=client_id

אחרי השלמת התהליך ב-OAuth 2.0, תתבצע הפניה אל http://localhost/oauth2callback. כתובת ה-URL הזו תוביל לשגיאה 404 NOT FOUND, אלא אם המכונה המקומית תציג קובץ בכתובת הזו. בשלב הבא יוצגו פרטים נוספים על המידע שמוצג ב-URI כשהמשתמש מופנה חזרה לאפליקציה.

קריאה ל-Google APIs

נקודות קצה של OAuth 2.0

לאחר שהאפליקציה תקבל אסימון גישה, תהיה לך אפשרות להשתמש באסימון כדי לבצע קריאות ל-Google API מטעם חשבון משתמש נתון, אם היקפי הגישה הנדרשים לממשק ה-API הוענקו. כדי לעשות את זה, צריך לכלול את אסימון הגישה בבקשה ל-API, באמצעות פרמטר של שאילתה access_token או ערך Bearer של כותרת HTTP Authorization. כשאפשר, עדיפה כותרת ה-HTTP, כי מחרוזות השאילתה מופיעות בדרך כלל ביומני השרתים. ברוב המקרים, תוכלו להשתמש בספריית לקוח כדי להגדיר את הקריאות ל-Google APIs (לדוגמה, בעת קריאה ל-Drive Files API).

אתם יכולים לנסות את כל ממשקי ה-API של Google ולראות את ההיקפים שלהם במגרש המשחקים של OAuth 2.0.

דוגמאות ל-HTTP GET

קריאה לנקודת הקצה drive.files (ה-API של Drive) באמצעות כותרת ה-HTTP Authorization: Bearer עשויה להיראות כך. שימו לב: עליכם לציין את אסימון הגישה שלכם:

GET /drive/v2/files HTTP/1.1
Host: www.googleapis.com
Authorization: Bearer access_token

זו קריאה לאותו API עבור המשתמש המאומת באמצעות הפרמטר access_token של מחרוזת השאילתה:

GET https://www.googleapis.com/drive/v2/files?access_token=access_token

curl דוגמאות

אפשר לבדוק את הפקודות האלה בעזרת אפליקציית שורת הפקודה curl. הנה דוגמה שמשתמשת באפשרות של כותרת HTTP (השדה המועדף):

curl -H "Authorization: Bearer access_token" https://www.googleapis.com/drive/v2/files

או לחילופין, אפשרות הפרמטר של מחרוזת השאילתה:

curl https://www.googleapis.com/drive/v2/files?access_token=access_token

קוד לדוגמה של JavaScript

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

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

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) {
  console.log(xhr.response);
};
xhr.send(null);

דוגמה מלאה

נקודות קצה של OAuth 2.0

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

בתהליך OAuth 2.0, הדף פועל לפי השלבים הבאים:

  1. היא מפנה את המשתמש לשרת OAuth 2.0 של Google, שמבקש גישה להיקף של https://www.googleapis.com/auth/drive.metadata.readonly.
  2. אחרי מתן (או דחייה) גישה להיקפים מבוקשים אחד או יותר, המשתמש מופנה לדף המקורי שמנתח את אסימון הגישה ממחרוזת מזהה המקטע.
  3. הדף משתמש באסימון הגישה כדי ליצור את בקשת ה-API לדוגמה.

    בבקשת ה-API, מתבצע קריאה ל-method about.get של Drive API כדי לאחזר מידע על חשבון Google Drive של המשתמש המורשה.

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

אפשר לבטל את הגישה לאפליקציה דרך הדף Permissions בחשבון Google. האפליקציה תופיע כהדגמה של OAuth 2.0 ל-Google API Docs.

כדי להפעיל את הקוד הזה באופן מקומי, צריך להגדיר ערכים למשתנים YOUR_CLIENT_ID ו-YOUR_REDIRECT_URI שתואמים לפרטי הכניסה להרשאות שלכם. המשתנה YOUR_REDIRECT_URI צריך להיות מוגדר לאותה כתובת URL שבה הדף מוצג. הערך חייב להיות זהה לאחד ממזהי ה-URI המורשים להפניה אוטומטית בלקוח OAuth 2.0, שהגדרת ב- API Console Credentials page. אם הערך הזה לא תואם ל-URI מורשה, תתקבל הודעת השגיאה redirect_uri_mismatch. בנוסף, צריך להפעיל בפרויקט את ה-API המתאים לבקשה הזו.

<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>

כללי אימות המקור של JavaScript

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

כללי אימות
סכמה

מקורות JavaScript חייבים להשתמש בסכימת HTTPS, ולא ב-HTTP פשוט. הכלל הזה לא כולל מזהי URI של מארח מקומי (כולל מזהי URI של כתובות IP של מארחים מקומיים).

מארח

מארחים לא יכולים להיות כתובות IP גולמיות. כתובות IP של מארח מקומי פטורות מהכלל הזה.

דומיין
  • דומיינים ברמה העליונה של מארח (דומיינים ברמה עליונה) חייבים להשתייך לרשימת הסיומות הציבוריות.
  • הדומיינים המארחים לא יכולים להיות “googleusercontent.com”.
  • מקורות JavaScript לא יכולים להכיל דומיינים של קיצור כתובות URL (למשל goo.gl) אלא אם הדומיין הוא בבעלות האפליקציה.
  • פרטי משתמש

    מקורות JavaScript לא יכולים להכיל את רכיב המשנה של פרטי המשתמש.

    נתיב

    מקורות JavaScript לא יכולים להכיל את רכיב הנתיב.

    שאילתה

    מקורות JavaScript לא יכולים להכיל את רכיב השאילתה.

    קטע

    מקורות JavaScript לא יכולים להכיל את רכיב המקטע.

    תווים מקורות JavaScript לא יכולים לכלול תווים מסוימים, כולל:
    • תווים כלליים לחיפוש ('*')
    • תווי ASCII שאינם ניתנים להדפסה
    • קידודי אחוזים לא חוקיים (כל קידוד באחוזים שאינו פועל בהתאם לצורת קידוד כתובת URL של סימן אחוז ואחריו שתי ספרות הקסדצימליות)
    • תווי null (תו NULL מקודד, למשל, %00, %C0%80)

    הרשאה מצטברת

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

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

    במקרה כזה, בזמן הכניסה האפליקציה עשויה לבקש מההיקפים openid ו-profile לבצע כניסה בסיסית, ובמועד מאוחר יותר לבקש את ההיקף https://www.googleapis.com/auth/drive.file כשהבקשה הראשונה לשמור שילוב.

    הכללים הבאים חלים על אסימון גישה שהתקבל מהרשאה מצטברת:

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

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

    נקודות קצה של OAuth 2.0

    כדי להוסיף היקפים לאסימון גישה קיים, צריך לכלול את הפרמטר include_granted_scopes בבקשה לשרת OAuth 2.0 של Google.

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

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

    var SCOPE = 'https://www.googleapis.com/auth/drive.metadata.readonly';
    var params = JSON.parse(localStorage.getItem('oauth2-test-params'));
    
    var current_scope_granted = false;
    if (params.hasOwnProperty('scope')) {
      var scopes = params['scope'].split(' ');
      for (var s = 0; s < scopes.length; s++) {
        if (SCOPE == scopes[s]) {
          current_scope_granted = true;
        }
      }
    }
    
    if (!current_scope_granted) {
      oauth2SignIn(); // This function is defined elsewhere in this document.
    } else {
      // Since you already have access, you can proceed with the API request.
    }

    ביטול אסימון

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

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

    נקודות קצה של OAuth 2.0

    כדי לבטל אסימון באופן פרוגרמטי, האפליקציה שולחת בקשה אל https://oauth2.googleapis.com/revoke וכוללת את האסימון כפרמטר:

    curl -d -X -POST --header "Content-type:application/x-www-form-urlencoded" \
            https://oauth2.googleapis.com/revoke?token={token}

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

    אם הביטול מעובד בהצלחה, קוד סטטוס ה-HTTP של התגובה הוא 200. במקרה של תנאי שגיאה, מוחזר קוד מצב HTTP 400 יחד עם קוד שגיאה.

    קטע הקוד הבא של JavaScript מראה איך לבטל אסימון ב-JavaScript בלי להשתמש בספריית הלקוח של Google APIs עבור JavaScript. נקודת הקצה של OAuth 2.0 של Google לביטול אסימונים לא תומכת בשיתוף משאבים בין מקורות (CORS), הקוד יוצר טופס ושולח את הטופס לנקודת הקצה, במקום להשתמש בשיטה XMLHttpRequest() כדי לפרסם את הבקשה.

    function revokeAccess(accessToken) {
      // Google's OAuth 2.0 endpoint for revoking access tokens.
      var revokeTokenEndpoint = 'https://oauth2.googleapis.com/revoke';
    
      // Create <form> element to use to POST data to the OAuth 2.0 endpoint.
      var form = document.createElement('form');
      form.setAttribute('method', 'post');
      form.setAttribute('action', revokeTokenEndpoint);
    
      // Add access token to the form so it is set as value of 'token' parameter.
      // This corresponds to the sample curl request, where the URL is:
      //      https://oauth2.googleapis.com/revoke?token={token}
      var tokenField = document.createElement('input');
      tokenField.setAttribute('type', 'hidden');
      tokenField.setAttribute('name', 'token');
      tokenField.setAttribute('value', accessToken);
      form.appendChild(tokenField);
    
      // Add form to page and submit it to actually revoke the token.
      document.body.appendChild(form);
      form.submit();
    }