במסמך הזה מוסבר איך אפליקציות של שרת אינטרנט משתמשות בספריות לקוח של Google API או בנקודות קצה של Google OAuth 2.0 כדי להטמיע הרשאה של OAuth 2.0 לגישה לממשקי Google API.
OAuth 2.0 מאפשר למשתמשים לשתף נתונים ספציפיים עם אפליקציה תוך שמירה על הפרטיות של שמות המשתמשים, הסיסמאות והמידע הנוסף שלהם. לדוגמה, אפליקציה יכולה להשתמש ב-OAuth 2.0 כדי לקבל מהמשתמשים הרשאה לאחסן קבצים ב-Google Drive שלהם.
התהליך הזה של OAuth 2.0 מיועד במיוחד להרשאת משתמשים. הוא מיועד לאפליקציות שיכולות לאחסן מידע סודי ולשמור מצב. אפליקציה של שרת אינטרנט עם הרשאה מתאימה יכולה לגשת ל-API בזמן שהמשתמש מקיים אינטראקציה עם האפליקציה או אחרי שהמשתמש עזב את האפליקציה.
אפליקציות של שרת אינטרנט משתמשות לעיתים קרובות גם ב חשבונות שירות כדי לאשר בקשות API, במיוחד כשמבצעים קריאה לממשקי Cloud API כדי לגשת לנתונים שמבוססים על פרויקט ולא לנתונים ספציפיים למשתמש. אפליקציות של שרת אינטרנט יכולות להשתמש בחשבונות שירות בשילוב עם הרשאת משתמש.
ספריות לקוח
בדוגמאות הספציפיות לשפות שבדף הזה נעשה שימוש בספריות הלקוח של Google API כדי להטמיע הרשאות OAuth 2.0. כדי להריץ את דוגמאות הקוד, צריך קודם להתקין את ספריית הלקוח בשפה הרצויה.
כשמשתמשים בספריית הלקוח של Google API כדי לטפל בזרימת OAuth 2.0 של האפליקציה, ספריית הלקוח מבצעת פעולות רבות שהאפליקציה הייתה צריכה לבצע בעצמה בעצמה. לדוגמה, הוא קובע מתי האפליקציה יכולה להשתמש באסימוני גישה שמאוחסנים או לרענן אותם, וגם מתי האפליקציה צריכה לקבל הסכמה מחדש. ספריית הלקוח גם יוצרת כתובות URL נכונות להפניה אוטומטית, ומסייעת להטמיע מנהלים של הפניות אוטומטיות שממירים קודי הרשאה לאסימוני גישה.
ספריות הלקוח של Google API לאפליקציות בצד השרת זמינות בשפות הבאות:
דרישות מוקדמות
הפעלת ממשקי API בפרויקט
כל אפליקציה שמבצעת קריאה ל-Google APIs צריכה להפעיל את ממשקי ה-API האלה ב- API Console.
כדי להפעיל ממשק API בפרויקט:
- Open the API Library ב Google API Console.
- If prompted, select a project, or create a new one.
- ב- API Library מפורטים כל ממשקי ה-API הזמינים, שמקובצים לפי משפחת מוצרים ופופולריות. אם ממשק ה-API שרוצים להפעיל לא מופיע ברשימה, אפשר לחפש אותו או ללחוץ על הצגת הכול במשפחת המוצרים שאליה הוא שייך.
- בוחרים את ה-API שרוצים להפעיל ולוחצים על הלחצן הפעלה.
- If prompted, enable billing.
- If prompted, read and accept the API's Terms of Service.
יצירת פרטי כניסה להרשאה
כל אפליקציה שמשתמשת ב-OAuth 2.0 כדי לגשת ל-Google APIs חייבת לכלול פרטי כניסה שמזהים את האפליקציה לשרת OAuth 2.0 של Google. בשלבים הבאים מוסבר איך ליצור פרטי כניסה לפרויקט. לאחר מכן, האפליקציות שלכם יוכלו להשתמש בפרטי הכניסה כדי לגשת לממשקי ה-API שהפעלתם בפרויקט הזה.
- Go to the Credentials page.
- לוחצים על Create credentials > מזהה לקוח OAuth.
- בוחרים את סוג האפליקציה Web application.
- ממלאים את הטופס ולוחצים על Create. באפליקציות שמשתמשות בשפות ובמסגרות כמו PHP, Java, Python, Ruby ו-NET, צריך לציין מזהי URI להפניה אוטומטית מורשים. מזהי ה-URI להפניה אוטומטית הם נקודות הקצה שאליהן שרת OAuth 2.0 יכול לשלוח תגובות. נקודות הקצה האלה חייבות לעמוד בכללי האימות של Google.
לצורך בדיקה, אפשר לציין מזהי URI שמפנים למכונה המקומית, כמו
http://localhost:8080
. לכן, חשוב לזכור שבכל הדוגמאות במסמך הזה נעשה שימוש ב-http://localhost:8080
בתור ה-URI להפניה אוטומטית.מומלץ לתכנן את נקודות הקצה לאימות של האפליקציה כך שהאפליקציה לא תחשוף קודי הרשאה למשאבים אחרים בדף.
אחרי שיוצרים את פרטי הכניסה, מורידים את הקובץ client_secret.json מה- API Console. שומרים את הקובץ באופן מאובטח במיקום שרק לאפליקציה יש גישה אליו.
זיהוי של היקפי גישה
היקפי הרשאות מאפשרים לאפליקציה לבקש גישה רק למשאבים שנחוצים לה, וגם מאפשרים למשתמשים לשלוט בכמות הגישה שהם מעניקים לאפליקציה. לכן, יכול להיות שיש קשר הפוך בין מספר ההיקפים המבוקשים לבין הסבירות לקבלת הסכמה מהמשתמשים.
לפני שמתחילים להטמיע הרשאה מסוג OAuth 2.0, מומלץ לזהות את היקפי ההרשאות שאליהם האפליקציה תצטרך גישה.
מומלץ גם שהאפליקציה תבקש גישה להיקפי הרשאות באמצעות תהליך הרשאה מצטברת, שבו האפליקציה מבקשת גישה לנתוני המשתמשים בהקשר המתאים. השיטה המומלצת הזו עוזרת למשתמשים להבין בקלות למה האפליקציה צריכה את הרשאת הגישה שהיא מבקשת.
במסמך היקפי הרשאות API של OAuth 2.0 מופיעה רשימה מלאה של ההיקפים שבהם אפשר להשתמש כדי לגשת לממשקי Google APIs.
דרישות ספציפיות לשפה
כדי להריץ כל אחת מדוגמאות הקוד במסמך הזה, יש צורך בחשבון Google, בגישה לאינטרנט ובדפדפן אינטרנט. אם אתם משתמשים באחת מספריות הלקוח של ה-API, כדאי לעיין גם בדרישות הספציפיות לשפה שמפורטות בהמשך.
PHP
כדי להריץ את דוגמאות הקוד של PHP במסמך הזה, צריך:
- PHP מגרסה 5.6 ואילך עם ממשק שורת הפקודה (CLI) ותוסף JSON מותקנים.
- הכלי לניהול יחסי התלות של Composer.
-
ספריית הלקוח של Google APIs ל-PHP:
composer require google/apiclient:^2.10
Python
כדי להריץ את דוגמאות הקוד של Python במסמך הזה, צריך:
- Python בגרסה 2.6 ומעלה
- הכלי לניהול חבילות pip.
- ספריית הלקוח של Google APIs ל-Python:
pip install --upgrade google-api-python-client
google-auth
,google-auth-oauthlib
ו-google-auth-httplib2
להרשאת משתמשים.pip install --upgrade google-auth google-auth-oauthlib google-auth-httplib2
- מסגרת לאפליקציות אינטרנט ב-Python של Flask.
pip install --upgrade flask
- ספריית ה-HTTP
requests
.pip install --upgrade requests
Ruby
כדי להריץ את דוגמאות הקוד ב-Ruby שמפורטות במסמך הזה, צריך:
- Ruby 2.6 ואילך
-
ספריית Google Auth ל-Ruby:
gem install googleauth
-
מסגרת לאפליקציות אינטרנט ב-Ruby של Sinatra.
gem install sinatra
Node.js
כדי להריץ את דוגמאות הקוד של Node.js במסמך הזה, צריך:
- מהדורת LTS לתחזוקה, מהדורת LTS פעילה או מהדורת Node.js הנוכחית.
-
לקוח Google APIs ל-Node.js:
npm install googleapis crypto express express-session
HTTP/REST
אין צורך להתקין ספריות כדי לקרוא ישירות לנקודות הקצה של OAuth 2.0.
קבלת אסימוני גישה מסוג OAuth 2.0
השלבים הבאים מראים איך האפליקציה שלכם מקיימת אינטראקציה עם שרת OAuth 2.0 של Google כדי לקבל הסכמה מהמשתמש לבצע בקשת API מטעמו. כדי להוציא לפועל בקשה של Google API שמחייבת הרשאת משתמש, האפליקציה צריכה לקבל את ההסכמה הזו.
הרשימה הבאה מסכמת במהירות את השלבים הבאים:
- האפליקציה מזהה את ההרשאות שדרושות לה.
- האפליקציה מפנה את המשתמש ל-Google יחד עם רשימת ההרשאות המבוקשות.
- המשתמש מחליט אם להעניק את ההרשאות לאפליקציה.
- האפליקציה תדע מה המשתמש החליט.
- אם המשתמש העניק את ההרשאות המבוקשות, האפליקציה מאחזרת את האסימונים הנדרשים לשליחת בקשות API מטעם המשתמש.
שלב 1: הגדרת הפרמטרים של ההרשאה
השלב הראשון הוא ליצור את בקשת ההרשאה. בבקשה הזו מוגדרים פרמטרים שמזהים את האפליקציה ומגדירים את ההרשאות שהמשתמש יתבקש להעניק לאפליקציה.
- אם אתם משתמשים בספריית לקוח של Google לאימות ולמתן הרשאות ב-OAuth 2.0, עליכם ליצור ולהגדיר אובייקט שמגדיר את הפרמטרים האלה.
- אם מבצעים קריאה ישירה לנקודת הקצה מסוג Google OAuth 2.0, אפשר ליצור כתובת URL ולהגדיר את הפרמטרים בכתובת ה-URL הזו.
הכרטיסיות הבאות מגדירות את פרמטרי ההרשאה הנתמכים לאפליקציות של שרת אינטרנט. הדוגמאות הספציפיות לשפות גם מראות איך להשתמש בספריית לקוח או בספריית הרשאות כדי להגדיר אובייקט שמגדיר את הפרמטרים האלה.
PHP
קטע הקוד שבהמשך יוצר אובייקט Google\Client()
, שמגדיר את הפרמטרים בבקשת ההרשאה.
האובייקט הזה משתמש במידע מהקובץ client_secret.json כדי לזהות את האפליקציה. (מידע נוסף על הקובץ הזה זמין במאמר יצירת פרטי כניסה להרשאה). האובייקט גם מזהה את היקפי ההרשאות שהאפליקציה מבקשת גישה אליהם ואת כתובת ה-URL של נקודת הקצה לאימות של האפליקציה, שתטפל בתגובה מהשרת של OAuth 2.0 של Google. לבסוף, הקוד מגדיר את הפרמטרים האופציונליים access_type
ו-include_granted_scopes
.
לדוגמה, הקוד הזה מבקש גישה לקריאה בלבד במצב אופליין ל-Google Drive של משתמש:
$client = new Google\Client(); // Required, call the setAuthConfig function to load authorization credentials from // client_secret.json file. $client->setAuthConfig('client_secret.json'); // Required, to set the scope value, call the addScope function $client->addScope(Google\Service\Drive::DRIVE_METADATA_READONLY); // Required, call the setRedirectUri function to specify a valid redirect URI for the // provided client_id $client->setRedirectUri('http://' . $_SERVER['HTTP_HOST'] . '/oauth2callback.php'); // Recommended, offline access will give you both an access and refresh token so that // your app can refresh the access token without user interaction. $client->setAccessType('offline'); // Recommended, call the setState function. Using a state value can increase your assurance that // an incoming connection is the result of an authentication request. $client->setState($sample_passthrough_value); // Optional, if your application knows which user is trying to authenticate, it can use this // parameter to provide a hint to the Google Authentication Server. $client->setLoginHint('hint@example.com'); // Optional, call the setPrompt function to set "consent" will prompt the user for consent $client->setPrompt('consent'); // Optional, call the setIncludeGrantedScopes function with true to enable incremental // authorization $client->setIncludeGrantedScopes(true);
Python
בקטע הקוד הבא נעשה שימוש במודול google-auth-oauthlib.flow
כדי ליצור את בקשת ההרשאה.
הקוד יוצר אובייקט Flow
שמזהה את האפליקציה באמצעות מידע מהקובץ client_secret.json שהורדתם אחרי יצירת פרטי כניסה להרשאה. האובייקט הזה גם מזהה את ההיקפים שאפליקצייתכם מבקשת גישה אליהם ואת כתובת ה-URL של נקודת הקצה לאימות של האפליקציה, שתטפל בתגובה מהשרת של OAuth 2.0 של Google. לבסוף, הקוד מגדיר את הפרמטרים האופציונליים access_type
ו-include_granted_scopes
.
לדוגמה, הקוד הזה מבקש גישה לקריאה בלבד במצב אופליין ל-Google Drive של המשתמש:
import google.oauth2.credentials import google_auth_oauthlib.flow # Required, call the from_client_secrets_file method to retrieve the client ID from a # client_secret.json file. The client ID (from that file) and access scopes are required. (You can # also use the from_client_config method, which passes the client configuration as it originally # appeared in a client secrets file but doesn't access the file itself.) flow = google_auth_oauthlib.flow.Flow.from_client_secrets_file( 'client_secret.json', scopes=['https://www.googleapis.com/auth/drive.metadata.readonly']) # Required, indicate where the API server will redirect the user after the user completes # the authorization flow. The redirect URI is required. The value must exactly # match one of the authorized redirect URIs for the OAuth 2.0 client, which you # configured in the API Console. If this value doesn't match an authorized URI, # you will get a 'redirect_uri_mismatch' error. flow.redirect_uri = 'https://www.example.com/oauth2callback' # Generate URL for request to Google's OAuth 2.0 server. # Use kwargs to set optional request parameters. authorization_url, state = flow.authorization_url( # Recommended, enable offline access so that you can refresh an access token without # re-prompting the user for permission. Recommended for web server apps. access_type='offline', # Optional, enable incremental authorization. Recommended as a best practice. include_granted_scopes='true', # Optional, if your application knows which user is trying to authenticate, it can use this # parameter to provide a hint to the Google Authentication Server. login_hint='hint@example.com', # Optional, set prompt to 'consent' will prompt the user for consent prompt='consent')
Ruby
משתמשים בקובץ client_secrets.json שיצרתם כדי להגדיר אובייקט לקוח באפליקציה. כשמגדירים אובייקט לקוח, צריך לציין את היקפי ההרשאות שהאפליקציה צריכה לגשת אליהן, יחד עם כתובת ה-URL של נקודת הקצה לאימות של האפליקציה, שתטפל בתגובה משרת OAuth 2.0.
לדוגמה, הקוד הזה מבקש גישה לקריאה בלבד במצב אופליין ל-Google Drive של משתמש:
require 'google/apis/drive_v3' require "googleauth" require 'googleauth/stores/redis_token_store' client_id = Google::Auth::ClientId.from_file('/path/to/client_secret.json') scope = 'https://www.googleapis.com/auth/drive.metadata.readonly' token_store = Google::Auth::Stores::RedisTokenStore.new(redis: Redis.new) authorizer = Google::Auth::WebUserAuthorizer.new(client_id, scope, token_store, '/oauth2callback')
האפליקציה משתמשת באובייקט הלקוח כדי לבצע פעולות OAuth 2.0, כמו יצירת כתובות URL של בקשות הרשאה והחלת אסימוני גישה על בקשות HTTP.
Node.js
קטע הקוד הבא יוצר אובייקט google.auth.OAuth2
שמגדיר את הפרמטרים בבקשת ההרשאה.
האובייקט הזה משתמש במידע מקובץ client_secret.json כדי לזהות את האפליקציה. כדי לבקש מהמשתמש הרשאות לאחזור טוקן גישה, מפנים אותו לדף הסכמה. כדי ליצור כתובת URL של דף הסכמה:
const {google} = require('googleapis'); const crypto = require('crypto'); const express = require('express'); const session = require('express-session'); /** * To use OAuth2 authentication, we need access to a CLIENT_ID, CLIENT_SECRET, AND REDIRECT_URI * from the client_secret.json file. To get these credentials for your application, visit * https://console.cloud.google.com/apis/credentials. */ const oauth2Client = new google.auth.OAuth2( YOUR_CLIENT_ID, YOUR_CLIENT_SECRET, YOUR_REDIRECT_URL ); // Access scopes for read-only Drive activity. const scopes = [ 'https://www.googleapis.com/auth/drive.metadata.readonly' ]; // Generate a secure random state value. const state = crypto.randomBytes(32).toString('hex'); // Store state in the session req.session.state = state; // Generate a url that asks permissions for the Drive activity scope const authorizationUrl = oauth2Client.generateAuthUrl({ // 'online' (default) or 'offline' (gets refresh_token) access_type: 'offline', /** Pass in the scopes array defined above. * Alternatively, if only one scope is needed, you can pass a scope URL as a string */ scope: scopes, // Enable incremental authorization. Recommended as a best practice. include_granted_scopes: true, // Include the state parameter to reduce the risk of CSRF attacks. state: state });
הערה חשובה – הערך של refresh_token
מוחזר רק בהרשאה הראשונה. פרטים נוספים
זמינים כאן.
HTTP/REST
נקודת הקצה של 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 מורשה להפניה אוטומטית של חשוב לשים לב שצריך להתאים את הסכימה, האותיות הגדולות והקטנות והקו האופק ( |
||||||
response_type |
חובה
המדיניות קובעת אם נקודת הקצה מסוג Google OAuth 2.0 מחזירה קוד הרשאה. צריך להגדיר את ערך הפרמטר כ- |
||||||
scope |
חובה
רשימה של היקפי הרשאות שמפרידה אותם באמצעות רווחים, ומזהה את המשאבים שהאפליקציה יכולה לגשת אליהם מטעם המשתמש. הערכים האלה מופיעים במסך ההסכמה ש-Google מציגה למשתמש. היקפי הרשאות מאפשרים לאפליקציה לבקש גישה רק למשאבים שנחוצים לה, ומאפשרים גם למשתמשים לקבוע את רמת הגישה שהם מעניקים לאפליקציה. לכן, יש קשר הפוך בין מספר ההיקפים המבוקשים לבין הסבירות לקבלת הסכמה מהמשתמשים. מומלץ לבקש מהאפליקציה לבקש גישה להיקפי הרשאה לפי הקשר, כשהדבר אפשרי. כשמבקשים גישה לנתוני המשתמשים בהקשר מסוים, באמצעות הרשאה מצטברת, קל יותר למשתמשים להבין למה האפליקציה מבקשת את הגישה אליה. |
||||||
access_type |
מומלץ
מציין אם האפליקציה יכולה לרענן אסימוני גישה כשהמשתמש לא נמצא בדפדפן. הערכים החוקיים של הפרמטר הם מגדירים את הערך ל- |
||||||
state |
מומלץ
מציין ערך מחרוזת שבו האפליקציה משתמשת כדי לשמור את המצב בין בקשת ההרשאה לבין התשובה של שרת ההרשאות.
השרת מחזיר את הערך המדויק ששלחתם כצמד אפשר להשתמש בפרמטר הזה למספר מטרות, למשל כדי להפנות את המשתמש למשאב הנכון באפליקציה, לשלוח ערכים חד-פעמיים (nonces) ולצמצם זיוף בקשות בין אתרים. אפשר לנחש את |
||||||
include_granted_scopes |
אופציונלי
מאפשרת לאפליקציות להשתמש בהרשאה מצטברת כדי לבקש גישה להיקפים נוספים בהקשר. אם מגדירים את הערך של הפרמטר הזה ל- |
||||||
enable_granular_consent |
אופציונלי
ברירת המחדל היא כש-Google מפעילה הרשאות מפורטות לאפליקציה, הפרמטר הזה כבר לא ישפיע עליה. |
||||||
login_hint |
אופציונלי
אם לאפליקציה ידוע איזה משתמש מנסה לבצע אימות, היא יכולה להשתמש בפרמטר הזה כדי לספק רמז לשרת האימות של Google. השרת משתמש בהצעה כדי לפשט את תהליך הכניסה, על ידי מילוי מראש של שדה האימייל בטופס הכניסה או על ידי בחירת הסשן המתאים לכניסה בכמה חשבונות. מגדירים את ערך הפרמטר ככתובת אימייל או כמזהה |
||||||
prompt |
אופציונלי
רשימה של הנחיות להצגה למשתמש, מופרדות באמצעות רווחים ותואמות רישיות. אם לא מציינים את הפרמטר הזה, המשתמש יתבקש רק בפעם הראשונה שהפרויקט יגיש בקשה לגישה. מידע נוסף זמין במאמר הצגת בקשה להסכמה חוזרת. הערכים האפשריים הם:
|
שלב 2: הפניה אוטומטית לשרת OAuth 2.0 של Google
מפנים את המשתמש לשרת OAuth 2.0 של Google כדי להתחיל את תהליך האימות וההרשאה. בדרך כלל, המצב הזה מתרחש בפעם הראשונה שהאפליקציה צריכה לגשת לנתונים של המשתמש. במקרה של הרשאה מצטברת, השלב הזה מתרחש גם כשהאפליקציה צריכה לגשת בפעם הראשונה למשאבים נוספים שעדיין אין לה הרשאת גישה אליהם.
PHP
- יוצרים כתובת URL לבקשת גישה משרת OAuth 2.0 של Google:
$auth_url = $client->createAuthUrl();
- מפנים את המשתמש אל
$auth_url
:header('Location: ' . filter_var($auth_url, FILTER_SANITIZE_URL));
Python
בדוגמה הזו מוסבר איך להפנות את המשתמש לכתובת ה-URL של ההרשאה באמצעות מסגרת אפליקציות האינטרנט של Flask:
return flask.redirect(authorization_url)
Ruby
- יוצרים כתובת URL לבקשת גישה משרת OAuth 2.0 של Google:
auth_uri = authorizer.get_authorization_url(login_hint: user_id, request: request)
- מפנים את המשתמש לכתובת
auth_uri
.
Node.js
-
משתמשים בכתובת ה-URL שנוצרה,
authorizationUrl
, משלב 1 שיטהgenerateAuthUrl
כדי לבקש גישה משרת OAuth 2.0 של Google. -
מפנים את המשתמש אל
authorizationUrl
.res.redirect(authorizationUrl);
HTTP/REST
דוגמה להפניה אוטומטית לשרת ההרשאות של Google
בהמשך מוצגת כתובת URL לדוגמה, עם הפסקות שורות ורווחים לשיפור הקריאוּת.
https://accounts.google.com/o/oauth2/v2/auth? scope=https%3A//www.googleapis.com/auth/drive.metadata.readonly& access_type=offline& include_granted_scopes=true& response_type=code& state=state_parameter_passthrough_value& redirect_uri=https%3A//oauth2.example.com/code& client_id=client_id
לאחר יצירת כתובת ה-URL של הבקשה, הפנה את המשתמש אליה.
שרת OAuth 2.0 של Google מאמת את המשתמש ומקבל ממנו הסכמה לאפליקציה לגשת להיקפי ההרשאות המבוקשים. התגובה נשלחת חזרה לאפליקציה באמצעות כתובת ה-URL להפניה אוטומטית שציינתם.
שלב 3: Google מבקשת מהמשתמש להביע הסכמה
בשלב הזה, המשתמש מחליט אם להעניק לאפליקציה את הרשאת הגישה המבוקשת. בשלב הזה, Google מציגה חלון הסכמה שמציג את שם האפליקציה ואת שירותי Google API שאליהם האפליקציה מבקשת הרשאה לגשת באמצעות פרטי הכניסה להרשאה של המשתמש וסיכום של היקפי הגישה שיש להעניק. לאחר מכן, המשתמש יכול להביע הסכמה להענקת גישה להיקף אחד או יותר שהאפליקציה ביקשה, או לדחות את הבקשה.
האפליקציה שלך לא צריכה לעשות שום דבר בשלב הזה. היא ממתינה לתשובה משרת OAuth 2.0 של Google, שמציינת אם ניתנה גישה. התגובה הזו מוסברת בשלב הבא.
שגיאות
יכול להיות שבבקשות לנקודת הקצה של הרשאת OAuth 2.0 של Google יוצגו הודעות שגיאה גלויות למשתמש, במקום תהליכי האימות וההרשאה הצפויים. בהמשך מפורטים קודי שגיאה נפוצים והצעות לפתרון.
admin_policy_enforced
חשבון Google לא יכול להעניק הרשאה להיקף אחד או יותר מהיקפי הגישה המבוקשים בגלל המדיניות של האדמין ב-Google Workspace. במאמר העזרה שליטה בגישה של אפליקציות של צד שלישי ואפליקציות פנימיות לנתונים ב-Google Workspace מוסבר איך אדמין יכול להגביל את הגישה לכל ההיקפים או להיקפים רגישים ומוגבלים, עד שתוענק גישה מפורשת למזהה הלקוח של OAuth.
disallowed_useragent
נקודת הקצה (endpoint) של ההרשאה מוצגת בתוך סוכן משתמש מוטמע שאסור לפי מדיניות OAuth 2.0 של Google.
Android
מפתחי Android עשויים להיתקל בהודעת השגיאה הזו כשהם פותחים בקשות הרשאה ב-android.webkit.WebView
.
במקום זאת, המפתחים צריכים להשתמש בספריות של Android, כמו Google Sign-In ל-Android או AppAuth ל-Android של OpenID Foundation.
הודעת השגיאה הזו עשויה לקרות כשאפליקציה ל-Android פותחת קישור כללי לאינטרנט בסוכן משתמש מוטמע ומשתמש מנווט באתר אל נקודת הקצה להרשאה מסוג OAuth 2.0 של Google באתר שלך. מפתחים צריכים לאפשר לקישורים כלליים להיפתח בבורר הקישורים שמוגדר כברירת מחדל במערכת ההפעלה, שכולל גם את הבוררים של קישורים לאפליקציות Android או את אפליקציית הדפדפן שמוגדרת כברירת מחדל. גם הספרייה Android Custom Tabs נתמכת.
iOS
מפתחים של iOS ו-macOS עשויים להיתקל בשגיאה הזו כשהם פותחים בקשות הרשאה ב-WKWebView
.
במקום זאת, המפתחים צריכים להשתמש בספריות ל-iOS כמו Google Sign-In ל-iOS או AppAuth ל-iOS של OpenID Foundation.
מפתחי אינטרנט עשויים להיתקל בשגיאה הזו כשאפליקציה ל-iOS או ל-macOS פותחת קישור אינטרנט כללי בסוכן משתמש מוטמע, ומשתמש מנווט מנקודת הקצה של הרשאת OAuth 2.0 של Google מהאתר שלכם. המפתחים צריכים לאפשר לקישורים כלליים להיפתח ב-handler של הקישור שמוגדר כברירת מחדל
של מערכת ההפעלה, שכולל את ה-handler של
הקישורים האוניברסליים
וגם את אפליקציית ברירת המחדל של הדפדפן. גם הספרייה SFSafariViewController
נתמכת.
org_internal
מזהה הלקוח ב-OAuth שצוין בבקשה הוא חלק מפרויקט שמגביל את הגישה לחשבונות Google ב ארגון ספציפי ב-Google Cloud. מידע נוסף על אפשרות ההגדרה הזו זמין בקטע סוג המשתמש במאמר העזרה בנושא הגדרת מסך הסכמה ל-OAuth.
invalid_client
סוד הלקוח של OAuth שגוי. בודקים את הגדרת הלקוח ב-OAuth, כולל מזהה הלקוח והסוד ששימשו לבקשה הזו.
invalid_grant
כשמרעננים אסימון גישה או משתמשים בהרשאה מצטברת, יכול להיות שתוקף האסימון פג או שהוא לא תקף. מאמתים שוב את המשתמש ומבקשים ממנו הסכמה לקבלת אסימונים חדשים. אם השגיאה הזו ממשיכה להופיע, צריך לוודא שהאפליקציה הוגדרה בצורה תקינה ושהבקשה כוללת את האסימונים והפרמטרים הנכונים. אחרת, יכול להיות שחשבון המשתמש נמחק או הושבת.
redirect_uri_mismatch
ה-redirect_uri
שהועבר בבקשת ההרשאה לא תואם ל-URI מורשה להפניה אוטומטית במזהה הלקוח ב-OAuth. בודקים את מזהי ה-URI המורשים להפניה אוטומטית בקטע Google API Console Credentials page.
יכול להיות שהפרמטר redirect_uri
מתייחס לתהליך של OAuth מחוץ למסגרת (OOB)
שיצא משימוש וכבר לא נתמך. כדי לעדכן את השילוב, אפשר לעיין במדריך להעברה.
invalid_request
הייתה בעיה בבקשה ששלחת. יכולות להיות לכך כמה סיבות:
- הפורמט של הבקשה שגוי
- חסרים פרמטרים נדרשים בבקשה
- הבקשה משתמשת בשיטת הרשאה ש-Google לא תומכת בה. מוודאים שהשילוב של OAuth מתבצע בשיטת שילוב מומלצת
שלב 4: טיפול בתגובה לשרת OAuth 2.0
שרת OAuth 2.0 מגיב לבקשת הגישה של האפליקציה באמצעות כתובת ה-URL שצוינה בבקשה.
אם המשתמש יאשר את בקשת הגישה, התשובה תכלול קוד הרשאה. אם המשתמש לא יאשר את הבקשה, התשובה תכלול הודעת שגיאה. קוד ההרשאה או הודעת השגיאה שמוחזרים לשרת האינטרנט מופיעים במחרוזת השאילתה, כפי שמוצג בהמשך:
תגובת שגיאה:
https://oauth2.example.com/auth?error=access_denied
תגובה עם קוד הרשאה:
https://oauth2.example.com/auth?code=4/P7q7W91a-oMsCeLvIaQm6bTrgtp7
דוגמה של תגובת שרת OAuth 2.0
כדי לבדוק את התהליך הזה, אפשר ללחוץ על כתובת ה-URL לדוגמה הבאה, שבה מופיעה בקשה לגישה לקריאה בלבד כדי להציג את המטא-נתונים של קבצים ב-Google Drive:
https://accounts.google.com/o/oauth2/v2/auth? scope=https%3A//www.googleapis.com/auth/drive.metadata.readonly& access_type=offline& include_granted_scopes=true& response_type=code& state=state_parameter_passthrough_value& redirect_uri=https%3A//oauth2.example.com/code& client_id=client_id
אחרי שתשלימו את התהליך ב-OAuth 2.0, תופנו אל
http://localhost/oauth2callback
, שככל הנראה תניב שגיאת
404 NOT FOUND
, אלא אם המחשב המקומי יציג קובץ בכתובת הזו. בשלב הבא נספק פרטים נוספים על המידע שמוחזר ב-URI כשהמשתמש מופנה חזרה לאפליקציה.
שלב 5: החלפת קוד ההרשאה באסימוני רענון וגישה
אחרי ששרת האינטרנט מקבל את קוד ההרשאה, הוא יכול להמיר את קוד ההרשאה לטוקן גישה.
PHP
כדי להמיר קוד הרשאה לטוקן גישה, משתמשים ב-method authenticate
:
$client->authenticate($_GET['code']);
אפשר לאחזר את אסימון הגישה באמצעות השיטה getAccessToken
:
$access_token = $client->getAccessToken();
Python
בדף הקריאה החוזרת, משתמשים בספרייה google-auth
כדי לאמת את התגובה של שרת ההרשאות. אחרי זה, משתמשים ב-method flow.fetch_token
כדי להחליף את קוד ההרשאה בתגובה הזו באסימון גישה:
state = flask.session['state'] flow = google_auth_oauthlib.flow.Flow.from_client_secrets_file( 'client_secret.json', scopes=['https://www.googleapis.com/auth/drive.metadata.readonly'], state=state) flow.redirect_uri = flask.url_for('oauth2callback', _external=True) authorization_response = flask.request.url flow.fetch_token(authorization_response=authorization_response) # Store the credentials in the session. # ACTION ITEM for developers: # Store user's access and refresh tokens in your data store if # incorporating this code into your real app. credentials = flow.credentials flask.session['credentials'] = { 'token': credentials.token, 'refresh_token': credentials.refresh_token, 'token_uri': credentials.token_uri, 'client_id': credentials.client_id, 'client_secret': credentials.client_secret, 'scopes': credentials.scopes}
Ruby
בדף הקריאה החוזרת, משתמשים בספרייה googleauth
כדי לאמת את התשובה של שרת ההרשאות. משתמשים ב-method authorizer.handle_auth_callback_deferred
כדי לשמור את קוד ההרשאה ולהפנות חזרה לכתובת ה-URL שבה נשלחה במקור בקשת ההרשאה. כך ניתן למנוע את החלפת הקוד על ידי הסתרה זמנית של התוצאות בסשן של המשתמש.
target_url = Google::Auth::WebUserAuthorizer.handle_auth_callback_deferred(request) redirect target_url
Node.js
כדי להמיר קוד הרשאה לטוקן גישה, משתמשים ב-method getToken
:
const url = require('url'); // Receive the callback from Google's OAuth 2.0 server. app.get('/oauth2callback', async (req, res) => { let q = url.parse(req.url, true).query; if (q.error) { // An error response e.g. error=access_denied console.log('Error:' + q.error); } else if (q.state !== req.session.state) { //check state value console.log('State mismatch. Possible CSRF attack'); res.end('State mismatch. Possible CSRF attack'); } else { // Get access and refresh tokens (if access_type is offline) let { tokens } = await oauth2Client.getToken(q.code); oauth2Client.setCredentials(tokens); });
HTTP/REST
כדי להמיר קוד הרשאה לאסימון גישה, צריך להפעיל את נקודת הקצה https://oauth2.googleapis.com/token
ולהגדיר את הפרמטרים הבאים:
שדות | |
---|---|
client_id |
מזהה הלקוח שהתקבל מ- API Console Credentials page. |
client_secret |
סוד הלקוח שהתקבל מ- API Console Credentials page. |
code |
קוד ההרשאה שהוחזר מהבקשה הראשונית. |
grant_type |
כפי שמוגדר במפרט של OAuth 2.0, הערך של השדה הזה צריך להיות authorization_code . |
redirect_uri |
אחד מ-URI להפניה אוטומטית שמפורטים לפרויקט שלכם ב- API Console
Credentials page עבור client_id הנתון. |
בקטע הקוד הבא מוצגת בקשה לדוגמה:
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
בתגובה לבקשה הזו, Google מחזירה אובייקט JSON שמכיל אסימון גישה לטווח קצר ואסימון רענון.
חשוב לזכור שאסימון הרענון מוחזר רק אם האפליקציה שלכם מגדירה את הפרמטר access_type
לערך offline
בבקשה הראשונית לשרת ההרשאות של Google.
התגובה כוללת את השדות הבאים:
שדות | |
---|---|
access_token |
האסימון שהאפליקציה שלכם שולחת כדי לאשר בקשת Google API. |
expires_in |
משך החיים שנותר של אסימון הגישה, בשניות. |
refresh_token |
אסימון שאפשר להשתמש בו כדי לקבל אסימון גישה חדש. אסימוני הרענון בתוקף עד שהמשתמש מבטל את הגישה.
שוב, השדה הזה מופיע בתגובה הזו רק אם מגדירים את הפרמטר access_type ל-offline בבקשה הראשונית לשרת ההרשאות של Google.
|
scope |
היקפי הגישה שהוענקו על ידי access_token , מוצגים כרשימה של מחרוזות תלויות-רישיות שמופרדות ברווחים. |
token_type |
סוג הטוקן שהוחזר. בשלב זה, הערך של השדה הזה תמיד מוגדר ל-Bearer . |
קטע הקוד הבא מציג תגובה לדוגמה:
{ "access_token": "1/fFAGRNJru1FTz70BzhT3Zg", "expires_in": 3920, "token_type": "Bearer", "scope": "https://www.googleapis.com/auth/drive.metadata.readonly", "refresh_token": "1//xEoDL4iW3cxlI7yDbSRFYNG01kVKM2C-259HOF2aQbI" }
שגיאות
כשמחליפים את קוד ההרשאה באסימון גישה, יכול להיות שתקבלו את השגיאה הבאה במקום התגובה הצפויה. קודי שגיאות נפוצים והצעות לפתרונות מפורטים בהמשך.
invalid_grant
קוד ההרשאה שסופק לא תקין או שהפורמט שלו שגוי. כדי לבקש קוד חדש, צריך להפעיל מחדש את תהליך ה-OAuth כדי לבקש שוב מהמשתמש להביע הסכמה.
קריאה ל-Google APIs
PHP
משתמשים באסימון הגישה כדי לקרוא ל-Google APIs. לשם כך מבצעים את השלבים הבאים:
- אם צריך להחיל אסימון גישה על אובייקט
Google\Client
חדש – לדוגמה, אם שמרתם את אסימון הגישה בסשן של משתמש – צריך להשתמש בשיטהsetAccessToken
:$client->setAccessToken($access_token);
- יוצרים אובייקט שירות ל-API שאליו רוצים לקרוא. כדי ליצור אובייקט שירות, מספקים אובייקט
Google\Client
מורשה למבנה ה-constructor של ה-API שרוצים לקרוא אליו. לדוגמה, כדי לקרוא ל-Drive API:$drive = new Google\Service\Drive($client);
- שולחים בקשות לשירות ה-API באמצעות הממשק שסופק על ידי אובייקט השירות.
לדוגמה, כדי להציג את הקבצים ב-Google Drive של המשתמש המאומת:
$files = $drive->files->listFiles(array())->getItems();
Python
אחרי קבלת אסימון גישה, האפליקציה יכולה להשתמש באסימון הזה כדי לאשר בקשות API מטעם חשבון משתמש או חשבון שירות נתון. משתמשים בפרטי הכניסה להרשאה הספציפית למשתמש כדי ליצור אובייקט שירות ל-API שאליו רוצים לקרוא, ולאחר מכן משתמשים באובייקט כדי לשלוח בקשות API מורשות.
- יוצרים אובייקט שירות ל-API שרוצים להפעיל. כדי ליצור אובייקט שירות, צריך לבצע קריאה ל-method
build
בספרייהgoogleapiclient.discovery
עם השם והגרסה של ה-API ופרטי הכניסה של המשתמש: לדוגמה, כדי לקרוא לגרסה 3 של Drive API:from googleapiclient.discovery import build drive = build('drive', 'v2', credentials=credentials)
- שולחים בקשות לשירות ה-API באמצעות הממשק של אובייקט השירות.
לדוגמה, כדי להציג את הקבצים ב-Google Drive של המשתמש המאומת:
files = drive.files().list().execute()
Ruby
אחרי קבלת אסימון גישה, האפליקציה יכולה להשתמש באסימון הזה כדי לשלוח בקשות API מטעם חשבון משתמש או חשבון שירות נתון. משתמשים בפרטי הכניסה להרשאה הספציפיים למשתמש כדי ליצור אובייקט שירות ל-API שרוצים לבצע אליו קריאה, ואז משתמשים באובייקט הזה כדי לשלוח בקשות מורשות ל-API.
- יוצרים אובייקט שירות ל-API שרוצים להפעיל.
לדוגמה, כדי לקרוא לגרסה 3 של Drive API:
drive = Google::Apis::DriveV3::DriveService.new
- מגדירים את פרטי הכניסה בשירות:
drive.authorization = credentials
- שולחים בקשות לשירות ה-API באמצעות הממשק שסופק על ידי אובייקט השירות.
לדוגמה, כדי להציג את הקבצים ב-Google Drive של המשתמש המאומת:
files = drive.list_files
לחלופין, אפשר לספק הרשאה לפי שיטות על ידי העברת הפרמטר options
לשיטה:
files = drive.list_files(options: { authorization: credentials })
Node.js
אחרי שמקבלים אסימון גישה ומגדירים אותו באובייקט OAuth2
, משתמשים באובייקט כדי לבצע קריאות ל-Google APIs. האפליקציה שלך יכולה להשתמש באסימון הזה כדי לאשר בקשות API בשם
חשבון משתמש או חשבון שירות נתונים. יוצרים אובייקט שירות ל-API שרוצים להפעיל.
const { google } = require('googleapis'); // Example of using Google Drive API to list filenames in user's Drive. const drive = google.drive('v3'); drive.files.list({ auth: oauth2Client, pageSize: 10, fields: 'nextPageToken, files(id, name)', }, (err1, res1) => { if (err1) return console.log('The API returned an error: ' + err1); const files = res1.data.files; if (files.length) { console.log('Files:'); files.map((file) => { console.log(`${file.name} (${file.id})`); }); } else { console.log('No files found.'); } });
HTTP/REST
אחרי שהאפליקציה מקבלת אסימון גישה, אפשר להשתמש באסימון כדי לבצע קריאות ל-Google API מטעם חשבון משתמש נתון, אם היקפי הגישה הנדרשים ל-API הוקצו. כדי לעשות זאת, צריך לכלול את אסימון הגישה בבקשה ל-API באמצעות פרמטר של שאילתה access_token
או ערך Bearer
בכותרת Authorization
של HTTP. כשהדבר אפשרי, עדיף להשתמש בכותרת ה-HTTP, כי מחרוזות השאילתות נוטים להיות גלויות ביומנים של השרת. ברוב המקרים אפשר להשתמש בספריית לקוח כדי להגדיר את הקריאות לממשקי Google API (לדוגמה, כשקוראים ל-Drive Files API).
תוכלו לנסות את כל ממשקי ה-API של Google כדי לצפות בהיקפים שלהם ב-OAuth 2.0 Playground.
דוגמאות לבקשות HTTP GET
קריאה לנקודת הקצה
drive.files
(Drive Files API) באמצעות כותרת ה-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
דוגמה מלאה
בדוגמה הבאה מודפסת רשימה של קבצים בפורמט JSON ב-Google Drive של משתמש, אחרי שהמשתמש מבצע אימות ומביע הסכמה לאפליקציה לגשת למטא-נתונים של המשתמש ב-Drive.
PHP
כדי להריץ את הדוגמה הזו:
- ב- API Console, מוסיפים את כתובת ה-URL של המכונה המקומית לרשימת כתובות ה-URL להפניה אוטומטית. לדוגמה, מוסיפים את
http://localhost:8080
. - יוצרים ספרייה חדשה ומשנים אליה. לדוגמה:
mkdir ~/php-oauth2-example cd ~/php-oauth2-example
- מתקינים את ספריית הלקוח של Google API ל-PHP באמצעות Composer:
composer require google/apiclient:^2.10
- יוצרים את הקבצים
index.php
ו-oauth2callback.php
עם התוכן הבא. - מריצים את הדוגמה באמצעות שרת אינטרנט שמוגדר להציג PHP. אם אתם משתמשים ב-PHP 5.6 ואילך, תוכלו להשתמש בשרת האינטרנט המובנה לבדיקה של PHP:
php -S localhost:8080 ~/php-oauth2-example
index.php
<?php require_once __DIR__.'/vendor/autoload.php'; session_start(); $client = new Google\Client(); $client->setAuthConfig('client_secrets.json'); $client->addScope(Google\Service\Drive::DRIVE_METADATA_READONLY); if (isset($_SESSION['access_token']) && $_SESSION['access_token']) { $client->setAccessToken($_SESSION['access_token']); $drive = new Google\Service\Drive($client); $files = $drive->files->listFiles(array())->getItems(); echo json_encode($files); } else { $redirect_uri = 'http://' . $_SERVER['HTTP_HOST'] . '/oauth2callback.php'; header('Location: ' . filter_var($redirect_uri, FILTER_SANITIZE_URL)); }
oauth2callback.php
<?php require_once __DIR__.'/vendor/autoload.php'; session_start(); $client = new Google\Client(); $client->setAuthConfigFile('client_secrets.json'); $client->setRedirectUri('http://' . $_SERVER['HTTP_HOST'] . '/oauth2callback.php'); $client->addScope(Google\Service\Drive::DRIVE_METADATA_READONLY); if (! isset($_GET['code'])) { // Generate and set state value $state = bin2hex(random_bytes(16)); $client->setState($state); $_SESSION['state'] = $state; $auth_url = $client->createAuthUrl(); header('Location: ' . filter_var($auth_url, FILTER_SANITIZE_URL)); } else { // Check the state value if (!isset($_GET['state']) || $_GET['state'] !== $_SESSION['state']) { die('State mismatch. Possible CSRF attack.'); } $client->authenticate($_GET['code']); $_SESSION['access_token'] = $client->getAccessToken(); $redirect_uri = 'http://' . $_SERVER['HTTP_HOST'] . '/'; header('Location: ' . filter_var($redirect_uri, FILTER_SANITIZE_URL)); }
Python
בדוגמה הזו נעשה שימוש ב-framework של Flask. הוא מפעיל אפליקציית אינטרנט בכתובת http://localhost:8080
שמאפשרת לבדוק את התהליך של OAuth 2.0. אם עוברים לכתובת ה-URL הזו, אמורים להופיע ארבעה קישורים:
- בדיקת בקשת API: הקישור הזה מפנה לדף שמנסה להריץ בקשת API לדוגמה. אם צריך, הוא מתחיל את תהליך ההרשאה. אם הפעולה בוצעה ללא שגיאות, התגובה של ה-API תוצג בדף.
- בדיקת תהליך האימות ישירות: הקישור הזה מפנה לדף שמנסה לשלוח את המשתמש דרך תהליך ההרשאה. האפליקציה מבקשת הרשאה לשלוח בקשות API מורשות בשם המשתמש.
- ביטול פרטי הכניסה הנוכחיים: הקישור הזה מפנה לדף ש מבטל את ההרשאות שהמשתמש כבר העניק לאפליקציה.
- ניקוי פרטי הכניסה של סשן Flask: הקישור הזה מנקה את פרטי הכניסה להרשאה שמאוחסנים בסשן Flask. כך תוכלו לראות מה יקרה אם משתמש שכבר העניק הרשאה לאפליקציה שלכם ינסה להריץ בקשת API בסשן חדש. הוא גם מאפשר לכם לראות את תגובת ה-API שהאפליקציה תקבל אם משתמש ביטל את ההרשאות שהוקצו לאפליקציה, והאפליקציה עדיין ניסתה לאשר בקשה עם אסימון גישה שהתבטל.
# -*- coding: utf-8 -*- import os import flask import requests import google.oauth2.credentials import google_auth_oauthlib.flow import googleapiclient.discovery # This variable specifies the name of a file that contains the OAuth 2.0 # information for this application, including its client_id and client_secret. CLIENT_SECRETS_FILE = "client_secret.json" # This OAuth 2.0 access scope allows for full read/write access to the # authenticated user's account and requires requests to use an SSL connection. SCOPES = ['https://www.googleapis.com/auth/drive.metadata.readonly'] API_SERVICE_NAME = 'drive' API_VERSION = 'v2' app = flask.Flask(__name__) # Note: A secret key is included in the sample so that it works. # If you use this code in your application, replace this with a truly secret # key. See https://flask.palletsprojects.com/quickstart/#sessions. app.secret_key = 'REPLACE ME - this value is here as a placeholder.' @app.route('/') def index(): return print_index_table() @app.route('/test') def test_api_request(): if 'credentials' not in flask.session: return flask.redirect('authorize') # Load credentials from the session. credentials = google.oauth2.credentials.Credentials( **flask.session['credentials']) drive = googleapiclient.discovery.build( API_SERVICE_NAME, API_VERSION, credentials=credentials) files = drive.files().list().execute() # Save credentials back to session in case access token was refreshed. # ACTION ITEM: In a production app, you likely want to save these # credentials in a persistent database instead. flask.session['credentials'] = credentials_to_dict(credentials) return flask.jsonify(**files) @app.route('/authorize') def authorize(): # Create flow instance to manage the OAuth 2.0 Authorization Grant Flow steps. flow = google_auth_oauthlib.flow.Flow.from_client_secrets_file( CLIENT_SECRETS_FILE, scopes=SCOPES) # The URI created here must exactly match one of the authorized redirect URIs # for the OAuth 2.0 client, which you configured in the API Console. If this # value doesn't match an authorized URI, you will get a 'redirect_uri_mismatch' # error. flow.redirect_uri = flask.url_for('oauth2callback', _external=True) authorization_url, state = flow.authorization_url( # Enable offline access so that you can refresh an access token without # re-prompting the user for permission. Recommended for web server apps. access_type='offline', # Enable incremental authorization. Recommended as a best practice. include_granted_scopes='true') # Store the state so the callback can verify the auth server response. flask.session['state'] = state return flask.redirect(authorization_url) @app.route('/oauth2callback') def oauth2callback(): # Specify the state when creating the flow in the callback so that it can # verified in the authorization server response. state = flask.session['state'] flow = google_auth_oauthlib.flow.Flow.from_client_secrets_file( CLIENT_SECRETS_FILE, scopes=SCOPES, state=state) flow.redirect_uri = flask.url_for('oauth2callback', _external=True) # Use the authorization server's response to fetch the OAuth 2.0 tokens. authorization_response = flask.request.url flow.fetch_token(authorization_response=authorization_response) # Store credentials in the session. # ACTION ITEM: In a production app, you likely want to save these # credentials in a persistent database instead. credentials = flow.credentials flask.session['credentials'] = credentials_to_dict(credentials) return flask.redirect(flask.url_for('test_api_request')) @app.route('/revoke') def revoke(): if 'credentials' not in flask.session: return ('You need to <a href="/authorize">authorize</a> before ' + 'testing the code to revoke credentials.') credentials = google.oauth2.credentials.Credentials( **flask.session['credentials']) revoke = requests.post('https://oauth2.googleapis.com/revoke', params={'token': credentials.token}, headers = {'content-type': 'application/x-www-form-urlencoded'}) status_code = getattr(revoke, 'status_code') if status_code == 200: return('Credentials successfully revoked.' + print_index_table()) else: return('An error occurred.' + print_index_table()) @app.route('/clear') def clear_credentials(): if 'credentials' in flask.session: del flask.session['credentials'] return ('Credentials have been cleared.<br><br>' + print_index_table()) def credentials_to_dict(credentials): return {'token': credentials.token, 'refresh_token': credentials.refresh_token, 'token_uri': credentials.token_uri, 'client_id': credentials.client_id, 'client_secret': credentials.client_secret, 'scopes': credentials.scopes} def print_index_table(): return ('<table>' + '<tr><td><a href="/test">Test an API request</a></td>' + '<td>Submit an API request and see a formatted JSON response. ' + ' Go through the authorization flow if there are no stored ' + ' credentials for the user.</td></tr>' + '<tr><td><a href="/authorize">Test the auth flow directly</a></td>' + '<td>Go directly to the authorization flow. If there are stored ' + ' credentials, you still might not be prompted to reauthorize ' + ' the application.</td></tr>' + '<tr><td><a href="/revoke">Revoke current credentials</a></td>' + '<td>Revoke the access token associated with the current user ' + ' session. After revoking credentials, if you go to the test ' + ' page, you should see an <code>invalid_grant</code> error.' + '</td></tr>' + '<tr><td><a href="/clear">Clear Flask session credentials</a></td>' + '<td>Clear the access token currently stored in the user session. ' + ' After clearing the token, if you <a href="/test">test the ' + ' API request</a> again, you should go back to the auth flow.' + '</td></tr></table>') if __name__ == '__main__': # When running locally, disable OAuthlib's HTTPs verification. # ACTION ITEM for developers: # When running in production *do not* leave this option enabled. os.environ['OAUTHLIB_INSECURE_TRANSPORT'] = '1' # Specify a hostname and port that are set as a valid redirect URI # for your API project in the Google API Console. app.run('localhost', 8080, debug=True)
Ruby
בדוגמה הזו נעשה שימוש במסגרת Sinatra.
require 'google/apis/drive_v3' require 'sinatra' require 'googleauth' require 'googleauth/stores/redis_token_store' configure do enable :sessions set :client_id, Google::Auth::ClientId.from_file('/path/to/client_secret.json') set :scope, Google::Apis::DriveV3::AUTH_DRIVE_METADATA_READONLY set :token_store, Google::Auth::Stores::RedisTokenStore.new(redis: Redis.new) set :authorizer, Google::Auth::WebUserAuthorizer.new(settings.client_id, settings.scope, settings.token_store, '/oauth2callback') end get '/' do user_id = settings.client_id.id credentials = settings.authorizer.get_credentials(user_id, request) if credentials.nil? redirect settings.authorizer.get_authorization_url(login_hint: user_id, request: request) end drive = Google::Apis::DriveV3::DriveService.new files = drive.list_files(options: { authorization: credentials }) "<pre>#{JSON.pretty_generate(files.to_h)}</pre>" end get '/oauth2callback' do target_url = Google::Auth::WebUserAuthorizer.handle_auth_callback_deferred(request) redirect target_url end
Node.js
כדי להריץ את הדוגמה הזו:
-
בקובץ API Console, מוסיפים את כתובת ה-URL של המכונה המקומית לרשימת כתובות ה-URL להפניה אוטומטית. לדוגמה, מוסיפים את
http://localhost
. - חשוב לוודא שהתקנתם את הגרסה הנוכחית, את הגרסה הפעילה של LTS או את הגרסה של LTS לתחזוקה של Node.js.
-
יוצרים ספרייה חדשה ועוברים אליה. לדוגמה:
mkdir ~/nodejs-oauth2-example cd ~/nodejs-oauth2-example
-
מתקינים את ספריית הלקוח של Google API ל-Node.js באמצעות npm:
npm install googleapis
-
יוצרים את הקבצים
main.js
עם התוכן שלמטה. -
מריצים את הדוגמה:
node .\main.js
main.js
const http = require('http'); const https = require('https'); const url = require('url'); const { google } = require('googleapis'); const crypto = require('crypto'); const express = require('express'); const session = require('express-session'); /** * To use OAuth2 authentication, we need access to a CLIENT_ID, CLIENT_SECRET, AND REDIRECT_URI. * To get these credentials for your application, visit * https://console.cloud.google.com/apis/credentials. */ const oauth2Client = new google.auth.OAuth2( YOUR_CLIENT_ID, YOUR_CLIENT_SECRET, YOUR_REDIRECT_URL ); // Access scopes for read-only Drive activity. const scopes = [ 'https://www.googleapis.com/auth/drive.metadata.readonly' ]; /* Global variable that stores user credential in this code example. * ACTION ITEM for developers: * Store user's refresh token in your data store if * incorporating this code into your real app. * For more information on handling refresh tokens, * see https://github.com/googleapis/google-api-nodejs-client#handling-refresh-tokens */ let userCredential = null; async function main() { const app = express(); app.use(session({ secret: 'your_secure_secret_key', // Replace with a strong secret resave: false, saveUninitialized: false, })); // Example on redirecting user to Google's OAuth 2.0 server. app.get('/', async (req, res) => { // Generate a secure random state value. const state = crypto.randomBytes(32).toString('hex'); // Store state in the session req.session.state = state; // Generate a url that asks permissions for the Drive activity scope const authorizationUrl = oauth2Client.generateAuthUrl({ // 'online' (default) or 'offline' (gets refresh_token) access_type: 'offline', /** Pass in the scopes array defined above. * Alternatively, if only one scope is needed, you can pass a scope URL as a string */ scope: scopes, // Enable incremental authorization. Recommended as a best practice. include_granted_scopes: true, // Include the state parameter to reduce the risk of CSRF attacks. state: state }); res.redirect(authorizationUrl); }); // Receive the callback from Google's OAuth 2.0 server. app.get('/oauth2callback', async (req, res) => { // Handle the OAuth 2.0 server response let q = url.parse(req.url, true).query; if (q.error) { // An error response e.g. error=access_denied console.log('Error:' + q.error); } else if (q.state !== req.session.state) { //check state value console.log('State mismatch. Possible CSRF attack'); res.end('State mismatch. Possible CSRF attack'); } else { // Get access and refresh tokens (if access_type is offline) let { tokens } = await oauth2Client.getToken(q.code); oauth2Client.setCredentials(tokens); /** Save credential to the global variable in case access token was refreshed. * ACTION ITEM: In a production app, you likely want to save the refresh token * in a secure persistent database instead. */ userCredential = tokens; // Example of using Google Drive API to list filenames in user's Drive. const drive = google.drive('v3'); drive.files.list({ auth: oauth2Client, pageSize: 10, fields: 'nextPageToken, files(id, name)', }, (err1, res1) => { if (err1) return console.log('The API returned an error: ' + err1); const files = res1.data.files; if (files.length) { console.log('Files:'); files.map((file) => { console.log(`${file.name} (${file.id})`); }); } else { console.log('No files found.'); } }); } }); // Example on revoking a token app.get('/revoke', async (req, res) => { // Build the string for the POST request let postData = "token=" + userCredential.access_token; // Options for POST request to Google's OAuth 2.0 server to revoke a token let postOptions = { host: 'oauth2.googleapis.com', port: '443', path: '/revoke', method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded', 'Content-Length': Buffer.byteLength(postData) } }; // Set up the request const postReq = https.request(postOptions, function (res) { res.setEncoding('utf8'); res.on('data', d => { console.log('Response: ' + d); }); }); postReq.on('error', error => { console.log(error) }); // Post the request with data postReq.write(postData); postReq.end(); }); const server = http.createServer(app); server.listen(80); } main().catch(console.error);
HTTP/REST
בדוגמה הזו ב-Python נעשה שימוש במסגרת Flask ובספרייה Requests כדי להדגים את תהליך האינטרנט של OAuth 2.0. בתהליך הזה מומלץ להשתמש בספריית הלקוח של Google API ל-Python. (בדוגמה בכרטיסייה Python נעשה שימוש בספריית הלקוח).
import json import flask import requests app = flask.Flask(__name__) CLIENT_ID = '123456789.apps.googleusercontent.com' CLIENT_SECRET = 'abc123' # Read from a file or environmental variable in a real app SCOPE = 'https://www.googleapis.com/auth/drive.metadata.readonly' REDIRECT_URI = 'http://example.com/oauth2callback' @app.route('/') def index(): if 'credentials' not in flask.session: return flask.redirect(flask.url_for('oauth2callback')) credentials = json.loads(flask.session['credentials']) if credentials['expires_in'] <= 0: return flask.redirect(flask.url_for('oauth2callback')) else: headers = {'Authorization': 'Bearer {}'.format(credentials['access_token'])} req_uri = 'https://www.googleapis.com/drive/v2/files' r = requests.get(req_uri, headers=headers) return r.text @app.route('/oauth2callback') def oauth2callback(): if 'code' not in flask.request.args: state = str(uuid.uuid4()) flask.session['state'] = state auth_uri = ('https://accounts.google.com/o/oauth2/v2/auth?response_type=code' '&client_id={}&redirect_uri={}&scope={}&state={}').format(CLIENT_ID, REDIRECT_URI, SCOPE, state) return flask.redirect(auth_uri) else: if 'state' not in flask.request.args or flask.request.args['state'] != flask.session['state']: return 'State mismatch. Possible CSRF attack.', 400 auth_code = flask.request.args.get('code') data = {'code': auth_code, 'client_id': CLIENT_ID, 'client_secret': CLIENT_SECRET, 'redirect_uri': REDIRECT_URI, 'grant_type': 'authorization_code'} r = requests.post('https://oauth2.googleapis.com/token', data=data) flask.session['credentials'] = r.text return flask.redirect(flask.url_for('index')) if __name__ == '__main__': import uuid app.secret_key = str(uuid.uuid4()) app.debug = False app.run()
כללי אימות של URI של הפניה לכתובת אחרת
Google מחילה את כללי האימות הבאים כדי להפנות מזהי URI להפניה אוטומטית, כדי לעזור למפתחים לשמור על אבטחת האפליקציות שלהם. מזהי ה-URI להפניה אוטומטית חייבים לעמוד בכללים האלה. ההגדרות של הדומיין, המארח, הנתיב, השאילתה, הסכימה והפרטים של המשתמש, שמפורטות בהמשך, מפורטות בסעיף 3 של RFC 3986.
כללי אימות | |
---|---|
Scheme |
מזהי URI להפניה אוטומטית חייבים להשתמש בפרוטוקול HTTPS, ולא ב-HTTP רגיל. מזהי URI של מארח מקומי (כולל מזהי URI של כתובות IP של Localhost) פטורים מהכלל הזה. |
מארח |
לא ניתן להשתמש בכתובות IP גולמיות כמארחים. כתובות IP של localhost פטורות מהכלל הזה. |
דומיין |
“googleusercontent.com” .goo.gl ), אלא אם הדומיין הוא בבעלות האפליקציה. בנוסף, אם אפליקציה שבבעלותה דומיין קיצור בוחרת להפנות לדומיין הזה, מזהה ה-URI של ההפניה האוטומטית חייב להכיל את הערך “/google-callback/” בנתיב שלו או להסתיים ב-“/google-callback” . |
Userinfo |
כתובות URI להפניה אוטומטית לא יכולות להכיל את רכיב המשנה userinfo. |
נתיב |
מזהי URI להפניה אוטומטית לא יכולים להכיל מעבר נתיב (נקרא גם חזרה אחורה בספרייה), שמיוצג על ידי |
שאילתה |
מזהי URI להפניה אוטומטית לא יכולים לכלול הפניות אוטומטיות פתוחות. |
מקטע |
מזהי URI של הפניות אוטומטיות לא יכולים להכיל את רכיב המקטע. |
דמויות |
מזהי URI להפניה אוטומטית לא יכולים להכיל תווים מסוימים, כולל:
|
הרשאה מצטברת
בפרוטוקול OAuth 2.0, האפליקציה מבקשת הרשאת גישה למשאבים שמזוהים לפי היקפים. מומלץ לבקש הרשאה למשאבים בזמן הצורך, כדי לשפר את חוויית המשתמש. כדי לאפשר את השיטה הזו, שרת ההרשאות של Google תומך בהרשאה מצטברת. התכונה הזו מאפשרת לבקש היקפי גישה לפי הצורך, ואם המשתמש מעניק הרשאה להיקף הגישה החדש, היא מחזירה קוד הרשאה שאפשר להמיר לטוקן שמכיל את כל היקפי הגישה שהמשתמש העניק לפרויקט.
לדוגמה, אפליקציה שמאפשרת לאנשים לדגום טראקים של מוזיקה וליצור מיקסים עשויה להזדקק למעט מאוד משאבים בזמן הכניסה לחשבון, אולי לא יותר מהשם של האדם שנכנס לחשבון. עם זאת, כדי לשמור את המיקס המוגמר, תצטרכו גישה ל-Google Drive שלהם. רוב האנשים ימצאו את זה טבעי אם תתבקשו מהם גישה ל-Google Drive רק בזמן שהאפליקציה באמת זקוקה לה.
במקרה כזה, בזמן הכניסה, האפליקציה עשויה לבקש את ההיקפים openid
ו-profile
כדי לבצע כניסה בסיסית, ולאחר מכן לבקש את ההיקף https://www.googleapis.com/auth/drive.file
בזמן הבקשה הראשונה כדי לשמור מיקס.
כדי להטמיע הרשאה מצטברת, צריך להשלים את התהליך הרגיל של בקשת אסימון גישה, אבל לוודא שבקשת ההרשאה כוללת היקפים שהוקצו בעבר. כך האפליקציה לא צריכה לנהל כמה אסימוני גישה.
הכללים הבאים חלים על אסימון גישה שמתקבל מהרשאה מצטברת:
- אפשר להשתמש באסימון כדי לגשת למשאבים שתואמים לכל אחד מההיקפים שצורפו להרשאה המשולבת החדשה.
- כשמשתמשים בטוקן הרענון לאישור המשולב כדי לקבל אסימון גישה, אסימון הגישה מייצג את האישור המשולב וניתן להשתמש בו לכל אחד מהערכים של
scope
שכלולים בתגובה. - ההרשאה המשולבת כוללת את כל היקפי ההרשאות שהמשתמש העניק לפרויקט ה-API, גם אם בקשות ההרשאה התקבלו מלקוחות שונים. לדוגמה, אם משתמש העניק גישה להיקף אחד באמצעות לקוח במחשב של אפליקציה, ולאחר מכן העניק היקף אחר לאותה אפליקציה דרך לקוח בנייד, ההרשאה המשולבת תכלול את שני ההיקפים.
- אם מבטלים אסימון שמייצג הרשאה משולבת, הגישה לכל ההיקפים של ההרשאה בשם המשתמש המשויך מבוטלת בו-זמנית.
בדוגמאות הקוד הספציפיות לשפות שמפורטות בקטע שלב 1: הגדרת הפרמטרים של ההרשאה ובכתובת ה-URL לדוגמה להפניה אוטומטית מסוג HTTP/REST שמפורטת בקטע שלב 2: הפניה אוטומטית לשרת OAuth 2.0 של Google נעשה שימוש בהרשאה מצטברת. בדוגמאות הקוד שבהמשך מוצג גם הקוד שצריך להוסיף כדי להשתמש בהרשאה מצטברת.
PHP
$client->setIncludeGrantedScopes(true);
Python
ב-Python, מגדירים את הארגומנט include_granted_scopes
של מילת המפתח ל-true
כדי לוודא שבקשת ההרשאה כוללת היקפים שניתנו בעבר. יכול להיות מאוד
שהארגומנט include_granted_scopes
לא יהיה הארגומנט היחיד של מילת המפתח שתגדירו, כמו בדוגמה הבאה.
authorization_url, state = flow.authorization_url( # Enable offline access so that you can refresh an access token without # re-prompting the user for permission. Recommended for web server apps. access_type='offline', # Enable incremental authorization. Recommended as a best practice. include_granted_scopes='true')
Ruby
auth_client.update!( :additional_parameters => {"include_granted_scopes" => "true"} )
Node.js
const authorizationUrl = oauth2Client.generateAuthUrl({ // 'online' (default) or 'offline' (gets refresh_token) access_type: 'offline', /** Pass in the scopes array defined above. * Alternatively, if only one scope is needed, you can pass a scope URL as a string */ scope: scopes, // Enable incremental authorization. Recommended as a best practice. include_granted_scopes: true });
HTTP/REST
GET https://accounts.google.com/o/oauth2/v2/auth? client_id=your_client_id& response_type=code& state=state_parameter_passthrough_value& scope=https%3A//www.googleapis.com/auth/drive.file& redirect_uri=https%3A//oauth2.example.com/code& prompt=consent& include_granted_scopes=true
רענון אסימון גישה (גישה אופליין)
התוקף של אסימוני הגישה פג מדי פעם והם הופכים לפרטי כניסה לא חוקיים לבקשת API קשורה. אם ביקשת גישה אופליין להיקפי ההרשאות שמשויכים לאסימון, אפשר לרענן אסימון גישה בלי לבקש הרשאה מהמשתמש (גם כשהמשתמש לא נמצא).
- אם אתם משתמשים בספריית לקוח של Google API, אובייקט הלקוח מעדכן את אסימון הגישה לפי הצורך, כל עוד הגדרתם את האובייקט הזה לגישה אופליין.
- אם אתם לא משתמשים בספריית לקוח, עליכם להגדיר את פרמטר השאילתה של HTTP
access_type
לערךoffline
כשמפנים את המשתמש לשרת OAuth 2.0 של Google. במקרה כזה, שרת ההרשאות של Google מחזיר אסימון רענון כשמחליפים קוד הרשאה באסימון גישה. לאחר מכן, אם פג התוקף של אסימון הגישה (או בכל שלב אחר), תוכלו להשתמש באסימון הרענון כדי לקבל אסימון גישה חדש.
שליחת בקשה לגישה אופליין היא דרישה לכל אפליקציה שצריכה לגשת ל-Google API כשהמשתמש לא נמצא. לדוגמה, אפליקציה שמבצעת שירותי גיבוי או מבצעת פעולות במועדים מוגדרים מראש צריכה להיות מסוגלת לרענן את אסימון הגישה שלה כשהמשתמש לא נמצא. סגנון הגישה שמוגדר כברירת מחדל נקרא online
.
אפליקציות אינטרנט בצד השרת, אפליקציות מותקנות ומכשירים מקבלים אסימוני רענון במהלך תהליך ההרשאה. בדרך כלל לא משתמשים באסימוני רענון באפליקציות אינטרנט בצד הלקוח (JavaScript).
PHP
אם האפליקציה שלכם צריכה גישה אופליין ל-Google API, צריך להגדיר את סוג הגישה של לקוח ה-API כ-offline
:
$client->setAccessType("offline");
אחרי שמשתמש מעניק גישה אופליין להיקפים המבוקשים, אפשר להמשיך להשתמש בלקוח ה-API כדי לגשת ל-Google APIs בשם המשתמש כשהוא אופליין. אובייקט הלקוח ירענן את אסימון הגישה לפי הצורך.
Python
ב-Python, מגדירים את הארגומנט של מילת המפתח access_type
לערך offline
כדי להבטיח שיהיה אפשר לרענן את אסימון הגישה בלי לבקש הרשאה מחדש מהמשתמש. יכול להיות מאוד ש-access_type
לא יהיה הארגומנט היחיד של מילת המפתח שתגדירו, כפי שמוצג בדוגמה הבאה.
authorization_url, state = flow.authorization_url( # Enable offline access so that you can refresh an access token without # re-prompting the user for permission. Recommended for web server apps. access_type='offline', # Enable incremental authorization. Recommended as a best practice. include_granted_scopes='true')
אחרי שמשתמש מעניק גישה אופליין להיקפי ההרשאות המבוקשים, אפשר להמשיך להשתמש בלקוח ה-API כדי לגשת לממשקי Google API מטעם המשתמש כשהוא אופליין. אובייקט הלקוח ירענן את אסימון הגישה לפי הצורך.
Ruby
אם לאפליקציה שלכם נדרשת גישה אופליין ל-Google API, צריך להגדיר את סוג הגישה של לקוח ה-API ל-offline
:
auth_client.update!( :additional_parameters => {"access_type" => "offline"} )
אחרי שמשתמש מעניק גישה אופליין להיקפים המבוקשים, אפשר להמשיך להשתמש בלקוח ה-API כדי לגשת ל-Google APIs בשם המשתמש כשהוא אופליין. אובייקט הלקוח ירענן את אסימון הגישה לפי הצורך.
Node.js
אם לאפליקציה שלכם דרושה גישה אופליין ל-Google API, צריך להגדיר את סוג הגישה של לקוח ה-API ל-offline
:
const authorizationUrl = oauth2Client.generateAuthUrl({ // 'online' (default) or 'offline' (gets refresh_token) access_type: 'offline', /** Pass in the scopes array defined above. * Alternatively, if only one scope is needed, you can pass a scope URL as a string */ scope: scopes, // Enable incremental authorization. Recommended as a best practice. include_granted_scopes: true });
אחרי שמשתמש מעניק גישה אופליין להיקפי ההרשאות המבוקשים, אפשר להמשיך להשתמש בלקוח ה-API כדי לגשת לממשקי Google API מטעם המשתמש כשהוא אופליין. אובייקט הלקוח ירענן את אסימון הגישה לפי הצורך.
תוקף אסימוני הגישה פג. הספרייה הזו תשתמש באופן אוטומטי באסימון רענון כדי לקבל אסימון גישה חדש אם התוקף שלו עומד לפוג. כדי לוודא שאתם תמיד שומרים את האסימונים העדכניים ביותר, תוכלו להשתמש באירוע האסימונים:
oauth2Client.on('tokens', (tokens) => { if (tokens.refresh_token) { // store the refresh_token in your secure persistent database console.log(tokens.refresh_token); } console.log(tokens.access_token); });
אירוע האסימונים הזה מתרחש רק באישור הראשון, וצריך להגדיר את access_type
לערך offline
כשקוראים לשיטה generateAuthUrl
כדי לקבל את אסימון הרענון. אם כבר הענקתם לאפליקציה את ההרשאות הנדרשות בלי להגדיר את האילוצים המתאימים לקבלת אסימון רענון, תצטרכו להעניק לאפליקציה הרשאה מחדש כדי לקבל אסימון רענון חדש.
כדי להגדיר את refresh_token
במועד מאוחר יותר, אפשר להשתמש בשיטה setCredentials
:
oauth2Client.setCredentials({ refresh_token: `STORED_REFRESH_TOKEN` });
אחרי שהלקוח יקבל אסימון רענון, אסימוני הגישה יירכשו ויתרעננו באופן אוטומטי בקריאה הבאה ל-API.
HTTP/REST
כדי לרענן אסימון גישה, האפליקציה שולחת בקשת POST
ב-HTTPS לשרת ההרשאות של Google (https://oauth2.googleapis.com/token
) שכוללת את הפרמטרים הבאים:
שדות | |
---|---|
client_id |
מזהה הלקוח שהתקבל מ- API Console. |
client_secret |
סוד הלקוח שהתקבל מ- API Console. |
grant_type |
כפי שמוגדר במפרט של OAuth 2.0, הערך של השדה הזה צריך להיות refresh_token . |
refresh_token |
אסימון הרענון שהוחזר מההמרה של קוד ההרשאה. |
בקטע הקוד הבא מוצגת בקשה לדוגמה:
POST /token HTTP/1.1 Host: oauth2.googleapis.com Content-Type: application/x-www-form-urlencoded client_id=your_client_id& client_secret=your_client_secret& refresh_token=refresh_token& grant_type=refresh_token
כל עוד המשתמש לא ביטל את הגישה שהוקצה לאפליקציה, שרת האסימונים מחזיר אובייקט JSON שמכיל אסימון גישה חדש. קטע הקוד הבא מציג תשובה לדוגמה:
{ "access_token": "1/fFAGRNJru1FTz70BzhT3Zg", "expires_in": 3920, "scope": "https://www.googleapis.com/auth/drive.metadata.readonly", "token_type": "Bearer" }
חשוב לדעת שיש מגבלות על מספר אסימוני הרענון שיונפק. יש מגבלה אחת לכל שילוב של לקוח/משתמש, ומגבלה נוספת לכל משתמש בכל הלקוחות. מומלץ לשמור אסימוני רענון באחסון לטווח ארוך ולהמשיך להשתמש בהם כל עוד הם בתוקף. אם האפליקציה שלכם מבקשת יותר מדי אסימוני רענון, היא עלולה להגיע למגבלות האלה. במקרה כזה, אסימוני רענון ישנים יותר יפסיקו לפעול.
ביטול טוקן
במקרים מסוימים, משתמשים עשויים לרצות לבטל את הגישה שניתנה לאפליקציה. משתמשים יכולים לבטל את הגישה שלהם דרך הגדרות החשבון. למידע נוסף, אפשר לעיין בקטע התמיכה לגבי הסרת הגישה של אתר או אפליקציה מאתרים ואפליקציות של צד שלישי שיש להם גישה לחשבון.
אפשר גם לבטל באופן פרוגרמטי את הגישה שניתנה לאפליקציה. ביטול תוכני קוד חשוב במקרים שבהם משתמש מבטל את המינוי, מסיר אפליקציה או שמשאבי ה-API הנדרשים לאפליקציה השתנו באופן משמעותי. במילים אחרות, חלק מתהליך ההסרה יכול לכלול בקשת API כדי לוודא שההרשאות שהוקצו לאפליקציה בעבר יוסרו.
PHP
כדי לבטל אסימון באופן פרוגרמטי, קוראים לפונקציה revokeToken()
:
$client->revokeToken();
Python
כדי לבטל אסימון באופן פרוגרמטי, שולחים בקשה אל https://oauth2.googleapis.com/revoke
שכוללת את האסימון כפרמטר ומגדירה את הכותרת Content-Type
:
requests.post('https://oauth2.googleapis.com/revoke', params={'token': credentials.token}, headers = {'content-type': 'application/x-www-form-urlencoded'})
Ruby
כדי לבטל אסימון באופן פרוגרמטי, שולחים בקשת HTTP לנקודת הקצה oauth2.revoke
:
uri = URI('https://oauth2.googleapis.com/revoke') response = Net::HTTP.post_form(uri, 'token' => auth_client.access_token)
האסימון יכול להיות אסימון גישה או אסימון רענון. אם האסימון הוא אסימון גישה ויש לו אסימון רענון תואם, גם אסימון הרענון יבוטל.
אם הביטול יעובד, קוד הסטטוס של התשובה יהיה 200
. במקרים של שגיאות, מוחזר קוד הסטטוס 400
יחד עם קוד שגיאה.
Node.js
כדי לבטל אסימון באופן פרוגרמטי, שולחים בקשת POST מסוג HTTPS לנקודת הקצה /revoke
:
const https = require('https'); // Build the string for the POST request let postData = "token=" + userCredential.access_token; // Options for POST request to Google's OAuth 2.0 server to revoke a token let postOptions = { host: 'oauth2.googleapis.com', port: '443', path: '/revoke', method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded', 'Content-Length': Buffer.byteLength(postData) } }; // Set up the request const postReq = https.request(postOptions, function (res) { res.setEncoding('utf8'); res.on('data', d => { console.log('Response: ' + d); }); }); postReq.on('error', error => { console.log(error) }); // Post the request with data postReq.write(postData); postReq.end();
פרמטר האסימון יכול להיות אסימון גישה או אסימון רענון. אם האסימון הוא אסימון גישה ויש לו אסימון רענון תואם, גם אסימון הרענון יבוטל.
אם הביטול יעובד, קוד הסטטוס של התשובה יהיה 200
. בתנאים של שגיאה, קוד הסטטוס 400
מוחזר יחד עם קוד שגיאה.
HTTP/REST
כדי לבטל אסימון באופן פרוגרמטי, האפליקציה שולחת בקשה אל 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
מוחזר יחד עם קוד שגיאה.
הטמעת ההגנה על כל החשבונות
כדי להגן על החשבונות של המשתמשים, צריך לבצע פעולה נוספת כדי להגן על החשבונות של המשתמשים: הטמעת הגנה על כל החשבונות באמצעות השירות של Google להגנה על כל החשבונות. השירות הזה מאפשר לכם להירשם לקבלת התראות על אירועי אבטחה, שמספקות לאפליקציה מידע על שינויים משמעותיים בחשבון המשתמש. לאחר מכן תוכלו להשתמש במידע הזה כדי לבצע פעולות בהתאם לאופן שבו תבחרו להגיב לאירועים.
דוגמאות לסוגי האירועים שנשלחים לאפליקציה שלכם על ידי שירות ההגנה על חשבונות שונים של Google:
-
https://schemas.openid.net/secevent/risc/event-type/sessions-revoked
-
https://schemas.openid.net/secevent/oauth/event-type/token-revoked
-
https://schemas.openid.net/secevent/risc/event-type/account-disabled
במאמר הגנה על חשבונות משתמשים באמצעות הגנה על כל החשבונות מוסבר איך מטמיעים את ההגנה על כל החשבונות ומופיעה רשימה מלאה של האירועים הזמינים.