שימוש ב-OAuth 2.0 לאפליקציות אינטרנט של JavaScript

המסמך הזה מסביר איך להטמיע הרשאת OAuth 2.0 כדי לגשת ל-YouTube Data API מאפליקציית אינטרנט של JavaScript. OAuth 2.0 מאפשר למשתמשים לשתף נתונים ספציפיים עם אפליקציה, תוך שמירה על הפרטיות של שמות המשתמשים, הסיסמאות ומידע אחר. לדוגמה, אפליקציה יכולה להשתמש ב-OAuth 2.0 כדי לקבל הרשאה להעלות סרטונים לערוץ YouTube של המשתמש.

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

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

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

אם משתמשים בספריית הלקוח של 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. בדף ספרייה אפשר למצוא את ממשק YouTube Data API ולהפעיל אותו. צריך לחפש ממשקי API אחרים שהאפליקציה תשתמש בהם ולהפעיל גם אותם.

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

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

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

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

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

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

ממשק YouTube Data API v3 משתמש בהיקפים הבאים:

טווחים
https://www.googleapis.com/auth/youtubeניהול חשבון YouTube שלך
https://www.googleapis.com/auth/youtube.channel-memberships.creatorהצגת רשימה מעודכנת של החברים הפעילים במועדון החברים של הערוץ, הרמה הנוכחית שלהם והתאריך שבו הם הצטרפו למועדון
https://www.googleapis.com/auth/youtube.force-sslהצגה, עריכה ומחיקה לצמיתות של סרטונים, דירוגים, תגובות וכתוביות ב-YouTube
https://www.googleapis.com/auth/youtube.readonlyהצגת חשבון YouTube שלך
https://www.googleapis.com/auth/youtube.uploadניהול הסרטונים שלך ב-YouTube
https://www.googleapis.com/auth/youtubepartnerהצגה וניהול של הנכסים והתכנים הקשורים שלך ב-YouTube
https://www.googleapis.com/auth/youtubepartner-channel-auditהצגת מידע פרטי של ערוץ YouTube שלך הרלוונטי בתהליך הביקורת של שותף YouTube.

המסמך היקפי API של OAuth 2.0 מכיל רשימה מלאה של היקפים שבהם תוכלו להשתמש כדי לגשת ל-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 חובה

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

redirect_uri חובה

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

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

response_type חובה

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

scope חובה

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

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

ממשק YouTube Data API v3 משתמש בהיקפים הבאים:

טווחים
https://www.googleapis.com/auth/youtubeניהול חשבון YouTube שלך
https://www.googleapis.com/auth/youtube.channel-memberships.creatorהצגת רשימה מעודכנת של החברים הפעילים במועדון החברים של הערוץ, הרמה הנוכחית שלהם והתאריך שבו הם הצטרפו למועדון
https://www.googleapis.com/auth/youtube.force-sslהצגה, עריכה ומחיקה לצמיתות של סרטונים, דירוגים, תגובות וכתוביות ב-YouTube
https://www.googleapis.com/auth/youtube.readonlyהצגת חשבון YouTube שלך
https://www.googleapis.com/auth/youtube.uploadניהול הסרטונים שלך ב-YouTube
https://www.googleapis.com/auth/youtubepartnerהצגה וניהול של הנכסים והתכנים הקשורים שלך ב-YouTube
https://www.googleapis.com/auth/youtubepartner-channel-auditהצגת מידע פרטי של ערוץ YouTube שלך הרלוונטי בתהליך הביקורת של שותף YouTube.

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

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

state המלצות

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

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

include_granted_scopes אופציונלי

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

login_hint אופציונלי

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

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

prompt אופציונלי

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

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

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

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

כתובת ה-URL לדוגמה שבהמשך מבקשת גישה אופליין (access_type=offline) להיקף שמאפשר גישה לצפייה בחשבון YouTube של המשתמש. הוא משתמש בהרשאה מצטברת כדי לוודא שאסימון הגישה החדש מכסה את כל ההיקפים שאליהם המשתמש העניק בעבר גישה לאפליקציה. כתובת ה-URL גם מגדירה ערכים לפרמטרים הנדרשים: redirect_uri, response_type ו-client_id, וגם לפרמטר state. כתובת ה-URL מכילה מעברי שורה ורווחים לשיפור הקריאוּת.

https://accounts.google.com/o/oauth2/v2/auth?
 scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fyoutube.readonly&
 include_granted_scopes=true&
 state=state_parameter_passthrough_value&
 redirect_uri=http%3A%2F%2Flocalhost%2Foauth2callback&
 response_type=token&
 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/youtube.force-ssl',
                '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 Workspace, אין אפשרות לתת הרשאה להיקף הרשאות אחד או יותר בחשבון Google. במאמר העזרה לאדמינים ב-Google Workspace מוסבר איך לקבוע לאילו אפליקציות של צד שלישי ואפליקציות פנימיות תהיה גישה לנתונים של Google Workspace, למידע נוסף על האופן שבו האדמין יכול להגביל את הגישה לכל ההיקפים או להיקפים הרגישים והמוגבלים, עד שתוענק גישה מפורשת למזהה הלקוח שלכם ב-OAuth.

disallowed_useragent

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

Android

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

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

iOS

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

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

org_internal

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

invalid_client

המקור שממנו נשלחה הבקשה לא מורשה עבור הלקוח הזה. פרטים נוספים זמינים בorigin_mismatch.

