אפשר להשתמש בממשקי ה-API של Google OAuth 2.0 גם לאימות וגם להרשאה. במסמך הזה מתואר יישום OAuth 2.0 שלנו לאימות, שתואם למפרט OpenID Connect ומאושר על ידי OpenID. התיעוד שמופיע במאמר שימוש ב-OAuth 2.0 לגישה ל-Google APIs רלוונטי גם לשירות הזה. אם רוצים לבדוק את הפרוטוקול הזה באופן אינטראקטיבי, מומלץ להשתמש ב-Google OAuth 2.0 Playground. כדי לקבל עזרה ב-Stack Overflow, צריך לתייג את השאלות בתג google-oauth.
הגדרת OAuth 2.0
כדי שהאפליקציה תוכל להשתמש במערכת האימות OAuth 2.0 של Google לצורך כניסת משתמשים, צריך להגדיר פרויקט ב- מסוף Google Cloud כדי לקבל פרטי כניסה של OAuth 2.0, להגדיר URI של הפניה אוטומטית, ובאופן אופציונלי, להתאים אישית את פרטי המיתוג שהמשתמשים רואים במסך הסכמת המשתמש. אפשר גם להשתמש במסוף Cloud כדי ליצור חשבון שירות, להפעיל חיוב, להגדיר סינון ולבצע משימות אחרות. לפרטים נוספים, אפשר לעיין בעזרה של Google Cloud Console.
קבלת פרטי כניסה של OAuth 2.0
אתם צריכים פרטי כניסה של OAuth 2.0, כולל מזהה לקוח וסוד לקוח, כדי לאמת משתמשים ולקבל גישה לממשקי ה-API של Google.
כדי לראות את מזהה הלקוח ואת הסוד של הלקוח עבור פרטי כניסה מסוימים של OAuth 2.0, לוחצים על הטקסט הבא: Select credential (בחירת פרטי כניסה). בחלון שנפתח, בוחרים את הפרויקט ואת פרטי הכניסה הרצויים, ואז לוחצים על View (הצגה).
אפשר גם לראות את מזהה הלקוח ואת הסוד של הלקוח בדף Clients ב-Cloud Console:
- עוברים אל דף הלקוחות.
- לוחצים על שם הלקוח או על סמל העריכה (create). מזהה הלקוח והסוד שלו מופיעים בחלק העליון של הדף.
הגדרת URI של הפניה אוטומטית
ה-URI של ההפניה האוטומטית שמוגדר ב-Cloud Console קובע לאן Google שולחת תגובות לבקשות האימות שלכם.
כדי ליצור, להציג או לערוך את כתובות ה-URI להפניה אוטומטית של פרטי כניסה מסוימים מסוג OAuth 2.0, צריך לבצע את הפעולות הבאות:
- עוברים אל דף הלקוחות.
- לוחצים על הלקוח.
- צפייה ב-URI של ההפניה או עריכה שלו.
אם אין לקוח ברשימה בדף Clients (לקוחות), סימן שלפרויקט אין פרטי כניסה של OAuth. כדי ליצור פרטי כניסה, לוחצים על Create client (יצירת לקוח).
התאמה אישית של מסך בקשת ההסכמה
חוויית האימות של OAuth 2.0 כוללת מסך הסכמה שבו מתואר המידע שהמשתמש משתף והתנאים שחלים עליו. לדוגמה, כשהמשתמש מתחבר, יכול להיות שהוא יתבקש לתת לאפליקציה שלכם גישה לכתובת האימייל ולפרטי החשבון הבסיסיים שלו. אתם מבקשים גישה למידע הזה באמצעות הפרמטר scope, שהאפליקציה שלכם כוללת בבקשת האימות שלה. אתם יכולים גם להשתמש בהיקפי הרשאות כדי לבקש גישה ל-Google APIs אחרים.
במסך ההסכמה מהמשתמש מוצג גם מידע על המיתוג, כמו שם המוצר, הלוגו וכתובת ה-URL של דף הבית. אתם שולטים במידע על המיתוג במסוף Cloud.
כדי להפעיל את מסך ההסכמה של הפרויקט:
- פותחים את הדף Branding במסוף Google Cloud.
- אם מתבקשים, בוחרים פרויקט או יוצרים פרויקט חדש.
- ממלאים את הטופס ולוחצים על שמירה.
בתיבת הדו-שיח להבעת הסכמה שמוצגת בהמשך אפשר לראות מה משתמש יראה כשבקשה כוללת שילוב של היקפי הרשאות של OAuth 2.0 ושל Google Drive. (תיבת הדו-שיח הגנרית הזו נוצרה באמצעות Google OAuth 2.0 Playground, ולכן היא לא כוללת מידע על מיתוג שמוגדר ב-Cloud Console).
גישה לשירות
Google וצדדים שלישיים מספקים ספריות שבהן אפשר להשתמש כדי לטפל בהרבה פרטים בהטמעה של אימות משתמשים וקבלת גישה ל-Google APIs. דוגמאות לכך הן Google Identity Services וספריות הלקוח של Google, שזמינות למגוון פלטפורמות.
אם אתם בוחרים לא להשתמש בספרייה, אתם צריכים לפעול לפי ההוראות שבהמשך המסמך הזה, שמתארות את תהליכי הבקשות מסוג HTTP שמהווים את הבסיס לספריות הזמינות.
אימות המשתמש
אימות המשתמש כולל קבלת אסימון מזהה ואימות שלו. אסימונים מזהים הם תכונה סטנדרטית של OpenID Connect שנועדה לשיתוף הצהרות זהות באינטרנט.
הגישות הנפוצות ביותר לאימות משתמש ולקבלת טוקן מזהה נקראות תהליך 'השרת' ותהליך 'המשתמע'. תהליך השרת מאפשר לשרת הבק-אנד של אפליקציה לאמת את הזהות של האדם שמשתמש בדפדפן או במכשיר נייד. תהליך המשתמע משמש כשאפליקציה בצד הלקוח (בדרך כלל אפליקציית JavaScript שפועלת בדפדפן) צריכה לגשת ישירות לממשקי API במקום להשתמש בשרת הבק-אנד שלה.
במאמר הזה מוסבר איך לבצע את תהליך השרת לאימות המשתמש. זרם הענקת הגישה המשתמע מסובך הרבה יותר בגלל סיכוני האבטחה שקיימים בטיפול באסימונים ובשימוש בהם בצד הלקוח. אם אתם צריכים להטמיע זרם הענקת גישה משתמע, מומלץ מאוד להשתמש בGoogle Identity Services.
תהליך העבודה של השרת
חשוב להגדיר את האפליקציה במסוף Cloud כדי לאפשר לה להשתמש בפרוטוקולים האלה ולאמת את המשתמשים. כשמשתמש מנסה להיכנס באמצעות חשבון Google, צריך:
- יצירת טוקן למניעת זיוף בקשות
- שליחת בקשת אימות ל-Google
- אישור הטוקן למניעת זיוף
- המרת
codeלאסימון גישה ולאסימון מזהה - קבלת פרטי משתמש מטוקן המזהה
- אימות המשתמש
1. יצירת טוקן למניעת זיוף
עליכם להגן על אבטחת המשתמשים שלכם ולמנוע התקפות זיוף בקשות. השלב הראשון הוא יצירת טוקן סשן ייחודי שמכיל את הסטטוס בין האפליקציה לבין הלקוח של המשתמש. בהמשך, אתם משווים את טוקן הסשן הייחודי הזה לתגובת האימות שמוחזרת על ידי שירות הכניסה באמצעות OAuth של Google, כדי לוודא שהמשתמש הוא זה ששולח את הבקשה ולא תוקף זדוני. האסימונים האלה נקראים לעיתים קרובות אסימוני CSRF (cross-site request forgery, זיוף בקשות בין אתרים).
אפשרות טובה לטוקן של מצב היא מחרוזת של כ-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', $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}\\s*CLIENT_ID\\s*[}]{2}", CLIENT_ID) .replaceAll("[{]{2}\\s*STATE\\s*[}]{2}", state) .replaceAll("[{]{2}\\s*APPLICATION_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
השלב הבא הוא יצירת בקשת HTTPS GET עם פרמטרים מתאימים של URI.
שימו לב שבכל השלבים בתהליך הזה נעשה שימוש ב-HTTPS ולא ב-HTTP. חיבורי HTTP נדחים. צריך לאחזר את כתובת ה-URI הבסיסית ממסמך Discovery באמצעות ערך המטא-נתונים authorization_endpoint. בדיון הבא נניח שכתובת ה-URI הבסיסית היא https://accounts.google.com/o/oauth2/v2/auth.
כדי ליצור בקשה בסיסית, צריך לציין את הפרמטרים הבאים:
client_id, שאפשר לקבל מתוך Cloud Console דף הלקוחות .-
response_type, שבבקשה בסיסית להרשאה באמצעות קוד צריך להיותcode. (מידע נוסף זמין בכתובתresponse_type). -
scope, שבבקשה בסיסית צריך להיותopenid email. (מידע נוסף זמין בכתובתscope). -
redirect_uriצריכה להיות נקודת הקצה של HTTP בשרת שלכם שתקבל את התגובה מ-Google. הערך חייב להיות זהה לאחד מכתובות ה-URI המורשות להפניה אוטומטית של לקוח OAuth 2.0, שהגדרתם בדף 'אמצעי אימות' במסוף Cloud. אם הערך הזה לא תואם ל-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//developers.google.com/oauthplayground& 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 שציינתם בבקשה. כל התשובות מוחזרות במחרוזת השאילתה:
https://developers.google.com/oauthplayground?state=security_token%3D138r5719ru3e1%26url%3Dhttps%3A%2F%2Foa2cb.example.com%2FmyHome&code=4/P7q7W91a-oMsCeLvIaQm6bTrgtp7&scope=openid%20email%20https://www.googleapis.com/auth/userinfo.email
בהתאם ל-RFC 6749, הלקוחות חייבים להתעלם מפרמטרים של תגובה שלא מזוהים. בשרת, צריך לוודא שאסימון הסשן 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, קוד הרשאה חד-פעמי שהשרת יכול להמיר לטוקן גישה ולטוקן מזהה. השרת שלכם מבצע את ההחלפה הזו על ידי שליחת בקשת HTTPS POST. בקשת POST נשלחת לנקודת הקצה של האסימון, שאותה צריך לאחזר ממסמך Discovery באמצעות ערך המטא-נתונים token_endpoint. בדיון הבא אנחנו מניחים שנקודת הקצה היא
https://oauth2.googleapis.com/token. הבקשה חייבת לכלול את הפרמטרים הבאים בגוף POST:
| שדות | |
|---|---|
code |
קוד ההרשאה שמוחזר מהבקשה הראשונית. |
client_id |
מזהה הלקוח שקיבלתם מ-Cloud Console, בדף Clients, כמו שמתואר במאמר קבלת פרטי כניסה של OAuth 2.0. |
client_secret |
סוד הלקוח שמתקבל מ-Cloud Console, בדף Clients, כמו שמתואר במאמר קבלת פרטי כניסה של OAuth 2.0. |
redirect_uri |
כתובת URI מורשית להפניה אוטומטית עבור client_id שצוין בדף הלקוחות ב-Cloud Console, כמו שמתואר במאמר הגדרת כתובת 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//developers.google.com/oauthplayground& grant_type=authorization_code
תגובה תקינה לבקשה הזו מכילה את השדות הבאים במערך JSON:
| שדות | |
|---|---|
access_token |
אסימון שאפשר לשלוח ל-Google API. |
expires_in |
משך החיים שנותר של אסימון הגישה בשניות. |
id_token |
JWT שמכיל פרטי זהות של המשתמש, שעליו חתמה Google באופן דיגיטלי. |
scope |
היקפי הגישה שניתנו על ידי access_token מוצגים כרשימה של מחרוזות שמופרדות ברווחים ותלויות באותיות רישיות. |
token_type |
מציין את סוג הטוקן שמוחזר. בשלב הזה, הערך של השדה הזה הוא תמיד
Bearer.
|
refresh_token |
(אופציונלי)
השדה הזה מופיע רק אם הפרמטר |
5. קבלת מידע על המשתמש מאסימון המזהה
אסימון מזהה הוא JWT (JSON Web Token), כלומר אובייקט JSON שמקודד ב-Base64 ונחתם באופן קריפטוגרפי. בדרך כלל, חשוב מאוד לאמת אסימון מזהה לפני שמשתמשים בו, אבל מכיוון שאתם מתקשרים ישירות עם Google דרך ערוץ HTTPS ללא מתווך ומשתמשים בסוד הלקוח כדי לאמת את עצמכם ב-Google, אתם יכולים להיות בטוחים שהאסימון שאתם מקבלים באמת מגיע מ-Google ותקף. אם השרת מעביר את האסימון המזהה לרכיבים אחרים באפליקציה, חשוב מאוד שהרכיבים האחרים יאמתו את האסימון לפני השימוש בו.
ברוב ספריות ה-API, האימות משולב עם פענוח הערכים בקידוד base64url וניתוח ה-JSON, ולכן סביר להניח שתבצעו אימות של הטוקן בכל מקרה כשתיגשו לטענות בטוקן הזהות.
המטען הייעודי (payload) של אסימון מזהה
טוקן ID הוא אובייקט 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 עשויים להכיל את השדות הבאים (שנקראים claims):
| מימוש | הוגדרו | תיאור |
|---|---|---|
aud |
תמיד | קהל היעד שאליו מיועד אסימון ה-ID הזה. הוא חייב להיות אחד ממזהי הלקוח ב-OAuth 2.0 של האפליקציה. |
exp |
תמיד | תאריך התפוגה שעד אליו או אחריו אסור לקבל את אסימון הזהות. התאריך מיוצג בפורמט של חותמת זמן של מערכת Unix (מספר שלם של שניות). |
iat |
תמיד | השעה שבה הונפק אסימון הזהות. הערך מוצג כזמן ראשית זמן יוניקס (מספר שלם של שניות). |
iss |
תמיד | מזהה המנפיק של המנפיק של התגובה. תמיד https://accounts.google.com או accounts.google.com עבור אסימוני מזהה של Google. |
sub |
תמיד | מזהה של המשתמש, ייחודי בין כל חשבונות Google וללא שימוש חוזר. לחשבון Google יכולות להיות כמה כתובות אימייל בנקודות זמן שונות, אבל הערך של sub אף פעם לא משתנה. אפשר להשתמש ב-sub באפליקציה כמפתח מזהה ייחודי של המשתמש. אורך מקסימלי של 255 תווים ב-ASCII, רגישים לאותיות רישיות. |
amr |
מערך JSON של מחרוזות שמזהות את שיטות האימות ששימשו לכניסה לחשבון Google. אם המערך קיים, הוא כולל ערך אחד או יותר מהערכים האפשריים האלה [IANA.AMR]:
amr נכללת בבקשת
האימות ומופעלת בהגדרות.
|
|
auth_time |
הזמן שבו התבצע אימות המשתמש, מספר בפורמט JSON שמייצג את מספר השניות שחלפו מאז ראשית זמן יוניקס (1 בינואר 1970, 00:00:00 UTC). הערך הזה מסופק אם התביעה auth_time כלולה בבקשת האימות ומופעלת בהגדרות.
|
|
at_hash |
גיבוב של טוקן הגישה. מספק אימות לכך שטוקן הגישה קשור לטוקן הזהות. אם טוקן הזהות מונפק עם ערך access_token בתהליך בצד השרת, ההצהרה הזו תמיד כלולה. אפשר להשתמש בהצהרה הזו כמנגנון חלופי להגנה מפני התקפות זיוף בקשות בין אתרים, אבל אם פועלים לפי שלב 1 ושלב 3, אין צורך לאמת את טוקן הגישה. |
|
azp |
client_id של המציג המורשה. הטענה הזו נדרשת רק אם הצד שמבקש את טוקן ה-ID הוא לא אותו צד שמוגדר כקהל של טוקן ה-ID. זה יכול לקרות ב-Google באפליקציות היברידיות שבהן לאפליקציית אינטרנט ולאפליקציית Android יש client_id שונה של OAuth 2.0, אבל הן חולקות את אותו פרויקט Google APIs. |
|
email |
כתובת האימייל של המשתמש. המידע הזה מסופק רק אם כללתם את היקף ההרשאות 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 |
השם המלא של המשתמש, בפורמט שניתן להצגה. אפשר לציין זאת במקרים הבאים:
אם יש טענות של |
|
nonce |
הערך של nonce שסופק על ידי האפליקציה שלכם בבקשת האימות.
כדי להגן מפני התקפות שליחה מחדש, צריך להציג את הערך הזה רק פעם אחת. |
|
picture |
כתובת ה-URL של תמונת הפרופיל של המשתמש. אפשר לציין זאת במקרים הבאים:
אם יש טענות של |
|
profile |
כתובת ה-URL של דף הפרופיל של המשתמש. אפשר לציין זאת במקרים הבאים:
אם יש טענות של |
6. אימות המשתמש
אחרי שמקבלים את פרטי המשתמש מטוקן ה-ID, צריך לשלוח שאילתה למסד הנתונים של המשתמשים באפליקציה. אם המשתמש כבר קיים במסד הנתונים שלכם, צריך להתחיל סשן של האפליקציה עבור המשתמש הזה אם התשובה של Google API עומדת בכל דרישות הכניסה.
אם המשתמש לא קיים במסד נתוני המשתמשים שלכם, צריך להפנות אותו לתהליך ההרשמה למשתמשים חדשים. יכול להיות שתוכלו לרשום את המשתמש באופן אוטומטי על סמך המידע שקיבלתם מ-Google, או לפחות למלא מראש חלק גדול מהשדות שנדרשים בטופס ההרשמה. בנוסף למידע באסימון המזהה, אפשר לקבל מידע נוסף על פרופיל המשתמש בנקודות הקצה של פרופיל המשתמש שלנו.
נושאים מתקדמים
בקטעים הבאים מפורט מידע נוסף על Google OAuth 2.0 API. המידע הזה מיועד למפתחים עם דרישות מתקדמות בנושא אימות והרשאות.
גישה ל-Google APIs אחרים
אחד היתרונות של שימוש ב-OAuth 2.0 לאימות הוא שהאפליקציה יכולה לקבל הרשאה להשתמש בממשקי API אחרים של Google בשם המשתמש (כמו YouTube, Google Drive, Calendar או אנשי קשר) בו-זמנית עם אימות המשתמש. כדי לעשות זאת, צריך לכלול את היקפי ההרשאות האחרים שנדרשים בבקשת האימות ששולחים ל-Google. לדוגמה, כדי להוסיף את קבוצת הגיל של המשתמש לבקשת האימות, צריך להעביר פרמטר של היקף הרשאות openid email https://www.googleapis.com/auth/profile.agerange.read. המשתמש יקבל הנחיות מתאימות במסך ההסכמה. אסימון הגישה שמתקבל מ-Google יאפשר לאפליקציה לגשת לכל ממשקי ה-API שקשורים להיקפי הגישה שביקשתם וקיבלתם.
אסימוני רענון
בבקשה לגישה ל-API, אפשר לבקש שהטוקן לרענון יוחזר במהלך codeההחלפה. אסימון רענון מספק לאפליקציה גישה רציפה לממשקי Google API בזמן שהמשתמש לא נמצא באפליקציה. כדי לבקש טוקן רענון, צריך להוסיף את הפרמטר access_type עם הערך offline אל בקשת האימות.
שיקולים:
- חשוב לשמור את טוקן הרענון בצורה בטוחה וקבועה, כי אפשר לקבל טוקן רענון רק בפעם הראשונה שמבצעים את תהליך החלפת הקוד.
- יש מגבלות על מספר טוקני הרענון שמונפקים: מגבלה אחת לכל שילוב של לקוח/משתמש, ומגבלה נוספת לכל משתמש בכל הלקוחות. אם האפליקציה מבקשת יותר מדי אסימוני רענון, היא עלולה להגיע למגבלות האלה, ובמקרה כזה אסימוני רענון ישנים יותר יפסיקו לפעול.
מידע נוסף זמין במאמר בנושא רענון של אסימון גישה (גישה במצב אופליין).
בקשת הסכמה מחדש
כדי לבקש מהמשתמש לאשר מחדש את הגישה לאפליקציה, צריך להגדיר את הפרמטר prompt לערך consent בבקשת האימות. אם prompt=consent כלול, מסך ההסכמה מוצג בכל פעם שהאפליקציה מבקשת הרשאה להיקפי גישה, גם אם כל ההיקפים כבר הוענקו לפרויקט Google APIs. לכן, כדאי להשתמש ב-prompt=consent רק כשצריך.
מידע נוסף על הפרמטר prompt מופיע בטבלה פרמטרים של URI לאימות, בשורה prompt.
פרמטרים של URI לאימות
בטבלה הבאה מפורטים תיאורים מלאים יותר של הפרמטרים שמתקבלים על ידי Google's OAuth 2.0 authentication API.
| פרמטר | חובה | תיאור | ||||||
|---|---|---|---|---|---|---|---|---|
client_id |
(נדרש) | מחרוזת מספר הלקוח שמתקבלת מדף הלקוחות ב-Cloud Console, כמו שמתואר במאמר קבלת פרטי כניסה של OAuth 2.0. | ||||||
nonce |
(נדרש) | ערך אקראי שנוצר על ידי האפליקציה ומאפשר הגנה מפני הפעלה חוזרת. | ||||||
response_type |
(נדרש) | אם הערך הוא code, מופעל תהליך הרשאה באמצעות קוד, שדורש POST לנקודת הקצה של הטוקן כדי לקבל את הטוקנים. אם הערך הוא token id_token או id_token token, מופעל זרם הענקת גישה משתמע, שדורש שימוש ב-JavaScript בכתובת ה-URI להפניה אוטומטית כדי לאחזר טוקנים ממזהה ה-URI #fragment. |
||||||
redirect_uri |
(נדרש) | קובע לאן התשובה תישלח. הערך של הפרמטר הזה צריך להיות זהה לאחד מערכי ההפניה האוטומטית המורשים שהגדרתם בדף 'לקוחות' במסוף Cloud (כולל סכימת ה-HTTP או ה-HTTPS, האותיות הגדולות והקטנות והסלאש בסוף, אם יש). | ||||||
scope |
(נדרש) | פרמטר ההיקף חייב להתחיל בערך אם קיים ערך ההיקף אם יש ערך של היקף בנוסף להיקפי ההרשאות הספציפיים ל-OpenID, ארגומנט היקף ההרשאות יכול לכלול גם ערכים אחרים של היקפי הרשאות. צריך להפריד בין כל הערכים של היקף ההרשאה באמצעות רווח. לדוגמה, אם רוצים גישה לכל קובץ ב-Google Drive של משתמש, פרמטר ההיקף יכול להיות למידע על היקפי ההרשאות הזמינים, אפשר לעיין במאמר היקפי ההרשאות של OAuth 2.0 ל-Google APIs או במסמכי התיעוד של Google API שרוצים להשתמש בו. |
||||||
state |
(אופציונלי, אבל מומלץ מאוד) | מחרוזת אטומה שמועברת הלוך ושוב בפרוטוקול. כלומר, היא מוחזרת כפרמטר של URI בתהליך הבסיסי, וכמזהה של URI הפרמטר |
||||||
access_type |
(אופציונלי) | הערכים המותרים הם offline ו-online. ההשפעה מתועדת במאמר בנושא גישה אופליין. אם מתבצעת בקשה לטוקן גישה, הלקוח לא מקבל טוקן רענון אלא אם מצוין הערך offline. |
||||||
claims |
(אופציונלי) | הפרמטר
claims משמש לציון שדה אופציונלי אחד או יותר שייכללו בתגובות של נקודת הקצה userinfo או של אסימון המזהה של בקשת האימות. הערך הוא אובייקט JSON שמכיל את סוג התגובה ואת ההצהרות המבוקשות. השרתים של Google מקבלים את בקשות ההצהרות הבאות:
|
||||||
display |
(אופציונלי) | ערך מחרוזת ASCII שמציין איך שרת ההרשאות מציג את דפי ממשק המשתמש של האימות וההסכמה. הערכים הבאים מצוינים ומתקבלים על ידי השרתים של Google, אבל אין להם השפעה על התנהגות זרימת הפרוטוקול: page, popup, touch ו-wap. |
||||||
hd |
(אופציונלי) | לייעל את תהליך הכניסה לחשבונות שנמצאים בבעלות של ארגון ב-Google Cloud. אם כוללים את הדומיין של הארגון ב-Google Cloud (לדוגמה, mycollege.edu), אפשר לציין שממשק המשתמש לבחירת חשבון צריך להיות מותאם לחשבונות בדומיין הזה. כדי לבצע אופטימיזציה לחשבונות ארגוניים ב-Google Cloud באופן כללי ולא רק לדומיין ארגוני אחד ב-Google Cloud, מגדירים ערך של כוכבית ( אל תסתמכו על האופטימיזציה הזו של ממשק המשתמש כדי לקבוע למי תהיה גישה לאפליקציה, כי אפשר לשנות בקשות בצד הלקוח. הקפידו לאמת שלערך הטענה של טוקן ה-ID שהוחזר |
||||||
include_granted_scopes |
(אופציונלי) | אם הפרמטר הזה מסופק עם הערך true, ובקשת ההרשאה מאושרת, ההרשאה תכלול את כל ההרשאות הקודמות שניתנו לשילוב הזה של משתמש/אפליקציה עבור היקפים אחרים. מידע נוסף זמין במאמר בנושא הרשאות מצטברות.
שימו לב: אי אפשר לבצע הרשאה מצטברת בתהליך של אפליקציה מותקנת. |
||||||
login_hint |
(אופציונלי) | כשהאפליקציה יודעת איזה משתמש מנסה לבצע אימות, היא יכולה לספק את הפרמטר הזה כרמז לשרת האימות. העברת הרמז הזה משביתה את תיבת הבחירה של החשבון, וממלאת מראש את תיבת האימייל בטופס הכניסה או בוחרת את הסשן המתאים (אם המשתמש משתמש בכניסה מרובה). כך אפשר להימנע מבעיות שמתרחשות אם האפליקציה מתחברת לחשבון משתמש שגוי.
הערך יכול להיות כתובת אימייל או המחרוזת sub, שהיא שוות ערך למזהה Google של המשתמש. |
||||||
prompt |
(אופציונלי) | רשימה של ערכי מחרוזות שמופרדים באמצעות רווחים, שמציינת אם שרת ההרשאות מציג למשתמש בקשה לאימות מחדש ולהסכמה. הערכים האפשריים:
אם לא מציינים ערך והמשתמש לא אישר בעבר את הגישה, מוצג למשתמש מסך הסכמה. |
||||||
hl |
(אופציונלי) | תג שפה BCP 47 שמשמש לציון שפת התצוגה במסכי הכניסה, בחלון לבחירת חשבון ובמסכי בקשת ההסכמה. אם הפרמטר הזה לא מסופק, השפה מוגדרת כברירת מחדל לשפה שמוגדרת בחשבון Google של המשתמש או בהגדרות הדפדפן. לדוגמה, כדי לבקש את ממשק המשתמש באנגלית בריטית, צריך להגדיר את הפרמטר ל-en-GB. |
||||||
אימות של אסימון מזהה
צריך לאמת את כל אסימוני הזהות בשרת, אלא אם אתם יודעים שהם הגיעו ישירות מ-Google. לדוגמה, השרת צריך לאמת את האותנטיות של כל טוקן מזהה שהוא מקבל מאפליקציות הלקוח.
אלה כמה מצבים נפוצים שבהם כדאי לשלוח אסימונים מזהים לשרת:
- שליחת אסימונים מזהים עם בקשות שצריך לאמת. אסימוני המזהה מציינים את המשתמש הספציפי ששולח את הבקשה ואת הלקוח שעבורו הוענק אסימון המזהה.
אסימוני זיהוי הם רגישים, ואם הם נתפסים על ידי גורם לא מורשה, הוא עלול לעשות בהם שימוש לרעה. אתם צריכים לוודא שהאסימונים האלה מטופלים בצורה מאובטחת. לשם כך, צריך להעביר אותם רק באמצעות HTTPS, ורק באמצעות נתוני POST או בכותרות של בקשות. אם אתם מאחסנים אסימוני זיהוי בשרת שלכם, אתם צריכים גם לאחסן אותם בצורה מאובטחת.
אחד היתרונות של אסימונים מזהים הוא שאפשר להעביר אותם בין רכיבים שונים באפליקציה. הרכיבים האלה יכולים להשתמש באסימון מזהה כמנגנון אימות קל משקל לאימות האפליקציה והמשתמש. אבל לפני שמשתמשים במידע באסימון המזהה או מסתמכים עליו כהצהרה שהמשתמש עבר אימות, חובה לאמת אותו.
כדי לאמת אסימון מזהה, צריך לבצע כמה שלבים:
- מוודאים שהטוקן של מזהה חתום כמו שצריך על ידי הרשות המנפיקה. טוקנים שהונפקו על ידי Google חתומים באמצעות אחד מהאישורים שנמצאים ב-URI שצוין בערך
jwks_urimetadata של מסמך Discovery. - מוודאים שהערך של הטענה
issבטוקן המזהה שווה ל-https://accounts.google.comאו ל-accounts.google.com. - מוודאים שהערך של הטענה
audבטוקן המזהה שווה למזהה הלקוח של האפליקציה. - מוודאים שתוקף האסימון (טענת
exp) לא פג. - אם ציינתם ערך של פרמטר hd בבקשה, צריך לוודא שלטוקן ה-ID יש טענה
hdשתואמת לדומיין מקובל שמשויך לארגון ב-Google Cloud.
בשלבים 2 עד 5 יש רק השוואות של מחרוזות ותאריכים, שהן די פשוטות, ולכן לא נפרט אותן כאן.
השלב הראשון מורכב יותר וכולל בדיקה של חתימה קריפטוגרפית. למטרות ניפוי באגים, אפשר להשתמש בנקודת הקצה tokeninfo של Google כדי להשוות לעיבוד מקומי שהוטמע בשרת או במכשיר. נניח שהערך של אסימון המזהה הוא XYZ123. אחר כך מבטלים את ההפניה של ה-URI
https://oauth2.googleapis.com/tokeninfo?id_token=XYZ123. אם החתימה של הטוקן תקינה, התגובה תהיה המטען הייעודי (payload) של ה-JWT בפורמט של אובייקט JSON מפוענח.
נקודת הקצה tokeninfo שימושית לניפוי באגים, אבל למטרות ייצור, צריך לאחזר את המפתחות הציבוריים של Google מנקודת הקצה של המפתחות ולבצע את האימות באופן מקומי. צריך לאחזר את כתובת ה-URI של המפתחות ממסמך Discovery באמצעות ערך המטא-נתונים jwks_uri. יכול להיות שיהיה ויסות של בקשות לנקודת הקצה של ניפוי הבאגים, או שהן יהיו כפופות לשגיאות לסירוגין.
מכיוון ש-Google משנה את המפתחות הציבוריים שלה רק לעיתים רחוקות, אפשר לשמור אותם במטמון באמצעות פקודות שמירה במטמון של תגובת ה-HTTP. ברוב המקרים, אפשר לבצע אימות מקומי בצורה יעילה יותר מאשר באמצעות נקודת הקצה tokeninfo. כדי לבצע את האימות הזה, צריך לאחזר ולנתח אישורים, ולבצע את הקריאות הקריפטוגרפיות המתאימות כדי לבדוק את החתימה. למרבה המזל, יש ספריות שעברו ניפוי באגים וזמינות במגוון רחב של שפות כדי לבצע את הפעולה הזו (ראו jwt.io).
קבלת פרטים מפרופיל המשתמש
כדי לקבל פרטי פרופיל נוספים על המשתמש, אפשר להשתמש באסימון הגישה (שהאפליקציה מקבלת במהלך תהליך האימות) ובסטנדרט OpenID Connect:
כדי לעמוד בדרישות של OpenID, צריך לכלול את ערכי ההיקף
openid profileבבקשת האימות.אם רוצים לכלול את כתובת האימייל של המשתמש, אפשר לציין ערך נוסף של היקף ההרשאות
email. כדי לציין גם אתprofileוגם אתemail, אפשר לכלול את הפרמטר הבא ב-URI של בקשת האימות:scope=openid%20profile%20email
- מוסיפים את טוקן הגישה לכותרת ההרשאה ושולחים בקשת HTTPS
GETלנקודת הקצה userinfo, שאותה צריך לאחזר ממסמך Discovery באמצעות ערך המטא-נתוניםuserinfo_endpoint. התגובה של userinfo כוללת מידע על המשתמש, כפי שמתואר בOpenID Connect Standard Claimsובערך המטא-נתוניםclaims_supportedשל מסמך Discovery. משתמשים או הארגונים שלהם יכולים לבחור אם לספק שדות מסוימים או לא, ולכן יכול להיות שלא תקבלו מידע לגבי כל שדה בהיקפי הגישה המורשים שלכם.
מסמך Discovery
פרוטוקול OpenID Connect מחייב שימוש בכמה נקודות קצה לאימות משתמשים ולבקשת משאבים, כולל אסימונים, פרטי משתמשים ומפתחות ציבוריים.
כדי לפשט את ההטמעות ולהגדיל את הגמישות, OpenID Connect מאפשר שימוש ב'מסמך Discovery', מסמך JSON שנמצא במיקום ידוע ומכיל צמדי מפתח/ערך שמספקים פרטים על ההגדרה של ספק OpenID Connect, כולל כתובות ה-URI של נקודות הקצה של ההרשאה, הטוקן, הביטול, פרטי המשתמש והמפתחות הציבוריים. אפשר לאחזר את מסמך Discovery של שירות 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 (המשמעויות שלהם מפורטות במסמך הזה). הערכים הם להמחשה בלבד ועשויים להשתנות, למרות שהם הועתקו מגרסה עדכנית של מסמך Discovery בפועל של Google:
{ "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" ] }
אפשר להימנע משימוש ב-HTTP round-trip על ידי שמירת הערכים במטמון ממסמך Discovery. נעשה שימוש בכותרות סטנדרטיות של HTTP לצורך שמירה במטמון, וצריך להתייחס אליהן.
ספריות לקוח
ספריות הלקוח הבאות משולבות עם מסגרות פופולריות, ולכן הן מפשטות את ההטמעה של OAuth 2.0:
תאימות ל-OpenID Connect
מערכת האימות של Google OAuth 2.0 תומכת בתכונות הנדרשות של מפרט OpenID Connect Core. כל לקוח שמיועד לעבוד עם OpenID Connect אמור לפעול עם השירות הזה (למעט אובייקט בקשת OpenID).
