OpenID Connect (original) (raw)
אפשר להשתמש בממשקי ה-API של Google מסוג OAuth 2.0 גם לאימות וגם להרשאה. במסמך הזה מתוארת הטמעת OAuth 2.0 שלנו לאימות, שתואמת למפרט של OpenID Connect ומאושרת על ידי OpenID. המסמכים שמופיעים במאמר שימוש ב-OAuth 2.0 כדי לגשת ל-Google APIs רלוונטיים גם לשירות הזה. כדי לבדוק את הפרוטוקול הזה באופן אינטראקטיבי, מומלץ להיכנס אל מגרש המשחקים של Google OAuth 2.0. כדי לקבל עזרה ב-Stack Overflow, צריך לתייג את השאלות שלכם בתג 'google-oauth'.
הגדרת OAuth 2.0
כדי שהאפליקציה שלכם תוכל להשתמש במערכת האימות של Google באמצעות OAuth 2.0 לכניסת משתמשים, עליכם להגדיר פרויקט ב- כדי לקבל פרטי כניסה ל-OAuth 2.0, להגדיר URI להפניה אוטומטית (redirect) ולשנות (אופציונלי) את פרטי המיתוג שיוצגו למשתמשים במסך ההסכמה שלהם. אפשר גם להשתמש ב- כדי ליצור חשבון שירות, להפעיל חיוב, להגדיר סינון ולבצע משימות אחרות. למידע נוסף, אפשר לעיין ב עזרה.
קבלת פרטי כניסה ל-OAuth 2.0
כדי לאמת משתמשים ולקבל גישה לממשקי ה-API של Google, נדרשים פרטי כניסה של OAuth 2.0, כולל מזהה לקוח וסוד לקוח.
כדי להציג את מזהה הלקוח וסוד הלקוח עבור אישור נתון OAuth 2.0, לחץ על הטקסט הבא: בחר אישור . בחלון שנפתח בחר את הפרוייקט שלך ואת האישור שאתה רוצה ולחץ על תצוגה .
לחלופין, צפה בזיהוי הלקוח ובסוד הלקוח שלך מדף האישורים ב API Console :
- Go to the Credentials page.
- לחץ על שם האישור שלך או על סמל העיפרון ( ). קוד זיהוי הלקוח וסודך נמצאים בראש העמוד.
הגדרת URI להפניה אוטומטית
ה-URI להפניה אוטומטית שהגדרתם ב- קובע לאן Google שולחת תשובות לבקשות האימות.
כדי ליצור, להציג או לערוך את כתובות ה- URI להפניה מחדש עבור אישור נתון OAuth 2.0, בצע את הפעולות הבאות:
- Go to the Credentials page.
- בקטע מזהי לקוח OAuth 2.0 בדף, לחץ על אישור.
- הצגה או עריכה של קבצי ה- URI המפנים מחדש.
אם אין קטע מזהי לקוח של OAuth 2.0 בדף האישורים, לפרויקט שלך אין אישורי OAuth. כדי ליצור אחת, לחץ על צור אישורים .
התאמה אישית של המסך לבקשת הסכמה מהמשתמשים
חוויית האימות של OAuth 2.0 כוללת מסך הסכמה שבו מתוארים המידע שהמשתמש משחרר והמונחים הרלוונטיים. לדוגמה, כשהמשתמש נכנס לחשבון, יכול להיות שהוא יתבקש לתת לאפליקציה גישה לכתובת האימייל ולפרטי החשבון הבסיסיים שלו. מבקשים גישה למידע הזה באמצעות הפרמטר scope, שהאפליקציה כוללת בבקשת האימות שלה. אפשר גם להשתמש בהיקפי הרשאות כדי לבקש גישה לממשקי API אחרים של Google.
במסך הסכמת המשתמש מוצגים גם פרטי מיתוג, כמו שם המוצר, הלוגו וכתובת ה-URL של דף הבית. אתם שולטים בפרטי המיתוג ב- .
כדי לאפשר את מסך ההסכמה של הפרויקט שלך:
- פתח את Consent Screen page ב- Google API Console .
- If prompted, select a project, or create a new one.
- מלא את הטופס ולחץ על שמור .
בתיבת הדו-שיח הבאה להבעת הסכמה מוצג מה שהמשתמש יראה כשבקשה כוללת שילוב של היקפי הרשאות של OAuth 2.0 ושל Google Drive. (תיבת הדו-שיח הגנרית הזו נוצרה באמצעות Google OAuth 2.0 Playground, ולכן היא לא כוללת פרטי מיתוג שייקבעו ב- ).
איור 1. צילום מסך של דף ההסכמה
גישה לשירות
Google וצדדים שלישיים מספקים ספריות שאפשר להשתמש בהן כדי לטפל בחלק גדול מפרטי ההטמעה של אימות המשתמשים וקבלת גישה לממשקי Google API. דוגמאות לכך הן Google Identity Services וספריות הלקוח של Google, שזמינות למגוון פלטפורמות.
אם בוחרים לא להשתמש בספרייה, פועלים לפי ההוראות שבחלקים הבאים של המסמך, שמתארים את תהליכי הבקשות של HTTP שמהווים את הבסיס לספריות הזמינות.
אימות המשתמש
אימות המשתמש כרוך בקבלת אסימון מזהה ואימות שלו.אסימונים מזהים הם תכונה סטנדרטית של OpenID Connect שנועדה לשימוש בשיתוף טענות נכוֹנוּת (assertions) של זהות באינטרנט.
הגישות הנפוצות ביותר לאימות משתמש ולקבלת אסימון מזהה נקראות 'זרם שרת' ו'זרם משתמע'. תהליך האימות בשרת מאפשר לשרת הקצה של האפליקציה לאמת את הזהות של המשתמש באמצעות דפדפן או מכשיר נייד. התהליך המשתמעים משמש כשאפליקציה בצד הלקוח (בדרך כלל אפליקציית JavaScript שפועלת בדפדפן) צריכה לגשת ל-API ישירות במקום להשתמש בשרת הקצה העורפי שלה.
במאמר הזה נסביר איך לבצע את תהליך האימות של המשתמש בשרת. התהליך המשתמע מורכב הרבה יותר בגלל סיכוני אבטחה שקשורים לטיפול באסימונים ולשימוש בהם בצד הלקוח. אם אתם צריכים להטמיע תהליך סמוי, מומלץ מאוד להשתמש ב-Google Identity Services.
תהליך השרת
חשוב להגדיר את האפליקציה ב- כדי לאפשר לה להשתמש בפרוטוקולים האלה ולאמת את המשתמשים. כשמשתמש מנסה להיכנס באמצעות חשבון Google, צריך:
- יצירת טוקן מצב למניעת זיוף
- שליחת בקשת אימות ל-Google
- אימות של אסימון המצב למניעת זיוף
- המרת code לאסימון גישה ולאסימון מזהה
- איך מקבלים את פרטי המשתמש מהאסימון המזהה
- אימות המשתמש
1. יצירת טוקן מצב למניעת זיוף
כדי להגן על אבטחת המשתמשים, עליכם למנוע התקפות של זיוף בקשות. השלב הראשון הוא יצירת אסימון סשן ייחודי שמכיל את המצב בין האפליקציה לבין הלקוח של המשתמש. בשלב מאוחר יותר, תוכלו להתאים את אסימון הסשן הייחודי הזה לתשובת האימות שמוחזרת על ידי שירות הכניסה של Google OAuth, כדי לוודא שהבקשה נשלחה על ידי המשתמש ולא על ידי תוקף זדוני. האסימונים האלה נקראים לעיתים קרובות אסימוני CSRF (זיוף בקשות בין אתרים).
אפשרות טובה לטוקן מצב היא מחרוזת של כ-30 תווים שנוצרה באמצעות מחולל מספרים אקראיים באיכות גבוהה. אפשרות נוספת היא גיבוב שנוצר על ידי חתימה על חלק ממשתני מצב הסשן באמצעות מפתח שנשמר בסוד בקצה העורפי.
הקוד הבא מדגים יצירת אסימוני סשן ייחודיים.
PHP
כדי להשתמש בדוגמה הזו, צריך להוריד את ספריית הלקוח של Google APIs ל-PHP.
// Create a state token to prevent request forgery. // Store it in the session for later validation. $state = bin2hex(random_bytes(128/8)); app[′session′]−>set(′state′,app['session']->set('state', app[′session′]−>set(′state′,state); // Set the client ID, token state, and application name in the HTML while // serving it. return $app['twig']->render('index.html', array( 'CLIENT_ID' => CLIENT_ID, 'STATE' => $state, 'APPLICATION_NAME' => APPLICATION_NAME ));
Java
כדי להשתמש בדוגמה הזו, צריך להוריד את ספריית הלקוח של Google APIs ל-Java.
// Create a state token to prevent request forgery. // Store it in the session for later validation. String state = new BigInteger(130, new SecureRandom()).toString(32); request.session().attribute("state", state); // Read index.html into memory, and set the client ID, // token state, and application name in the HTML before serving it. return new Scanner(new File("index.html"), "UTF-8") .useDelimiter("\A").next() .replaceAll("[{]{2}\sCLIENT_ID\s[}]{2}", CLIENT_ID) .replaceAll("[{]{2}\sSTATE\s[}]{2}", state) .replaceAll("[{]{2}\sAPPLICATION_NAME\s[}]{2}", APPLICATION_NAME);
Python
כדי להשתמש בדוגמה הזו, צריך להוריד את ספריית הלקוח של Google APIs ל-Python.
Create a state token to prevent request forgery.
Store it in the session for later validation.
state = hashlib.sha256(os.urandom(1024)).hexdigest() session['state'] = state
Set the client ID, token state, and application name in the HTML while
serving it.
response = make_response( render_template('index.html', CLIENT_ID=CLIENT_ID, STATE=state, APPLICATION_NAME=APPLICATION_NAME))
2. שליחת בקשת אימות ל-Google
השלב הבא הוא ליצור בקשת GET
ב-HTTPS עם פרמטרים מתאימים של URI. חשוב לשים לב לשימוש ב-HTTPS במקום ב-HTTP בכל שלבי התהליך. חיבורי HTTP נדחים. צריך לאחזר את כתובת ה-URI הבסיסית ממסמך הגילוי באמצעות ערך המטא-נתונים authorization_endpoint
. בחלק הבא נעשה שימוש ב-URI הבסיסי https://accounts.google.com/o/oauth2/v2/auth
.
בבקשה בסיסית, צריך לציין את הפרמטרים הבאים:
client_id
, שמקבלים מה- .response_type
, שבבקשה בסיסית של תהליך הרשאה באמצעות קוד צריך להיותcode
. (מידע נוסף זמין במאמר response_type).scope
, שבבקשה בסיסית צריך להיותopenid email
. (מידע נוסף זמין בכתובת scope).redirect_uri
צריכה להיות נקודת הקצה (endpoint) של HTTP בשרת שלכם שתקבל את התגובה מ-Google. הערך חייב להתאים בדיוק לאחד מ-URI של ההפניה האוטומטית המורשים של לקוח OAuth 2.0, שהגדרתם ב- Credentials page. אם הערך הזה לא תואם ל-URI מורשה, הבקשה תיכשל עם השגיאהredirect_uri_mismatch
.- השדה
state
צריך לכלול את הערך של אסימון הסשן הייחודי למניעת זיוף, וגם כל מידע אחר שנחוץ לשחזור ההקשר כשהמשתמש חוזר לאפליקציה, למשל כתובת ה-URL ההתחלתית. (מידע נוסף זמין בכתובת state). nonce
הוא ערך אקראי שנוצר על ידי האפליקציה ומאפשר הפעלת הגנה מפני הפעלה חוזרת כשהוא קיים.login_hint
יכול להיות כתובת האימייל של המשתמש או המחרוזתsub
, שמקבילה למזהה Google של המשתמש. אם לא תספקו את הערךlogin_hint
והמשתמש מחובר, מסך ההסכמה יכלול בקשה לאישור כדי למסור את כתובת האימייל של המשתמש לאפליקציה. (מידע נוסף זמין במאמר login_hint).- משתמשים בפרמטר
hd
כדי לבצע אופטימיזציה של תהליך OpenID Connect למשתמשים בדומיין מסוים שמשויך לארגון ב-Google Workspace או ב-Cloud (מידע נוסף זמין במאמר hd).
זו דוגמה ל-URI מלא לאימות OpenID Connect, עם הפסקות שורות ומרווחי טקסט לצורך קריאה:
https://accounts.google.com/o/oauth2/v2/auth? response_type=code& client_id=424911365001.apps.googleusercontent.com& scope=openid%20email& redirect_uri=https%3A//oauth2.example.com/code& state=security_token%3D138r5719ru3e1%26url%3Dhttps%3A%2F%2Foauth2-login-demo.example.com%2FmyHome& login_hint=jsmith@example.com& nonce=0394852-3190485-2490358& hd=example.com
המשתמשים נדרשים להביע הסכמה אם האפליקציה מבקשת מידע חדש עליהם, או אם האפליקציה מבקשת גישה לחשבון שהם לא אישרו בעבר.
3. אישור אסימון מצב למניעת זיוף
התגובה נשלחת אל redirect_uri
שציינתם בבקשה. כל התשובות מוחזרות במחרוזת השאילתה:
בשרת, צריך לוודא שה-state
שהתקבל מ-Google תואם לאסימון הסשן שיצרתם בשלב 1. האימות הלוך ושוב עוזר לוודא שהבקשה נשלחת על ידי המשתמש ולא על ידי סקריפט זדוני.
הקוד הבא מדגים אימות של אסימוני הסשן שיצרתם בשלב 1:
PHP
כדי להשתמש בדוגמה הזו, צריך להוריד את ספריית הלקוח של Google APIs ל-PHP.
// Ensure that there is no request forgery going on, and that the user // sending us this connect request is the user that was supposed to. if ($request->get('state') != ($app['session']->get('state'))) { return new Response('Invalid state parameter', 401); }
Java
כדי להשתמש בדוגמה הזו, צריך להוריד את ספריית הלקוח של Google APIs ל-Java.
// Ensure that there is no request forgery going on, and that the user // sending us this connect request is the user that was supposed to. if (!request.queryParams("state").equals( request.session().attribute("state"))) { response.status(401); return GSON.toJson("Invalid state parameter."); }
Python
כדי להשתמש בדוגמה הזו, צריך להוריד את ספריית הלקוח של Google APIs ל-Python.
Ensure that the request is not a forgery and that the user sending
this connect request is the expected user.
if request.args.get('state', '') != session['state']: response = make_response(json.dumps('Invalid state parameter.'), 401) response.headers['Content-Type'] = 'application/json' return response
4. המרת code
לאסימון גישה ולאסימון מזהה
התגובה כוללת את הפרמטר code
, שהוא קוד הרשאה חד-פעמי שהשרת יכול להמיר לאסימון גישה ולאסימון מזהה. השרת מבצע את ההחלפה הזו על ידי שליחת בקשת POST
ב-HTTPS. הבקשה POST
נשלחת לנקודת הקצה של האסימון, שצריך לאחזר ממסמך ה-Discovery באמצעות ערך המטא-נתונים token_endpoint
. בחלק הבא נניח שנקודת הקצה היא https://oauth2.googleapis.com/token
. הבקשה חייבת לכלול את הפרמטרים הבאים בגוף POST
:
שדות | |
---|---|
code | קוד ההרשאה שמוחזר מהבקשה הראשונית. |
client_id | מזהה הלקוח שמקבלים מ- , כפי שמתואר במאמרקבלת פרטי כניסה ל-OAuth 2.0. |
client_secret | הסוד של הלקוח שמקבלים מ- , כפי שמתואר במאמרקבלת פרטי כניסה ל-OAuth 2.0. |
redirect_uri | URI מורשה להפניה אוטומטית של client_id שצוין ב- , כפי שמתואר בקטע הגדרת URI להפניה אוטומטית. |
grant_type | השדה הזה חייב להכיל את הערך authorization_code, כפי שמוגדר במפרט של OAuth 2.0. |
הבקשה בפועל עשויה להיראות כמו בדוגמה הבאה:
POST /token HTTP/1.1 Host: oauth2.googleapis.com Content-Type: application/x-www-form-urlencoded
code=4/P7q7W91a-oMsCeLvIaQm6bTrgtp7& client_id=your-client-id& client_secret=your-client-secret& redirect_uri=https%3A//oauth2.example.com/code& grant_type=authorization_code
תגובה תקינה לבקשה הזו מכילה את השדות הבאים במערך JSON:
שדות | |
---|---|
access_token | אסימון שאפשר לשלוח ל-Google API. |
expires_in | משך החיים שנותר של אסימון הגישה, בשניות. |
id_token | JWT שמכיל פרטי זהות של המשתמש, עם חתימה דיגיטלית של Google. |
scope | היקפי הגישה שמוענקים על ידי access_token, כפי שהם מפורטים ברשימה של מחרוזות תלויות-אותיות רישיות שמפרידים ביניהן רווחים. |
token_type | מזהה את סוג האסימון שהוחזר. בשלב הזה, השדה הזה תמיד מכיל את הערךBearer. |
refresh_token | (אופציונלי)השדה הזה מופיע רק אם הפרמטר access_type הוגדר לערך offline בבקשת האימות. פרטים נוספים זמינים במאמר אסימוני רענון. |
5. אחזור פרטי משתמשים מהאסימון המזהה
אסימון מזהה הוא JWT (JSON Web Token), כלומר אובייקט JSON חתום באופן קריפטוגרפי בקידוד Base64. בדרך כלל, חשוב מאוד לבדוק את תקינות האסימון המזהה לפני שמשתמשים בו, אבל מכיוון שאתם מתקשרים ישירות עם Google דרך ערוץ HTTPS ללא מתווך, ומשתמשים בסוד הלקוח כדי לאמת את עצמכם בפני Google, אתם יכולים להיות בטוחים שהאסימון שאתם מקבלים באמת מגיע מ-Google ותקף. אם השרת מעביר את אסימון הזהות לרכיבים אחרים באפליקציה, חשוב מאוד שהרכיבים האחרים יאמתו את האסימון לפני השימוש בו.
מאחר שרוב ספריות ה-API משלבות את האימות עם הפענוח של הערכים בקידוד base64url ופירוק ה-JSON שבתוכם, סביר להניח שתצטרכו לאמת את האסימון בכל מקרה כשתיגשו לטענות הנכונות באסימון המזהה.
עומס העבודה של אסימון מזהה
אסימון מזהה הוא אובייקט JSON שמכיל קבוצה של צמדי שם/ערך. הנה דוגמה, בפורמט שקל לקריאה:
{ "iss": "https://accounts.google.com", "azp": "1234987819200.apps.googleusercontent.com", "aud": "1234987819200.apps.googleusercontent.com", "sub": "10769150350006150715113082367", "at_hash": "HK6E_P6Dh8Y93mRNtsDB1Q", "hd": "example.com", "email": "jsmith@example.com", "email_verified": "true", "iat": 1353601026, "exp": 1353604926, "nonce": "0394852-3190485-2490358" }
אסימונים מזהים של Google עשויים לכלול את השדות הבאים (שנקראים הצהרות):
מימוש | הוגדרו | תיאור |
---|---|---|
aud | תמיד | הקהל שאסימון המזהה הזה מיועד לו. הוא חייב להיות אחד ממזהי הלקוח ב-OAuth 2.0 של האפליקציה. |
exp | תמיד | מועד התפוגה, שבו אסור לקבל את טוקן המזהה או אחריו. מיוצג בזמן Unix epoch (שניות שלמות). |
iat | תמיד | השעה שבה הונפק האסימון המזהה. מיוצג בזמן Unix epoch (שניות שלמות). |
iss | תמיד | מזהה המנפיק של המנפיק של התשובה. תמיד https://accounts.google.com או accounts.google.com לאסימונים מזהים של Google. |
sub | תמיד | מזהה של המשתמש, ייחודי לכל חשבונות Google ולא ניתן לשימוש חוזר. לחשבון Google יכולות להיות כמה כתובות אימייל בנקודות זמן שונות, אבל הערך של sub אף פעם לא משתנה. משתמשים ב-sub באפליקציה בתור המפתח של המזהה הייחודי של המשתמש. אורך מקסימלי של 255 תווים ASCII שמוגדרת להם אותיות רישיות. |
at_hash | גיבוב (hash) של אסימון הגישה. מאפשרת לאמת שאסימון הגישה קשור לאסימון הזהות. אם האסימון המזהה מונפק עם ערך access_token בתהליך של השרת, ההצהרה הזו תמיד נכללת. אפשר להשתמש בהצהרה הזו כמנגנון חלופי להגנה מפני התקפות זיוף בקשות בין אתרים, אבל אם פועלים לפי שלב 1 ושלב 3, לא צריך לאמת את אסימון הגישה. | |
azp | client_id של המגיש המורשה. הצהרת ההסכמה הזו נדרשת רק אם הצד שמבקש את אסימון המזהה הוא לא אותו צד שאליו מיועד אסימון המזהה. יכול להיות שזה המצב ב-Google באפליקציות היברידיות שבהן לאפליקציית האינטרנט ולאפליקציית Android יש client_id שונה של OAuth 2.0, אבל הן משתפות את אותו פרויקט ב-Google APIs. | |
כתובת האימייל של המשתמש. האפשרות הזו מוצגת רק אם הכללתם את ההיקף email בבקשה. יכול להיות שהערך של ההצהרה הזו לא יהיה ייחודי לחשבון הזה, והוא עשוי להשתנות עם הזמן. לכן, אל תשתמשו בערך הזה כמזהה הראשי לקישור לרשומות המשתמש. בנוסף, אי אפשר להסתמך על הדומיין של הצהרת email כדי לזהות משתמשים בארגונים של Google Workspace או Cloud. במקום זאת, צריך להשתמש בהצהרה hd. | ||
email_verified | הערך יהיה True אם כתובת האימייל של המשתמש אומתה, אחרת הערך יהיה False. | |
family_name | השמות הפרטיים או שמות המשפחה של המשתמש. יכול להיות שהשדה הזה יופיע אם יש תלונה מסוג name. | |
given_name | השמות הפרטיים של המשתמש. יכול להיות שהשדה הזה יופיע אם יש תלונה מסוג name. | |
hd | הדומיין שמשויך לארגון של המשתמש ב-Google Workspace או ב-Cloud. השדה הזה מופיע רק אם המשתמש שייך לארגון ב-Google Cloud. צריך לבדוק את ההצהרה הזו כשמגבילים את הגישה למשאב רק לחברים בדומיינים מסוימים. אם ההצהרה הזו לא מופיעה, המשמעות היא שהחשבון לא שייך לדומיין שמתארח ב-Google. | |
locale | אזור הזמן והשפה של המשתמש, שמיוצגים על ידי תג שפה מסוג BCP 47. יכול להיות שהשדה הזה יופיע אם יש תלונה מסוג name. | |
name | השם המלא של המשתמש, בצורה שניתנת להצגה. יכול להיות שהיא תסופק במקרים הבאים: היקף הבקשה כלל את המחרוזת 'profile' האסימון המזהה מוחזר מרענון של אסימון כשיש הצהרות name, אפשר להשתמש בהן כדי לעדכן את רשומות המשתמשים באפליקציה. חשוב לדעת שההצהרה הזו לא תמיד מופיעה. | |
nonce | הערך של nonce שסופק על ידי האפליקציה שלכם בבקשת האימות. כדי להגן מפני התקפות שליחה מחדש, צריך להציג את הערך הזה רק פעם אחת. | |
picture | כתובת ה-URL של תמונת הפרופיל של המשתמש. יכול להיות שהיא תסופק במקרים הבאים: היקף הבקשה כלל את המחרוזת 'profile' האסימון המזהה מוחזר מרענון של אסימון כשיש הצהרות picture, אפשר להשתמש בהן כדי לעדכן את רשומות המשתמשים של האפליקציה. חשוב לדעת שההצהרה הזו לא תמיד מופיעה. | |
profile | כתובת ה-URL של דף הפרופיל של המשתמש. יכול להיות שהיא תסופק במקרים הבאים: היקף הבקשה כלל את המחרוזת 'profile' האסימון המזהה מוחזר מרענון של אסימון כשיש הצהרות profile, אפשר להשתמש בהן כדי לעדכן את רשומות המשתמשים של האפליקציה. חשוב לדעת שההצהרה הזו לא תמיד מופיעה. |
6. אימות המשתמש
אחרי שמקבלים את פרטי המשתמש מאסימון המזהה, צריך לשלוח שאילתה למסד הנתונים של המשתמשים באפליקציה. אם המשתמש כבר קיים במסד הנתונים, צריך להתחיל סשן של האפליקציה עבור המשתמש הזה אם התשובה מ-Google API עומדת בכל דרישות הכניסה.
אם המשתמש לא קיים במסד הנתונים של המשתמשים, צריך להפנות אותו לתהליך ההרשמה של משתמשים חדשים. יכול להיות שתוכלו לרשום את המשתמש באופן אוטומטי על סמך המידע שאתם מקבלים מ-Google, או לפחות לאכלס מראש הרבה מהשדות הנדרשים בטופס ההרשמה. בנוסף למידע באסימון המזהה, אפשר לקבל פרטים נוספים על פרופיל המשתמש בנקודות הקצה של פרופיל המשתמש.
נושאים מתקדמים
בקטעים הבאים מוסבר בפירוט רב יותר על Google OAuth 2.0 API. המידע הזה מיועד למפתחים עם דרישות מתקדמות בנוגע לאימות ולהרשאה.
גישה לממשקי API אחרים של Google
אחד מהיתרונות של שימוש ב-OAuth 2.0 לאימות הוא שהאפליקציה יכולה לקבל הרשאה להשתמש בממשקי API אחרים של Google בשם המשתמש (כמו YouTube, Google Drive, יומן או אנשי קשר) בזמן שאתם מאמתים את המשתמש. כדי לעשות זאת, צריך לכלול את ההיקפים האחרים הנדרשים בבקשת האימות ששולחים ל-Google. לדוגמה, כדי להוסיף את קבוצת הגיל של המשתמש לבקשת האימות, מעבירים את הפרמטר openid email https://www.googleapis.com/auth/profile.agerange.read
. המשתמש מקבל בקשה מתאימה במסך ההסכמה. אסימון הגישה שתקבלו מ-Google יאפשר לאפליקציה לגשת לכל ממשקי ה-API שקשורים להיקפי הגישה שביקשת וקיבלתם.
אסימוני רענון
בבקשה לגישה ל-API, אפשר לבקש שיוחזר טוקן רענון במהלך ההחלפה של code. אסימון רענון מספק לאפליקציה גישה רציפה לממשקי Google APIs בזמן שהמשתמש לא נמצא באפליקציה. כדי לבקש אסימון רענון, צריך להגדיר את הערך offline
לפרמטר access_type בבקשת האימות.
שיקולים:
- חשוב לאחסן את אסימון הרענון באופן מאובטח וקבוע, כי אפשר לקבל אסימון רענון רק בפעם הראשונה שמבצעים את תהליך החלפת הקוד.
- יש מגבלות על מספר האסימונים לרענון שמונפקים: מגבלה אחת לכל שילוב של לקוח/משתמש, ומגבלה נוספת לכל משתמש בכל הלקוחות. אם האפליקציה מבקשת יותר מדי אסימוני רענון, היא עלולה להגיע למגבלות האלה, ובמקרה כזה אסימוני רענון ישנים יותר יפסיקו לפעול.
מידע נוסף זמין במאמר רענון של אסימון גישה (גישה אופליין).
הצגת בקשה חוזרת לקבלת הסכמה
כדי לבקש מהמשתמש להעניק הרשאה מחדש לאפליקציה, מגדירים את הפרמטר prompt לערך consent
בבקשת האימות. כשהאפשרות prompt=consent
כלולה, מסך ההסכמה מוצג בכל פעם שהאפליקציה מבקשת הרשאה להיקפי גישה, גם אם כל ההיקפים הוקצו בעבר לפרויקט Google APIs. לכן, מומלץ לכלול את prompt=consent
רק במקרים שבהם הדבר הכרחי.
מידע נוסף על הפרמטר prompt
זמין בקטע prompt בטבלה פרמטרים של URI לאימות.
פרמטרים של URI לאימות
בטבלה הבאה מפורטים תיאורים מלאים יותר של הפרמטרים שמקבל API האימות של OAuth 2.0 של Google.
פרמטר | חובה | תיאור |
---|---|---|
client_id | (נדרש) | מחרוזת מזהה הלקוח שמקבלים מ- , כפי שמתואר בקטע קבלת פרטי כניסה ל-OAuth 2.0. |
nonce | (נדרש) | ערך אקראי שנוצר על ידי האפליקציה ומאפשר הגנה מפני הפעלה חוזרת. |
response_type | (נדרש) | אם הערך הוא code, מתבצעת הפעלה של תהליך קוד הרשאה בסיסי, שבו נדרש POST לנקודת הקצה של האסימון כדי לקבל את האסימונים. אם הערך הוא token id_token או id_token token, מופעל תהליך סמוי, שבו נדרש שימוש ב-JavaScript בכתובת ה-URI להפניה האוטומטית כדי לאחזר אסימונים ממזהה ה-URI #fragment. |
redirect_uri | (נדרש) | קובע לאן התשובה נשלחת. הערך של הפרמטר הזה חייב להתאים בדיוק לאחד מערכי ההפניה האוטומטית המורשים שהגדרתם ב- (כולל הסכימה HTTP או HTTPS, אותיות רישיות וסימן הספרה '/' בסוף, אם יש). |
scope | (נדרש) | פרמטר ההיקף חייב להתחיל בערך openid ואז לכלול את הערך profile, את הערך email או את שניהם. אם ערך ההיקף profile קיים, ייתכן שטוקן המזהה יכלול את הצהרות profile שמוגדרות כברירת מחדל של המשתמש (אבל אין ערובה לכך). אם ערך ההיקף email קיים, אסימון המזהה כולל טענות נכונות (claims) של email ושל email_verified. בנוסף להיקפי ההרשאות הספציפיים ל-OpenID, ארגומנט ההיקף יכול לכלול גם ערכים אחרים של היקף. כל ערכי ההיקף חייבים להיות מופרדים באמצעות רווחים. לדוגמה, אם רוצים גישה לקובץ מסוים ב-Google Drive של משתמש, פרמטר ההיקף יכול להיות openid profile email https://www.googleapis.com/auth/drive.file. למידע על ההיקפים הזמינים, אפשר לעיין במאמר היקפי OAuth 2.0 ל-Google APIs או במסמכי העזרה של ממשק Google API שבו רוצים להשתמש. |
state | (אופציונלי, אבל מומלץ מאוד) | מחרוזת אטומה שמתבצעת בה חזרה (round-trip) בפרוטוקול. כלומר, היא מוחזרת כפרמטר URI בתהליך הבסיסי, ובמזהה #fragment של ה-URI בתהליך המשתמע. השדה state יכול להיות שימושי ליצירת התאמה בין בקשות לתשובות. מכיוון שאפשר לנחש את הערך של redirect_uri, שימוש בערך state יכול להגביר את הוודאות שחיבור נכנס הוא תוצאה של בקשת אימות שהאפליקציה שלכם יזמה. אם תיצרו מחרוזת אקראית או תקודדו את הגיבוב של מצב לקוח כלשהו (למשל, קובץ cookie) במשתנה state הזה, תוכלו לאמת את התשובה כדי לוודא שהבקשה והתשובה מקורן באותו דפדפן. כך אפשר להגן מפני התקפות כמו זיוף בקשות בין אתרים. |
access_type | (אופציונלי) | הערכים המותרים הם offline ו-online. ההשפעה מתועדת בקטע גישה אופליין. אם מבקשים אסימון גישה, הלקוח לא מקבל אסימון רענון אלא אם מציינים את הערך offline. |
display | (אופציונלי) | ערך מחרוזת ASCII שמציין את האופן שבו שרת ההרשאה מציג את דפי ממשק המשתמש של האימות וההסכמה. הערכים הבאים מצוינים ומאושרים על ידי שרתי Google, אבל אין להם השפעה על התנהגות זרימת הפרוטוקול: page, popup, touch ו-wap. |
hd | (אופציונלי) | ייעול תהליך ההתחברות לחשבונות שבבעלות ארגון ב-Google Cloud. אם תכללו את הדומיין הארגוני של Google Cloud (לדוגמה, mycollege.edu), תוכלו לציין שצריך לבצע אופטימיזציה של ממשק המשתמש לבחירת חשבון עבור חשבונות בדומיין הזה. כדי לבצע אופטימיזציה לחשבונות ארגוניים ב-Google Cloud באופן כללי, במקום רק לדומיין ארגוני אחד ב-Google Cloud, מגדירים ערך של כוכב (*): hd=*. אל תסתמכו על אופטימיזציית ממשק המשתמש הזו כדי לקבוע מי יכול לגשת לאפליקציה, כי אפשר לשנות בקשות בצד הלקוח. חשוב validate שלאסימון המזהה המוחזר יש ערך הצהרה hd שתואם למה שציפיתם (למשל mycolledge.edu). בניגוד לפרמטר הבקשה, הצהרת ה-hd באסימון המזהה נכללת באסימון אבטחה מ-Google, כך שאפשר לסמוך על הערך. |
include_granted_scopes | (אופציונלי) | אם הפרמטר הזה מסופק עם הערך true, ובקשת ההרשאה מאושרת, ההרשאה תכלול את כל ההרשאות הקודמות שהוקצו לשילוב הזה של משתמש/אפליקציה להיקפים אחרים. מידע נוסף זמין במאמר הרשאה מצטברת.חשוב לזכור שאי אפשר לבצע הרשאה מצטברת בתהליך של אפליקציה מותקנת. |
login_hint | (אופציונלי) | כשהאפליקציה יודעת איזה משתמש היא מנסה לאמת, היא יכולה לספק את הפרמטר הזה בתור רמז לשרת האימות. העברת ההצעה הזו תשבית את חלון הבחירה של החשבון ותמלא מראש את תיבת האימייל בטופס הכניסה, או תבחר את הסשן המתאים (אם המשתמש משתמש בכניסה בכמה חשבונות). כך תוכלו למנוע בעיות שקשורות להתחברות לחשבון המשתמש הלא נכון באפליקציה. הערך יכול להיות כתובת אימייל או המחרוזת sub, שמקבילה למזהה Google של המשתמש. |
prompt | (אופציונלי) | רשימה של ערכי מחרוזות מופרדים ברווחים, שמציינת אם שרת ההרשאות יבקש מהמשתמש לבצע אימות חוזר ולהסכים. הערכים האפשריים הם: none שרת ההרשאות לא מציג מסכי אימות או הסכמה של משתמשים. הוא יחזיר הודעת שגיאה אם המשתמש עדיין לא מאומת ולא הגדיר מראש הסכמה להיקפי הגישה המבוקשים. אפשר להשתמש ב-none כדי לבדוק אם יש אימות קיים ו/או הסכמה. consent שרת ההרשאות מבקש מהמשתמש להביע הסכמה לפני שהוא מחזיר מידע ללקוח. select_account שרת ההרשאה מבקש מהמשתמש לבחור חשבון משתמש. כך משתמש שיש לו כמה חשבונות בשרת ההרשאות יכול לבחור מבין כמה חשבונות שעשויים להיות לו סשנים פעילים. אם לא צוין ערך והמשתמש לא העניק גישה בעבר, יוצג לו מסך הסכמה. |
אימות של אסימון מזהה
עליכם לאמת את כל אסימוני המזהה בשרת, אלא אם אתם יודעים שהם הגיעו ישירות מ-Google. לדוגמה, השרת צריך לאמת את האותנטיות של כל טוקני הזיהוי שהוא מקבל מאפליקציות הלקוח.
אלה מצבים נפוצים שבהם יכול להיות שתשלחו אסימונים מזהים לשרת:
- שליחת אסימונים מזהים עם בקשות שצריך לאמת. אסימונים מזהים מאפשרים לכם לדעת מהו המשתמש הספציפי ששלח את הבקשה, ולמי הוקצה אסימון המזהה.
אסימוני מזהה הם מידע רגיש, ואפשר לעשות בו שימוש לרעה אם הוא יאוחזר. כדי להבטיח שהאסימונים האלה יטופלו בצורה מאובטחת, צריך להעביר אותם רק דרך HTTPS, ולהשתמש רק בנתוני POST או בכותרות של בקשות. אם אתם שומרים טוקנים מזהים בשרת, עליכם גם לאחסן אותם באופן מאובטח.
אחד מהיתרונות של אסימונים מזהים הוא העובדה שאפשר להעביר אותם בין רכיבים שונים באפליקציה. הרכיבים האלה יכולים להשתמש באסימון מזהה כמנגנון אימות קל לאימות האפליקציה והמשתמש. עם זאת, כדי שתוכלו להשתמש במידע באסימון המזהה או להסתמך עליו כטענת נכוֹנוּת (assertion) על כך שהמשתמש עבר אימות, חובה לאמת אותו.
תיקוף של אסימון מזהה מחייב כמה שלבים:
- מוודאים שהאסימון המזהה נחתם כראוי על ידי המנפיק. אסימונים שהונפקו על ידי Google חותמים באמצעות אחד מהאישורים שנמצאים בכתובת ה-URI שצוינה בערך המטא-נתונים
jwks_uri
של מסמך Discovery. - מוודאים שהערך של הצהרת
iss
באסימון המזהה שווה ל-https://accounts.google.com
או ל-accounts.google.com
. - מוודאים שהערך של הצהרת
aud
בטוקן המזהה שווה למזהה הלקוח של האפליקציה. - מוודאים שזמן התפוגה (הצהרת
exp
) של אסימון המזהה לא חלף. - אם ציינתם ערך של פרמטר hd בבקשה, עליכם לוודא שבאסימון המזהה יש הצהרת
hd
שתואמת לדומיין מקובל שמשויך לארגון ב-Google Cloud.
שלבים 2 עד 5 כוללים רק השוואות בין מחרוזות ותאריכים, שהן די פשוטות, ולכן לא נדון בהן כאן.
השלב הראשון הוא מורכב יותר, והוא כולל בדיקת חתימה קריפטוגרפית. למטרות ניפוי באגים, אפשר להשתמש בנקודת הקצה tokeninfo
של Google כדי להשוות לעיבוד המקומי שמוטמע בשרת או במכשיר. נניח שהערך של אסימון המזהה הוא XYZ123
. לאחר מכן, מבטלים את ההפניה למזהה ה-URI https://oauth2.googleapis.com/tokeninfo?id_token=XYZ123
. אם החתימה על האסימון תקינה, התגובה תהיה המטען הייעודי של ה-JWT בפורמט אובייקט ה-JSON שעבר פענוח.
נקודת הקצה tokeninfo
שימושית לניפוי באגים, אבל למטרות ייצור, צריך לאחזר את המפתחות הציבוריים של Google מנקודת הקצה של המפתחות ולבצע את האימות באופן מקומי. צריך לאחזר את כתובת ה-URI של המפתחות ממסמך הגילוי באמצעות ערך המטא-נתונים jwks_uri
. יכול להיות שהבקשות לנקודת הקצה לניפוי באגים יאוטלו או יהיו נתונות לשגיאות לסירוגין.
Google משנה את המפתחות הציבוריים שלה רק לעיתים רחוקות, כך שאפשר לשמור אותם במטמון באמצעות ההנחיות למטמון בתגובה ל-HTTP, וברוב המקרים לבצע אימות מקומי בצורה יעילה הרבה יותר מאשר באמצעות נקודת הקצה tokeninfo
. כדי לבצע את האימות הזה, צריך לאחזר ולנתח אישורים ולבצע את הקריאות הקריפטוגרפיות המתאימות כדי לבדוק את החתימה. למרבה המזל, יש ספריות שעבר תיקון באגים זמינות במגוון רחב של שפות שאפשר להשתמש בהן כדי להשיג את זה (ראו jwt.io).
אחזור פרטים מפרופיל המשתמש
כדי לקבל פרטי פרופיל נוספים על המשתמש, אפשר להשתמש באסימון הגישה (שהאפליקציה מקבלת במהלך תהליך האימות) ובתקן OpenID Connect:
- כדי לעמוד בדרישות של OpenID, צריך לכלול את ערכי ההיקף openid profile בבקשת האימות.
אם רוצים לכלול את כתובת האימייל של המשתמש, אפשר לציין ערך היקף נוסף של email. כדי לציין גם אתprofile
וגם אתemail
, אפשר לכלול את הפרמטר הבא ב-URI של בקשת האימות:
scope=openid%20profile%20email - מוסיפים את אסימון הגישה לכותרת ההרשאה ושולחים בקשת
GET
מסוג HTTPS לנקודת הקצה של userinfo. צריך לאחזר את נקודת הקצה הזו ממסמך Discovery באמצעות הערך של המטא-נתוניםuserinfo_endpoint
. התגובה של userinfo כוללת מידע על המשתמש, כפי שמתואר ב-OpenID Connect Standard Claims, ואת ערך המטא-נתוניםclaims_supported
של מסמך Discovery. המשתמשים או הארגונים שלהם יכולים לבחור לספק או להשמיט שדות מסוימים, כך שיכול להיות שלא תקבלו מידע לגבי כל השדות בהיקפי הגישה המורשים שלכם.
מסמך Discovery
פרוטוקול OpenID Connect מחייב שימוש במספר נקודות קצה לאימות משתמשים ולבקשת משאבים, כולל אסימונים, פרטי משתמשים ומפתחות ציבוריים.
כדי לפשט את ההטמעות ולהגדיל את הגמישות, ב-OpenID Connect אפשר להשתמש ב'מסמך איתור', מסמך JSON שנמצא במיקום ידוע ומכיל צמדי מפתח/ערך שמספקים פרטים על ההגדרות של ספק OpenID Connect, כולל מזהי ה-URI של נקודות הקצה של ההרשאה, האסימון, הביטול, פרטי המשתמש והמפתחות הציבוריים. אפשר לאחזר את מסמך הגילוי של שירות OpenID Connect של Google מהמקומות הבאים:
https://accounts.google.com/.well-known/openid-configuration
כדי להשתמש בשירותי OpenID Connect של Google, צריך להטמיע את ה-URI של מסמך הגילוי (https://accounts.google.com/.well-known/openid-configuration
) באפליקציה. האפליקציה מאחזרת את המסמך, מחילה על התגובה כללי שמירת מטמון ולאחר מכן מאחזרת ממנו את מזהי ה-URI של נקודות הקצה לפי הצורך. לדוגמה, כדי לאמת משתמש, הקוד ימשוך את ערך המטא-נתונים authorization_endpoint
(https://accounts.google.com/o/oauth2/v2/auth
בדוגמה הבאה) בתור ה-URI הבסיסי לבקשות האימות שנשלחות ל-Google.
לפניכם דוגמה למסמך כזה. שמות השדות הם אלה שצוינו ב-OpenID Connect Discovery 1.0 (המשמעות שלהם מפורטת במסמך הזה). הערכים הם להמחשה בלבד ועשויים להשתנות, למרות שהם מועתקים מגרסה עדכנית של מסמך Google Discovery:
{ "issuer": "https://accounts.google.com", "authorization_endpoint": "https://accounts.google.com/o/oauth2/v2/auth", "device_authorization_endpoint": "https://oauth2.googleapis.com/device/code", "token_endpoint": "https://oauth2.googleapis.com/token", "userinfo_endpoint": "https://openidconnect.googleapis.com/v1/userinfo", "revocation_endpoint": "https://oauth2.googleapis.com/revoke", "jwks_uri": "https://www.googleapis.com/oauth2/v3/certs", "response_types_supported": [ "code", "token", "id_token", "code token", "code id_token", "token id_token", "code token id_token", "none" ], "subject_types_supported": [ "public" ], "id_token_signing_alg_values_supported": [ "RS256" ], "scopes_supported": [ "openid", "email", "profile" ], "token_endpoint_auth_methods_supported": [ "client_secret_post", "client_secret_basic" ], "claims_supported": [ "aud", "email", "email_verified", "exp", "family_name", "given_name", "iat", "iss", "locale", "name", "picture", "sub" ], "code_challenge_methods_supported": [ "plain", "S256" ] }
כדי להימנע מטריק חזרה (round-trip) של HTTP, אפשר לשמור במטמון את הערכים ממסמך הגילוי. נעשה שימוש בכותרות HTTP רגילות לשמירת נתונים במטמון, וצריך לפעול בהתאם להן.
ספריות לקוח
ספריות הלקוח הבאות מאפשרות לשלב את OAuth 2.0 עם מסגרות פופולריות, וכך ליישם אותו בקלות רבה יותר:
- Google APIs Client Library for Java
- Google APIs Client Library ל-Python
- Google APIs Client Library for .NET
- Google APIs Client Library for Ruby
- Google APIs Client Library for PHP
- OAuth 2.0 Library for Google Web Toolkit
- Google Toolbox למנהלי OAuth 2.0 ב-Mac
תאימות ל-OpenID Connect
מערכת האימות של Google ל-OAuth 2.0 תומכת בתכונות הנדרשות של מפרט OpenID Connect Core. כל לקוח שמיועד לעבודה עם OpenID Connect אמור לפעול בשיתוף פעולה עם השירות הזה (למעט אובייקט הבקשה של OpenID).