invalid_grant

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

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 שצוין בבקשה לאסימון הגישה.

אם המשתמש יאשר את הבקשה, התגובה תכיל אסימון גישה. אם המשתמש לא יאשר את הבקשה, התשובה תכיל הודעת שגיאה. אסימון הגישה או הודעת השגיאה מוחזרים בקטע הגיבוב של ה-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%2F%2Fwww.googleapis.com%2Fauth%2Fyoutube.readonly&
 include_granted_scopes=true&
 state=state_parameter_passthrough_value&
 redirect_uri=http%3A%2F%2Flocalhost%2Foauth2callback&
 response_type=token&
 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 (למשל, כששולחים קריאה ל-YouTube Data API).

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

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

דוגמאות ל-HTTP GET

קריאה לנקודת הקצה ( youtube.channels) (YouTube Data API) באמצעות כותרת ה-HTTP Authorization: Bearer עשויה להיראות כך. שימו לב שתצטרכו לציין אסימון גישה משלכם:

GET /youtube/v3/channels?part=snippet&mine=true HTTP/1.1
Host: www.googleapis.com
Authorization: Bearer access_token

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

GET https://www.googleapis.com/youtube/v3/channels?access_token=access_token&part=snippet&mine=true

curl דוגמאות

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

curl -H "Authorization: Bearer access_token" https://www.googleapis.com/youtube/v3/channels?part=snippet&mine=true

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

curl https://www.googleapis.com/youtube/v3/channels?access_token=access_token&part=snippet&mine=true

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

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

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

var xhr = new XMLHttpRequest();
xhr.open('GET',
    'https://www.googleapis.com/youtube/v3/channels?part=snippet&mine=true&' +
    '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/youtube.force-ssl.
  2. אחרי הענקת (או דחייה) של גישה להיקף מבוקש אחד או יותר, המשתמש מופנה לדף המקורי, שמנתח את אסימון הגישה מהמחרוזת של מזהה המקטע.
  3. הדף משתמש באסימון הגישה כדי לבצע את בקשת ה-API לדוגמה.

    בקשת ה-API הזו מפעילה את השיטה channels.list של YouTube Data API כדי לאחזר נתונים על ערוץ YouTube של המשתמש המורשה.

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

אפשר לבטל את הגישה לאפליקציה דרך הדף הרשאות בחשבון 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';

  // Parse query string to see if page request is coming from OAuth 2.0 server.
  var fragmentString = location.hash.substring(1);
  var params = {};
  var regex = /([^&=]+)=([^&]*)/g, m;
  while (m = regex.exec(fragmentString)) {
    params[decodeURIComponent(m[1])] = decodeURIComponent(m[2]);
  }
  if (Object.keys(params).length > 0 && params['state']) {
    if (params['state'] == localStorage.getItem('state')) {
      localStorage.setItem('oauth2-test-params', JSON.stringify(params) );

      trySampleRequest();
    } else {
      console.log('State mismatch. Possible CSRF attack');
    }
  }

  // Function to generate a random state value
  function generateCryptoRandomState() {
    const randomValues = new Uint32Array(2);
    window.crypto.getRandomValues(randomValues);

    // Encode as UTF-8
    const utf8Encoder = new TextEncoder();
    const utf8Array = utf8Encoder.encode(
      String.fromCharCode.apply(null, randomValues)
    );

    // Base64 encode the UTF-8 data
    return btoa(String.fromCharCode.apply(null, utf8Array))
      .replace(/\+/g, '-')
      .replace(/\//g, '_')
      .replace(/=+$/, '');
  }

  // 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/youtube/v3/channels?part=snippet&mine=true&' +
          '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() {
    // create random state value and store in local storage
    var state = generateCryptoRandomState();
    localStorage.setItem('state', state);

    // 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/youtube.force-ssl',
                  'state': state,
                  '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, סעיף 3.

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

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

מארח

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

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

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

    נתיב

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

    שאילתה

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

    מקטע

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

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

    הרשאה מצטברת

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

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

    במקרה כזה, בזמן הכניסה, יכול להיות שהאפליקציה לא תצטרך גישה להיקפים כלשהם או לא תבקש גישה אליהם. עם זאת, אם המשתמש ניסה לסווג סרטון, להוסיף סרטון לפלייליסט או לבצע פעולה אחרת ב-YouTube, האפליקציה תוכל לבקש גישה להיקף ההרשאות https://www.googleapis.com/auth/youtube.force-ssl. באופן דומה, האפליקציה יכולה לבקש גישה להיקף https://www.googleapis.com/auth/calendar אם המשתמש ניסה להוסיף אירוע ביומן.

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

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

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

    נקודות קצה ב-OAuth 2.0

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

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

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

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

    var SCOPE = 'https://www.googleapis.com/auth/youtube.force-ssl';
    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. במקרים של שגיאות, מוחזר קוד הסטטוס 400 של HTTP יחד עם קוד השגיאה.

    קטע הקוד הבא של JavaScript מראה איך לבטל אסימון ב-JavaScript בלי להשתמש בספריית הלקוח של Google APIs ל-JavaScript. נקודת הקצה מסוג OAuth 2.0 של Google לביטול אסימונים לא תומכת בשיתוף משאבים בין מקורות (CORS), ולכן הקוד יוצר טופס ושולח את הטופס לנקודת הקצה במקום להשתמש ב-method 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();
    }