เอกสารนี้อธิบายวิธีที่แอปพลิเคชันเว็บเซิร์ฟเวอร์ใช้ไลบรารีของไคลเอ็นต์ Google API หรือปลายทาง Google OAuth 2.0 เพื่อใช้การให้สิทธิ์แบบ OAuth 2.0 ในการเข้าถึง Google APIs
OAuth 2.0 อนุญาตให้ผู้ใช้แชร์ข้อมูลบางอย่างกับแอปพลิเคชันโดยที่ยังเก็บชื่อผู้ใช้ รหัสผ่าน และข้อมูลอื่นๆ ไว้เป็นส่วนตัว ตัวอย่างเช่น แอปพลิเคชันสามารถใช้ OAuth 2.0 เพื่อขอสิทธิ์จากผู้ใช้ในการจัดเก็บไฟล์ใน Google ไดรฟ์
ขั้นตอน 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 นั้นๆ อยู่
- เลือก 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 Clients page.
- คลิกสร้างไคลเอ็นต์
- เลือกประเภทแอปพลิเคชันเป็นเว็บแอปพลิเคชัน
- กรอกแบบฟอร์ม แล้วคลิกสร้าง แอปพลิเคชันที่ใช้ภาษาและเฟรมเวิร์ก
เช่น 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 API
ข้อกำหนดเฉพาะภาษา
หากต้องการเรียกใช้ตัวอย่างโค้ดในเอกสารนี้ คุณจะต้องมีบัญชี Google, สิทธิ์เข้าถึง อินเทอร์เน็ต และเว็บเบราว์เซอร์ หากคุณใช้ไลบรารีของไคลเอ็นต์ API รายการใดรายการหนึ่ง โปรดดูข้อกำหนดเฉพาะภาษาด้านล่างด้วย
PHP
หากต้องการเรียกใช้ตัวอย่างโค้ด PHP ในเอกสารนี้ คุณจะต้องมีสิ่งต่อไปนี้
- PHP 8.0 ขึ้นไปที่มีการติดตั้งอินเทอร์เฟซบรรทัดคำสั่ง (CLI) และส่วนขยาย JSON
- เครื่องมือการจัดการการขึ้นต่อกันของ Composer
-
ไลบรารีของไคลเอ็นต์ Google APIs สำหรับ PHP
composer require google/apiclient:^2.15.0
ดูข้อมูลเพิ่มเติมได้ที่ไลบรารีของไคลเอ็นต์ Google APIs สำหรับ PHP
Python
หากต้องการเรียกใช้ตัวอย่างโค้ด Python ในเอกสารนี้ คุณจะต้องมีสิ่งต่อไปนี้
- Python 3.7 ขึ้นไป
- เครื่องมือจัดการแพ็กเกจ pip
- การเปิดตัวไลบรารีของไคลเอ็นต์ Google APIs สำหรับ Python 2.0
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 ของ
requestspip install --upgrade requests
อ่านหมายเหตุประจำรุ่นของไลบรารีของไคลเอ็นต์ Google API สำหรับ Python หากคุณอัปเกรด Python และคู่มือการย้ายข้อมูลที่เกี่ยวข้องไม่ได้
Ruby
หากต้องการเรียกใช้ตัวอย่างโค้ด Ruby ในเอกสารนี้ คุณจะต้องมีสิ่งต่อไปนี้
- Ruby 2.6 ขึ้นไป
-
ไลบรารีการตรวจสอบสิทธิ์ของ Google สำหรับ Ruby
gem install googleauth
-
ไลบรารีของไคลเอ็นต์สำหรับ Google API ของไดรฟ์และ��ฏิทิน
gem install google-apis-drive_v3 google-apis-calendar_v3
-
เฟรมเวิร์กเว็บแ���ปพลิเคชัน Sinatra Ruby
gem install sinatra
Node.js
คุณต้องมีสิ่งต่อไปนี้จึงจะเรียกใช้ตัวอย่างโค้ด Node.js ในเอกสารนี้ได้
- LTS ที่มีการบำรุงรักษา, LTS ที่ใช้งานอยู่ หรือรุ่นปัจจุบันของ Node.js
-
ไคลเอ็นต์ Node.js ของ Google APIs
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 ไดรฟ์และกิจกรรมในปฏิทินของผู้ใช้
use Google\Client; $client = new 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, Google\Service\Calendar::CALENDAR_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 ไดรฟ์และกิจกรรมในปฏิทินของผู้ใช้
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', 'https://www.googleapis.com/auth/calendar.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 ไดรฟ์และกิจกรรมในปฏิทินของผู้ใช้
require 'googleauth' require 'googleauth/web_user_authorizer' require 'googleauth/stores/redis_token_store' require 'google/apis/drive_v3' require 'google/apis/calendar_v3' # Required, call the from_file method to retrieve the client ID from a # client_secret.json file. client_id = Google::Auth::ClientId.from_file('/path/to/client_secret.json') # Required, scope value # Access scopes for two non-Sign-In scopes: Read-only Drive activity and Google Calendar. scope = ['Google::Apis::DriveV3::AUTH_DRIVE_METADATA_READONLY', 'Google::Apis::CalendarV3::AUTH_CALENDAR_READONLY'] # Required, Authorizers require a storage instance to manage long term persistence of # access and refresh tokens. token_store = Google::Auth::Stores::RedisTokenStore.new(redis: Redis.new) # 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. callback_uri = '/oauth2callback' # 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. authorizer = Google::Auth::WebUserAuthorizer.new(client_id, scope, token_store, callback_uri)
แอปพลิเคชันของคุณใช้ออบเจ็กต์ไคลเอ็นต์เพื่อดำเนินการ 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 two non-Sign-In scopes: Read-only Drive activity and Google Calendar. const scopes = [ 'https://www.googleapis.com/auth/drive.metadata.readonly', 'https://www.googleapis.com/auth/calendar.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 and Google Calendar 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 |
จำเป็น
รหัสไคลเอ็นต์สำหรับแอปพลิเคชัน คุณดูค่านี้ได้ใน Cloud Console Clients page |
||||||
redirect_uri |
จำเป็น
กำหนดว่าเซิร์ฟเวอร์ API จะเปลี่ยนเส้นทางผู้ใช้ไปที่ใดหลังจากที่ผู้ใช้ทำขั้นตอนการให้สิทธิ์เสร็จสมบูรณ์
ค่าต้องตรงกับ URI การเปลี่ยนเส้นทางที่ได้รับอนุญาตสำหรับไคลเอ็นต์ OAuth 2.0 ซึ่งคุณกำหนดค่าไว้ใน Cloud Console
Clients pageของไคลเอ็นต์ หากค่านี้ไม่ตรงกับ URI การเปลี่ยนเส้นทางที่ได้รับอนุญาตสำหรับ โปรดทราบว่ารูปแบบ |
||||||
response_type |
จำเป็น
กำหนดว่าปลายทาง Google OAuth 2.0 จะแสดงรหัสการให้สิทธิ์หรือไม่ ตั้งค่าพารามิเตอร์เป็น |
||||||
scope |
จำเป็น
รายการขอบเขตที่คั่นด้วยช่องว่างซึ่งระบุทรัพยากรที่แอปพลิเคชันของคุณเข้าถึงได้ในนามของผู้ใช้ ค่าเหล่านี้จะแจ้งให้หน้าจอคำยินยอมที่ Google แสดงต่อผู้ใช้ทราบ ขอบเขตช่วยให้แอปพลิเคชันขอสิทธิ์เข้าถึงเฉพาะทรัพยากรที่จำเป็น ในขณะเดียวกันก็ช่วยให้ผู้ใช้ควบคุมระดับการเข้าถึงที่อนุญาตให้แอปพลิเคชันของคุณได้ด้วย ดังนั้น จำนวนขอบเขตที่ขอ จึงมีความสัมพันธ์แบบผกผันกั��แนวโน้มที่จะได้รับความยินยอมจากผู้ใช้ เราขอแนะนำให้แอปพลิเคชันของคุณขอสิทธิ์เข้าถึงขอบเขตการให้สิทธิ์ในบริบท เมื่อใดก็ตามที่เป็นไปได้ การขอสิทธิ์เข้าถึงข้อมูลผู้ใช้ตามบริบทโดยใช้การให้สิทธิ์ทีละส่วนจะช่วยให้ผู้ใช้ เข้าใจว่าทำไมแอปพลิเคชันของคุณจึงต้องการสิทธิ์เข้าถึงที่ขอ |
||||||
access_type |
แนะนำ
ระบุว่าแอปพลิเคชันของคุณจะรีเฟรชโทเค็นการเข้าถึงได้หรือไม่เมื่อผู้ใช้ไม่ได้อยู่ที่เบราว์เซอร์
ค่าพารามิเตอร์ที่ใช้ได้คือ ตั้งค่าเป็น |
||||||
state |
แนะนำ
ระบุค่าสตริงที่แอปพลิเคชันใช้เพื่อรักษาสถานะระหว่างคำขอการให้สิทธิ์กับคำตอบของเซิร์ฟเวอร์การให้สิทธิ์
เซิร์ฟเวอร์จะแสดงค่าที่แน่นอนที่คุณส่งเป็นคู่ คุณใช้พารามิเตอร์นี้ได้หลายวัตถุประสงค์ เช่น การนำผู้ใช้ไปยัง
แหล่งข้อมูลที่ถูกต้องในแอปพลิเคชัน การส่ง Nonce และการลดการปลอมแปลงคำขอข้ามเว็บไซต์
เนื่องจาก |
||||||
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(request: request)
- เปลี่ยนเส้นทางผู้ใช้ไปยัง
auth_uri
Node.js
-
ใช้ URL ที่สร้างขึ้น
authorizationUrlจากขั้นตอนที่ 1 วิธีgenerateAuthUrlเพื่อขอสิทธิ์เข้าถึงจากเซิร์ฟเวอร์ OAuth 2.0 ของ Google -
เปลี่ยนเส้นทางผู้ใช้ไปยัง
authorizationUrlres.redirect(authorizationUrl);
HTTP/REST
ตัวอย่างการเปลี่ยนเส้นทางไปยังเซิร์ฟเวอร์การให้สิทธิ์ของ Google
ตัวอย่าง URL แสดงอยู่ด้านล่าง โดยมีการเว้นบรรทัดและเว้นวรรคเพื่อให้ง่ายต่อการอ่าน
https://accounts.google.com/o/oauth2/v2/auth? scope=https%3A//www.googleapis.com/auth/drive.metadata.readonly%20https%3A//www.googleapis.com/auth/calendar.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 คำขอแล้ว ให้เปลี่ยนเส้นทางผู้ใช้ไปยัง URL นั้น
เซิร์ฟเวอร์ OAuth 2.0 ของ Google จะตรวจสอบสิทธิ์ผู้ใช้และขอรับความยินยอมจากผู้ใช้เพื่อให้แอปพลิเคชันของคุณเข้าถึงขอบเขตที่ขอ ระบบจะส่งการตอบกลับกลับไปยังแอปพลิเคชันของคุณ โดยใช้ URL เปลี่ยนเส้นทางที่คุณระบุ
ขั้นตอนที่ 3: Google ขอความยินยอมจากผู้ใช้
ในขั้นตอนนี้ ผู้ใช้จะเลือกว่าจะให้สิทธิ์เข้าถึงที่แอปพลิเคชันของคุณร้องขอหรือไม่ ในขั้นตอนนี้ Google จะแสดงหน้าต่างความยินยอมซึ่งแสดงชื่อแอปพลิเคชันและบริการ Google API ที่แอปพลิเคชันกำลังขอสิทธิ์เข้าถึงด้วยข้อมูลเข้าสู่ระบบการให้สิทธิ์ของผู้ใช้ รวมถึง สรุปขอบเขตการเข้าถึงที่จะได้รับ จากนั้นผู้ใช้จะให้ความยินยอมในการให้สิทธิ์เข้าถึงขอบเขตอย่างน้อย 1 รายการที่แอปพลิเคชันของคุณขอ หรือปฏิเสธคำขอได้
แอปพลิเคชันของคุณไม่จำเป็นต้องดำเนินการใดๆ ในขั้นตอนนี้ เนื่องจากรอการตอบกลับจากเซิร์ฟเวอร์ OAuth 2.0 ของ Google ซึ่งจะระบุว่ามีการให้สิทธิ์เข้าถึงหรือไม่ ซึ่งจะอธิบายในขั้นตอนต่อไป
ข้อผิดพลาด
คำขอไปยังปลายทางการให้สิทธิ์ OAuth 2.0 ของ Google อาจแสดงข้อความแสดงข้อผิดพลาดที่ผู้ใช้เห็น แทนที่จะเป็นขั้นตอนการตรวจสอบสิทธิ์และการให้สิทธิ์ที่คาดไว้ รหัสข้อผิดพลาดที่พบบ่อยและวิธีแก้ไขที่แนะนำมีดังนี้
admin_policy_enforced
บัญชี Google ไม่สามารถให้สิทธิ์ขอบเขตอย่างน้อย 1 รายการที่ขอเนื่องจากนโยบายของผู้ดูแลระบบ Google Workspace ดูข้อมูลเพิ่มเติ��เกี่ยวกับวิธีที่ผู้ดูแลระบบอาจจำกัดการเข้าถึงขอบเขตทั้งหมดหรือขอบเขตที่มีความละเอียดอ่อนและ จำกัดจนกว่าจะมีการให้สิทธิ์เข้าถึงรหัสไคลเอ็นต์ OAuth อย่างชัดแจ้งได้ที่บทความช่วยเหลือสำหรับผู้ดูแลระบบ Google Workspace ควบคุมว่าจะให้แอปของบุคคลที่สามและแอปภายในรายการใดเข้าถึงข้อมูล Google Workspace ได้บ้าง
disallowed_useragent
ปลายทางการให้สิทธิ์จะแสดงภายใน User-Agent แบบฝังที่นโยบาย OAuth 2.0 ของ Google ไม่อนุญาต
นักพัฒนาแอป iOS และ macOS อาจพบข้อผิดพลาดนี้เมื่อเปิดคำขอการให้สิทธิ์ใน
WKWebView
นักพัฒนาแอปควรใช้ไลบรารี iOS เช่น
Google Sign-In สำหรับ iOS หรือ
AppAuth สำหรับ iOS ของ OpenID Foundation แทน
นักพัฒนาเว็บอาจพบข้อผิดพลาดนี้เมื่อแอป iOS หรือ macOS เปิดลิงก์เว็บทั่วไปใน
User-Agent ที่ฝังอยู่ และผู้ใช้นำทางไปยังปลายทางการให้สิทธิ์ OAuth 2.0 ของ Google จาก
เว็บไซต์ของคุณ นักพัฒนาแอปควรอำนวยความสะดวกให้ลิงก์ทั่วไปเปิดในตัวแฮนเดิลลิงก์เริ่มต้นของ
ระบบปฏิบัติการ ซึ่งรวมถึงทั้งตัวแฮนเดิล
Universal Link
หรือแอปเบราว์เซอร์เริ่มต้น นอกจากนี้ ไลบรารี SFSafariViewController
ยังเป็นตัวเลือกที่รองรั����้����
org_internal
รหัสไคลเอ็นต์ OAuth ในคำขอเป็นส่วนหนึ่งของโปรเจ็กต์ที่จำกัดกา���เข้าถึงบัญชี Google ใน องค์กร Google Cloud ที่เฉพาะเจาะจง ดูข้อมูลเพิ่มเติมเกี่ยวกับตัวเลือกการกำหนดค่านี้ได้ที่ส่วนประเภทผู้ใช้ในบทความช่วยเหลือเกี่ยวกับการตั้งค่าหน้าจอขอความยินยอม OAuth
invalid_client
รหัสลับไคลเอ็นต์ OAuth ไม่ถูกต้อง ตรวจสอบการกำหนดค่าไคลเอ็นต์ OAuth รวมถึงรหัสไคลเอ็นต์และรหัสลับที่ใช้สำหรับคำขอนี้
deleted_client
ไคลเอ็นต์ OAuth ที่ใช้ส่งคำขอถูกลบไปแล้ว การลบอาจเกิดขึ้นด้วยตนเอง หรือโดยอัตโนมัติในกรณีของ ไคลเอ็นต์ที่ไม่ได้ใช้ คุณกู้คืนลูกค้าที่ถูกลบได้ภายใน 30 วันนับจากวันที่ลบ ดูข้อมูลเพิ่มเติม
invalid_grant
เมื่อรีเฟรชโทเค็นเพื่อการเข้าถึงหรือใช้ การให้สิทธิ์แบบเพิ่มทีละรายการ โทเค็นอาจหมดอายุหรือ ถูกทำให้ใช้ไม่ได้ ตรวจสอบสิทธิ์ผู้ใช้อีกครั้งและขอความยินยอมจากผู้ใช้เพื่อรับโทเค็นใหม่ หากยังเห็นข้อผิดพลาดนี้อยู่ โปรดตรวจสอบว่าได้กำหนดค่าแอปพลิเคชันอย่างถูกต้อง และคุณใช้โทเค็นและพารามิเตอร์ที่ถูกต้องในคำขอ มิฉะนั้นบัญชีผู้ใช้อาจถูกลบหรือปิ��ใช้
redirect_uri_mismatch
redirect_uri ที่ส่งในคำขอการให้สิทธิ์ไม่ตรงกับ URI การเปลี่ยนเส้นทางที่ได้รับอนุญาต
สำหรับรหัสไคลเอ็นต์ OAuth ตรวจสอบ URI การเปลี่ยนเส้นทางที่ได้รับอนุญาตใน
Google Cloud Console
Clients 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
คุณทดสอบโฟลว์นี้ได้โดยคลิกลิงก์ตัวอย่างต่อไปนี้ ซึ่งจะขอสิทธิ์เข้าถึงแบบอ่านอย่างเดียวเพื่อดูข้อมูลเมตาของไฟล์ใน Google ไดรฟ์ และสิทธิ์เข้าถึงแบบอ่านอย่างเดียวเพื่อดูกิจกรรมใน Google ปฏิทิน
https://accounts.google.com/o/oauth2/v2/auth? scope=https%3A//www.googleapis.com/auth/drive.metadata.readonly%20https%3A//www.googleapis.com/auth/calendar.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
หากต้องการแลกรหัสการให้สิทธิ์เป็นโทเค็นเพื่อการเข้าถึง ให้ใช้วิธี fetchAccessTokenWithAuthCode ดังนี้
$access_token = $client->fetchAccessTokenWithAuthCode($_GET['code']);Python
ในหน้าเรียกกลับ ให้ใช้ไลบรารี google-auth เพื่อยืนยันการตอบกลับของเซิร์ฟเวอร์การให้สิทธิ์
จากนั้นใช้วิธี 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 browser session storage, but for security: client_id, client_secret, # and token_uri are instead stored only on the backend server. credentials = flow.credentials flask.session['credentials'] = { 'token': credentials.token, 'refresh_token': credentials.refresh_token, 'granted_scopes': credentials.granted_scopes}
Ruby
ในหน้าเรียกกลับ ให้ใช้ไลบรารี googleauth เพื่อยืนยันการตอบกลับของเซิร์ฟเวอร์การให้สิทธิ์
ใช้เมธอด authorizer.handle_auth_callback_deferred เพื่อบันทึก
รหัสการให้สิทธิ์และเปลี่ยนเส้นทางกลับไปยัง URL ที่ขอการให้สิทธิ์ในตอนแรก ซึ่งจะ
เลื่อนการแลกรหัสโดยการซ่อนผลลัพธ์ไว้ชั่วคราวในเซสชันของผู้ใช้
target_url = Google::Auth::WebUserAuthorizer.handle_auth_callback_deferred(request) redirect target_url
Node.js
หากต้องการแลกรหัสการให้สิทธิ์เป็นโทเค็นเพื่อการเข้าถึง ให้ใช้วิธี 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 |
รหัสไคลเอ็นต์ที่ได้รับจาก Cloud Console Clients page |
client_secret |
ไม่บังคับ
รหัสลับไคลเอ็นต์ที่ได้รับจาก Cloud Console Clients page |
code |
รหัสการให้สิทธิ์ที่แสดงผลจากคำขอเริ่มต้น |
grant_type |
ตามที่กำหนดไว้ในข้อกำหนด OAuth 2.0 ค่าของช่องนี้ต้องตั้งเป็น authorization_code |
redirect_uri |
URI การเปลี่ยนเส้นทางรายการใดรายการหนึ่งที่แสดงสำหรับโปรเจ็กต์ของคุณใน
Cloud Console
Clients 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& 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
|
refresh_token_expires_in |
อายุการใช้งานที่เหลือของโทเค็นการรีเฟรชเป็นวินาที ค่านี้จะตั้งค่าก็ต่อเมื่อผู้ใช้ให้สิทธิ์เข้าถึงตามเวลาเท่านั้น |
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 https://www.googleapis.com/auth/calendar.readonly", "refresh_token": "1//xEoDL4iW3cxlI7yDbSRFYNG01kVKM2C-259HOF2aQbI" }
ข้อผิดพลาด
เมื่อแลกรหัสการให้สิทธิ์เป็นโทเค็นเพื่อการเข้าถึง คุณอาจพบข้อผิดพลาดต่อไปนี้แทนการตอบกลับที่คาดไว้ รหัสข้อผิดพลาด��ี่พบบ่อยและวิธีแก้ไขที่แนะนำมีดังนี้
invalid_grant
รหัสการให้สิทธิ์ที่ระบุไม่ถูกต้องหรืออยู่ในรูปแบบที่ไม่ถูกต้อง ขอรหัสใหม่โดย เริ่มกระบวนการ OAuth อีกครั้งเพื่อแจ้งให้ผู้ใช้ให้ความยินยอม อีกครั้ง
ขั้นตอนที่ 6: ตรวจสอบขอบเขตที่ผู้ใช้ให้สิทธิ์
เมื่อขอสิทธิ์ (ขอบเขต) หลายรายการ ผู้ใช้อาจไม่ให้สิทธิ์แอปของคุณเข้าถึง สิทธิ์ทั้งหมด แอปของคุณต้องยืนยันว่ามีการให้ขอบเขตใดบ้างจริง และจัดการสถานการณ์ที่ระบบปฏิเสธสิทธิ์บางอย่างอย่างเหมาะสม โดยปกติแล้วจะปิดใช้ฟีเจอร์ที่ต้องใช้ขอบเขตที่ถูกปฏิเสธเหล่านั้น
แต่ก็มีข้อยกเว้น แอป Google Workspace Enterprise ที่มี การมอบสิทธิ์ระดับโดเมน หรือแอปที่ทำเครื่องหมายเป็น เชื่อถือได้ จะข้ามหน้าจอขอความยินยอมให้สิทธิ์แบบละเอียด สำหรับแอปเหล่านี้ ผู้ใช้จะไม่เห็นหน้าจอขอความยินยอมให้สิทธิ์แบบละเอียด แต่แอปของคุณจะได้รับขอบเขตที่ขอทั้งหมด หรือไม่ได้รับเลย
ดูข้อมูลโดยละเอียดเพิ่มเติมได้ที่ วิธีจัดการสิทธิ์แบบละเอียด
PHP
หากต้องการตรวจสอบว่าผู้ใช้ให้สิทธิ์เข้าถึงขอบเขตใด ให้ใช้วิธี getGrantedScope() ดังนี้
// Space-separated string of granted scopes if it exists, otherwise null. $granted_scopes = $client->getOAuth2Service()->getGrantedScope(); // Determine which scopes user granted and build a dictionary $granted_scopes_dict = [ 'Drive' => str_contains($granted_scopes, Google\Service\Drive::DRIVE_METADATA_READONLY), 'Calendar' => str_contains($granted_scopes, Google\Service\Calendar::CALENDAR_READONLY) ];
Python
ออบเจ็กต์ credentials ที่แสดงผลมีพร็อพเพอร์ตี้ granted_scopes
ซึ่งเป็นรายการขอบเขตที่ผู้ใช้ให้สิทธิ์แก่แอปของคุณ
credentials = flow.credentials flask.session['credentials'] = { 'token': credentials.token, 'refresh_token': credentials.refresh_token, 'granted_scopes': credentials.granted_scopes}
ฟังก์ชันต่อไปนี้จะตรวจสอบว่าผู้ใช้ได้ให้สิทธิ์เข้าถึงขอบเขตใดบ้างแก่แอปของคุณ
def check_granted_scopes(credentials): features = {} if 'https://www.googleapis.com/auth/drive.metadata.readonly' in credentials['granted_scopes']: features['drive'] = True else: features['drive'] = False if 'https://www.googleapis.com/auth/calendar.readonly' in credentials['granted_scopes']: features['calendar'] = True else: features['calendar'] = False return features
Ruby
เมื่อขอขอบเขตหลายรายการพร้อมกัน ให้ตรวจสอบว่ามีการให้สิทธิ์ขอบเขตใดบ้างผ่านscopeพร็อพเพอร์ตี้credentialsของออบเจ็กต์
# User authorized the request. Now, check which scopes were granted. if credentials.scope.include?(Google::Apis::DriveV3::AUTH_DRIVE_METADATA_READONLY) # User authorized read-only Drive activity permission. # Calling the APIs, etc else # User didn't authorize read-only Drive activity permission. # Update UX and application accordingly end # Check if user authorized Calendar read permission. if credentials.scope.include?(Google::Apis::CalendarV3::AUTH_CALENDAR_READONLY) # User authorized Calendar read permission. # Calling the APIs, etc. else # User didn't authorize Calendar read permission. # Update UX and application accordingly end
Node.js
เมื่อขอขอบเขตหลายรายการพร้อมกัน ให้ตรวจสอบว่ามีการให้สิทธิ์ขอบเขตใดบ้างผ่านscopeพร็อพเพอร์ตี้tokensของออบเจ็กต์
// User authorized the request. Now, check which scopes were granted. if (tokens.scope.includes('https://www.googleapis.com/auth/drive.metadata.readonly')) { // User authorized read-only Drive activity permission. // Calling the APIs, etc. } else { // User didn't authorize read-only Drive activity permission. // Update UX and application accordingly } // Check if user authorized Calendar read permission. if (tokens.scope.includes('https://www.googleapis.com/auth/calendar.readonly')) { // User authorized Calendar read permission. // Calling the APIs, etc. } else { // User didn't authorize Calendar read permission. // Update UX and application accordingly }
HTTP/REST
หากต้องการตรวจสอบว่าผู้ใช้ได้ให้สิทธิ์แอปพลิเคชันของคุณเข้าถึงขอบเขตใดขอบเขตหนึ่งหรือไม่ ให้
ตรวจสอบฟิลด์ scope ในการตอบกลับโทเค็นการเข้าถึง ขอบเขตการเข้าถึงที่ได้รับจาก
access_token แสดงเป็นรายการสตริงที่คำนึงถึงตัวพิมพ์เล็กและตัวพิมพ์ใหญ่ซึ่งคั่นด้วยช่องว่าง
ตัวอย่างเช่น การตอบกลับโทเค็นเพื่อการเข้าถึงตัวอย่างต่อไปนี้บ่งชี้ว่าผู้ใช้ได้ให้สิทธิ์แอปพลิเคชันของคุณในการเข้าถึงสิทธิ์กิจกรรมในไดรฟ์แบบอ่านอย่างเดียวและกิจกรรมในปฏิทิน
{ "access_token": "1/fFAGRNJru1FTz70BzhT3Zg", "expires_in": 3920, "token_type": "Bearer", "scope": "https://www.googleapis.com/auth/drive.metadata.readonly https://www.googleapis.com/auth/calendar.readonly", "refresh_token": "1//xEoDL4iW3cxlI7yDbSRFYNG01kVKM2C-259HOF2aQbI" }
เรียกใช้ Google APIs
PHP
ใช้โทเค็นการเข้าถึงเพื่อเรียก Google APIs โดยทำตามขั้นตอนต่อไปนี้
- หากต้องการใช้โทเค็นเพื่อการเข้าถึงกับออบเจ็กต์
Google\Clientใหม่ เช่น หากคุณจัดเก็บโทเค็นเพื่อการเข้าถึงในเซสชันของผู้ใช้ ให้ใช้วิธีการsetAccessTokenดังนี้$client->setAccessToken($access_token); - สร้างออบเจ็กต์บริการสำหรับ API ที่ต้องการเรียก คุณสร้างออบเจ็กต์บริการได้โดยระบุออบเจ็กต์
Google\Clientที่ได้รับอนุญาตให้กับตัวสร้างสำหรับ API ที่ต้องการเรียก เช่น หากต้องการเรียกใช้ Drive API ให้ทำดังนี้$drive = new Google\Service\Drive($client); - ส่งคำขอไปยังบริการ API โดยใช้
อินเทอร์เฟซที่จัดหาให้โดยออบเจ็กต์บริการ
เช่น หากต้องการแสดงรายการไฟล์ใน Google ไดรฟ์ของผู้ใช้ที่ได้รับการตรวจสอบสิทธิ์ ให้ทำดังนี้
$files = $drive->files->listFiles(array());
Python
หลังจากได้รับโทเค็นเพื่อการเข้าถึงแล้ว แอปพลิเคชันจะใช้โทเค็นดังกล่าวเพื่อให้สิทธิ์คำขอ API ในนามของบัญชีผู้ใช้หรือบัญชีบริการที่ระบุได้ ใช้ข้อมูลเข้าสู่ระบบการให้สิทธิ์เฉพาะผู้ใช้ เพื่อสร้างออบเจ็กต์บริการสำหรับ API ที่ต้องการเรียกใช้ จากนั้นใช้ออบเจ็กต์ดังกล่าวเพื่อส่ง คำขอ API ที่ได้รับอนุญาต
- สร้างออบเจ็กต์บริการสำหรับ API ที่ต้องการเรียก คุณสร้างออบเจ็กต์บริการได้โดย
เรียกใช้เมธอด
buildของgoogleapiclient.discoveryไลบรารีbuildด้วย ชื่อและเวอร์ชันของ API และข้อมูลเข้าสู่ระบบของผู้ใช้ เช่น หากต้องการเรียกใช้ Drive API เวอร์ชัน 3 ให้ทำดังนี้from googleapiclient.discovery import build drive = build('drive', 'v2', credentials=credentials)
- ส่งคำขอไปยังบริการ API โดยใช้อินเทอร์เฟซที่จัดหาให้โดยออบเจ็กต์บริการ
เช่น หากต้องการแสดงรายการไฟล์ใน Google ไดรฟ์ของผู้ใช้ที่ได้รับการตรวจสอบสิทธิ์ ให้ทำดังนี้
files = drive.files().list().execute()
Ruby
หลังจากได้รับโทเค็นการเข้าถึงแล้ว แอปพลิเคชันจะใช้โทเค็นดังกล่าวเพื่อส่งคำขอ API ในนามของบัญชีผู้ใช้หรือบัญชีบริการท���่ระบุได้ ใช้ข้อมูลเข้าสู่ระบบการให้สิทธิ์เฉพาะผู้ใช้ เพื่อสร้างออบเจ็กต์บริการสำหรับ API ที่ต้องการเรียกใช้ จากนั้นใช้ออบเจ็กต์ดังกล่าวเพื่อส่ง คำขอ API ที่ได้รับอนุญาต
- สร้างออบเจ็กต์บริการสำหรับ API ที่ต้องการเรียก
เช่น หากต้องการเรียกใช้ Drive API เวอร์ชัน 3 ให้ทำดังนี้
drive = Google::Apis::DriveV3::DriveService.new
- ตั้งค่าข้อมูลเข้าสู่ระบบในบริการโดยทำดังนี้
drive.authorization = credentials
- ส่งคำขอไปยังบริการ API โดยใช้อินเทอร์เฟซ
ที่จัดหาให้โดยออบเจ็กต์บริการ
เช่น หากต้องการแสดงรายการไฟล์ใน Google ไดรฟ์ของผู้ใช้ที่ได้รับการตรวจสอบสิทธิ์ ให้ทำดังนี้
files = drive.list_files
หรือจะให้สิทธิ์ทีละวิธีก็ได้โดยระบุพารามิเตอร์
options ให้กับวิธี
files = drive.list_files(options: { authorization: credentials })
Node.js
หลังจากได้รับโทเค็นเพื่อการเข้าถึงและตั้งค่าให้กับออบเจ็กต์ OAuth2 แล้ว ให้ใช้ออบเจ็กต์
เพื่อเรียก Google APIs แอปพลิเคชันของคุณสามารถใช้โทเค็นดังกล่าวเพื่อให้สิทธิ์คำขอ API ในนามของ
บัญชีผู้ใช้หรือบัญชีบริการที่ระบุ สร้างออบเจ็กต์บริการสำหรับ API ที่ต้องการเรียก
ตัวอย่างเช่น โค้ดต่อไปนี้ใช้ Google Drive 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การค้นหาหรือค่าส่วนหัว HTTP Authorization Bearer หากเป็นไปได้
เราขอแนะนำให้ใช้ส่วนหัว HTTP เนื่องจากสตริงการค้นหามักจะปรากฏในบันทึกของเซิร์ฟเวอร์ ในกรณีส่วนใหญ่
คุณสามารถใช้ไลบรารีของไคลเอ็นต์เพื่อตั้งค่าการเรียกไปยัง Google API ได้ (เช่น เมื่อเรียกใช้ Drive Files API)
คุณลองใช้ Google APIs ทั้งหมดและดูขอบเขตของ API ได้ที่ 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 ไดรฟ์ของผู้ใช้หลังจากที่ ผู้ใช้ตรวจสอบสิทธิ์และให้ความยินยอมให้แอปพลิเคชันเข้าถึงข้อมูลเมตาของไดรฟ์ของผู้ใช้
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.15.0
- สร้างไฟล์
index.phpและoauth2callback.phpที่มีเนื้อหาต่อไปนี้ - เรียกใช้ตัวอย่างด้วยเว็บเซิร์ฟเวอร์ทดสอบในตัวของ 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_secret.json'); // User granted permission as an access token is in the session. if (isset($_SESSION['access_token']) && $_SESSION['access_token']) { $client->setAccessToken($_SESSION['access_token']); // Check if user granted Drive permission if ($_SESSION['granted_scopes_dict']['Drive']) { echo "Drive feature is enabled."; echo "</br>"; $drive = new Drive($client); $files = array(); $response = $drive->files->listFiles(array()); foreach ($response->files as $file) { echo "File: " . $file->name . " (" . $file->id . ")"; echo "</br>"; } } else { echo "Drive feature is NOT enabled."; echo "</br>"; } // Check if user granted Calendar permission if ($_SESSION['granted_scopes_dict']['Calendar']) { echo "Calendar feature is enabled."; echo "</br>"; } else { echo "Calendar feature is NOT enabled."; echo "</br>"; } } else { // Redirect users to outh2call.php which redirects users to Google OAuth 2.0 $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(); // Required, call the setAuthConfig function to load authorization credentials from // client_secret.json file. $client->setAuthConfigFile('client_secret.json'); $client->setRedirectUri('http://' . $_SERVER['HTTP_HOST']. $_SERVER['PHP_SELF']); // Required, to set the scope value, call the addScope function. $client->addScope([Google\Service\Drive::DRIVE_METADATA_READONLY, Google\Service\Calendar::CALENDAR_READONLY]); // Enable incremental authorization. Recommended as a best practice. $client->setIncludeGrantedScopes(true); // 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"); // Generate a URL for authorization as it doesn't contain code and error if (!isset($_GET['code']) && !isset($_GET['error'])) { // Generate and set state value $state = bin2hex(random_bytes(16)); $client->setState($state); $_SESSION['state'] = $state; // Generate a url that asks permissions. $auth_url = $client->createAuthUrl(); header('Location: ' . filter_var($auth_url, FILTER_SANITIZE_URL)); } // User authorized the request and authorization code is returned to exchange access and // refresh tokens. if (isset($_GET['code'])) { // Check the state value if (!isset($_GET['state']) || $_GET['state'] !== $_SESSION['state']) { die('State mismatch. Possible CSRF attack.'); } // Get access and refresh tokens (if access_type is offline) $token = $client->fetchAccessTokenWithAuthCode($_GET['code']); /** Save access and refresh token to the session variables. * ACTION ITEM: In a production app, you likely want to save the * refresh token in a secure persistent storage instead. */ $_SESSION['access_token'] = $token; $_SESSION['refresh_token'] = $client->getRefreshToken(); // Space-separated string of granted scopes if it exists, otherwise null. $granted_scopes = $client->getOAuth2Service()->getGrantedScope(); // Determine which scopes user granted and build a dictionary $granted_scopes_dict = [ 'Drive' => str_contains($granted_scopes, Google\Service\Drive::DRIVE_METADATA_READONLY), 'Calendar' => str_contains($granted_scopes, Google\Service\Calendar::CALENDAR_READONLY) ]; $_SESSION['granted_scopes_dict'] = $granted_scopes_dict; $redirect_uri = 'http://' . $_SERVER['HTTP_HOST'] . '/'; header('Location: ' . filter_var($redirect_uri, FILTER_SANITIZE_URL)); } // An error response e.g. error=access_denied if (isset($_GET['error'])) { echo "Error: ". $_GET['error']; } ?>
Python
ตัวอย่างนี้ใช้เฟรมเวิร์ก Flask โดยจะเรียกใช้เว็บแอปพลิเคชันที่ http://localhost:8080 ซึ่งช่วยให้คุณทดสอบขั้นตอน OAuth 2.0
ได้ หากไปที่ URL ดังกล่าว คุณควรเห็นลิงก์ 5 รายการ ดังนี้
- เรียกใช้ Drive API: ลิงก์นี้จะนำไปยังหน้าที่พยายามดำเนินการคำขอ API ตัวอย่าง หากผู้ใช้ให้สิทธิ์ หากจำเป็น ระบบจะเริ่มขั้นตอนการให้สิทธิ์ หากสำเร็จ หน้าเว็บจะแสดงการตอบกลับของ API
- หน้าจำลองเพื่อเรียก Calendar API: ลิงก์นี้จะนำไปยังหน้าจำลองที่พยายามดำเนินการ คำขอ Calendar API ตัวอย่างหากผู้ใช้ให้สิทธิ์ หากจำเป็น ระบบจะเริ่ม ขั้นตอนการให้สิทธิ์ หากสำเร็จ หน้าเว็บจะแสดงการตอบกลับของ API
- ทดสอบโฟลว์การให้สิทธิ์โดยตรง: ลิงก์นี้จะนำไปยังหน้าที่พยายามส่งผู้ใช้ผ่านโฟลว์การให้สิทธิ์ แอปขอสิทธิ์เพื่อ ส่งคำขอ API ที่ได้รับอนุญาตในนามของผู้ใช้
- เพิกถอนข้อมูลเข้าสู่ระบบปัจจุบัน: ลิงก์นี้จะนำไปยังหน้าที่ เพิกถอนสิทธิ์ที่ผู้ใช้ให้ไว้กับแอปพลิเคชันแล้ว
- ล้างข้อมูลเข้าสู่ระบบของเซสชัน Flask: ลิงก์นี้จะล้างข้อมูลเข้าสู่ระบบการให้สิทธิ์ที่จัดเก็บไว้ในเซสชัน Flask ซึ่งจะช่วยให้คุณเห็นสิ่งที่เกิดขึ้นหากผู้ใช้ที่เคยให้สิทธิ์แก่แอปของคุณแล้วพยายามดำเนินการคำขอ API ในเซสชันใหม่ นอกจากนี้ยังช่วยให้คุณดูการตอบกลับ API ที่แอปจะได้รับหากผู้ใช้เพิกถอนสิทธิ์ที่ให้ไว้กับแอป และแอปยังคงพยายามให้สิทธิ์คำขอด้วยโทเค็นการเข้าถึงที่ถูกเพิกถอน
# -*- coding: utf-8 -*- import os import flask import json 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" # The OAuth 2.0 access scope allows for access to the # authenticated user's account and requires requests to use an SSL connection. SCOPES = ['https://www.googleapis.com/auth/drive.metadata.readonly', 'https://www.googleapis.com/auth/calendar.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('/drive') def drive_api_request(): if 'credentials' not in flask.session: return flask.redirect('authorize') features = flask.session['features'] if features['drive']: # Load client secrets from the server-side file. with open(CLIENT_SECRETS_FILE, 'r') as f: client_config = json.load(f)['web'] # Load user-specific credentials from browser session storage. session_credentials = flask.session['credentials'] # Reconstruct the credentials object. credentials = google.oauth2.credentials.Credentials( refresh_token=session_credentials.get('refresh_token'), scopes=session_credentials.get('granted_scopes'), token=session_credentials.get('token'), client_id=client_config.get('client_id'), client_secret=client_config.get('client_secret'), token_uri=client_config.get('token_uri')) 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. flask.session['credentials'] = credentials_to_dict(credentials) return flask.jsonify(**files) else: # User didn't authorize read-only Drive activity permission. return '<p>Drive feature is not enabled.</p>' @app.route('/calendar') def calendar_api_request(): if 'credentials' not in flask.session: return flask.redirect('authorize') features = flask.session['features'] if features['calendar']: # User authorized Calendar read permission. # Calling the APIs, etc. return ('<p>User granted the Google Calendar read permission. '+ 'This sample code does not include code to call Calendar</p>') else: # User didn't authorize Calendar read permission. # Update UX and application accordingly return '<p>Calendar feature is not enabled.</p>' @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 credentials = credentials_to_dict(credentials) flask.session['credentials'] = credentials # Check which scopes user granted features = check_granted_scopes(credentials) flask.session['features'] = features return flask.redirect('/') @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.') # Load client secrets from the server-side file. with open(CLIENT_SECRETS_FILE, 'r') as f: client_config = json.load(f)['web'] # Load user-specific credentials from the session. session_credentials = flask.session['credentials'] # Reconstruct the credentials object. credentials = google.oauth2.credentials.Credentials( refresh_token=session_credentials.get('refresh_token'), scopes=session_credentials.get('granted_scopes'), token=session_credentials.get('token'), client_id=client_config.get('client_id'), client_secret=client_config.get('client_secret'), token_uri=client_config.get('token_uri')) 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: # Clear the user's session credentials after successful revocation if 'credentials' in flask.session: del flask.session['credentials'] del flask.session['features'] 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, 'granted_scopes': credentials.granted_scopes} def check_granted_scopes(credentials): features = {} if 'https://www.googleapis.com/auth/drive.metadata.readonly' in credentials['granted_scopes']: features['drive'] = True else: features['drive'] = False if 'https://www.googleapis.com/auth/calendar.readonly' in credentials['granted_scopes']: features['calendar'] = True else: features['calendar'] = False return features def print_index_table(): return ('<table>' + '<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="/drive">Call Drive API directly</a></td>' + '<td> Use stored credentials to call the API, you still might not be prompted to reauthorize ' + ' the application.</td></tr>' + '<tr><td><a href="/calendar">Call Calendar API directly</a></td>' + '<td> Use stored credentials to call the API, 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="/authorize">authorize</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' # This disables the requested scopes and granted scopes check. # If users only grant partial request, the warning would not be thrown. os.environ['OAUTHLIB_RELAX_TOKEN_SCOPE'] = '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 'googleauth' require 'googleauth/web_user_authorizer' require 'googleauth/stores/redis_token_store' require 'google/apis/drive_v3' require 'google/apis/calendar_v3' require 'sinatra' configure do enable :sessions # Required, call the from_file method to retrieve the client ID from a # client_secret.json file. set :client_id, Google::Auth::ClientId.from_file('/path/to/client_secret.json') # Required, scope value # Access scopes for two non-Sign-In scopes: Read-only Drive activity and Google Calendar. scope = ['Google::Apis::DriveV3::AUTH_DRIVE_METADATA_READONLY', 'Google::Apis::CalendarV3::AUTH_CALENDAR_READONLY'] # Required, Authorizers require a storage instance to manage long term persistence of # access and refresh tokens. set :token_store, Google::Auth::Stores::RedisTokenStore.new(redis: Redis.new) # 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. set :callback_uri, '/oauth2callback' # 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. set :authorizer, Google::Auth::WebUserAuthorizer.new(settings.client_id, settings.scope, settings.token_store, callback_uri: settings.callback_uri) end get '/' do # NOTE: Assumes the user is already authenticated to the app user_id = request.session['user_id'] # Fetch stored credentials for the user from the given request session. # nil if none present credentials = settings.authorizer.get_credentials(user_id, request) if credentials.nil? # Generate a url that asks the user to authorize requested scope(s). # Then, redirect user to the url. redirect settings.authorizer.get_authorization_url(request: request) end # User authorized the request. Now, check which scopes were granted. if credentials.scope.include?(Google::Apis::DriveV3::AUTH_DRIVE_METADATA_READONLY) # User authorized read-only Drive activity permission. # Example of using Google Drive API to list filenames in user's Drive. drive = Google::Apis::DriveV3::DriveService.new files = drive.list_files(options: { authorization: credentials }) "<pre>#{JSON.pretty_generate(files.to_h)}</pre>" else # User didn't authorize read-only Drive activity permission. # Update UX and application accordingly end # Check if user authorized Calendar read permission. if credentials.scope.include?(Google::Apis::CalendarV3::AUTH_CALENDAR_READONLY) # User authorized Calendar read permission. # Calling the APIs, etc. else # User didn't authorize Calendar read permission. # Update UX and application accordingly end end # Receive the callback from Google's OAuth 2.0 server. get '/oauth2callback' do # Handle the result of the oauth callback. Defers the exchange of the code by # temporarily stashing the results in the user's session. target_url = Google::Auth::WebUserAuthorizer.handle_auth_callback_deferred(request) redirect target_url end
Node.js
วิธีเรียกใช้ตัวอย่างนี้
-
ใน API Consoleให้เพิ่ม URL ของ
เครื่องในพื้นที่ลงในรายการ URL การเปลี่ยนเส้นทาง เช่น เพิ่ม
http://localhost - ตรวจสอบว่าคุณได้ติดตั้ง Node.js เวอร์ชัน LTS สำหรับการบำรุงรักษา, LTS ที่ใช้งานอยู่ หรือเวอร์ชันปัจจุบัน แล้ว
-
สร้างไดเรกทอรีใหม่และเปลี่ยนไปใช้ไดเรกทอรีนั้น เช่น
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 two non-Sign-In scopes: Read-only Drive activity and Google Calendar. const scopes = [ 'https://www.googleapis.com/auth/drive.metadata.readonly', 'https://www.googleapis.com/auth/calendar.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 and Google Calendar 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; // User authorized the request. Now, check which scopes were granted. if (tokens.scope.includes('https://www.googleapis.com/auth/drive.metadata.readonly')) { // User authorized read-only Drive activity permission. // 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.'); } }); } else { // User didn't authorize read-only Drive activity permission. // Update UX and application accordingly } // Check if user authorized Calendar read permission. if (tokens.scope.includes('https://www.googleapis.com/auth/calendar.readonly')) { // User authorized Calendar read permission. // Calling the APIs, etc. } else { // User didn't authorize Calendar read permission. // Update UX and application accordingly } } }); // 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(8080); } 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__) # To get these credentials (CLIENT_ID CLIENT_SECRET) and for your application, visit # https://console.cloud.google.com/apis/credentials. CLIENT_ID = '123456789.apps.googleusercontent.com' CLIENT_SECRET = 'abc123' # Read from a file or environmental variable in a real app # Access scopes for two non-Sign-In scopes: Read-only Drive activity and Google Calendar. SCOPE = 'https://www.googleapis.com/auth/drive.metadata.readonly https://www.googleapis.com/auth/calendar.readonly' # 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. 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: # User authorized the request. Now, check which scopes were granted. if 'https://www.googleapis.com/auth/drive.metadata.readonly' in credentials['scope']: # User authorized read-only Drive activity permission. # Example of using Google Drive API to list filenames in user's Drive. headers = {'Authorization': 'Bearer {}'.format(credentials['access_token'])} req_uri = 'https://www.googleapis.com/drive/v2/files' r = requests.get(req_uri, headers=headers).text else: # User didn't authorize read-only Drive activity permission. # Update UX and application accordingly r = 'User did not authorize Drive permission.' # Check if user authorized Calendar read permission. if 'https://www.googleapis.com/auth/calendar.readonly' in credentials['scope']: # User authorized Calendar read permission. # Calling the APIs, etc. r += 'User authorized Calendar permission.' else: # User didn't authorize Calendar read permission. # Update UX and application accordingly r += 'User did not authorize Calendar permission.' return r @app.route('/oauth2callback') def oauth2callback(): if 'code' not in flask.request.args: state = str(uuid.uuid4()) flask.session['state'] = state # Generate a url that asks permissions for the Drive activity # and Google Calendar scope. Then, redirect user to the url. 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'} # Exchange authorization code for access and refresh tokens (if access_type is offline) 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 การเปลี่ยนเส้นทางต้องเป็นไปตามกฎต่อไปนี้ ดูคำจำกัดความของโดเมน โฮสต์ เส้นทาง การค้นหา รูปแบบ และ userinfo ที่กล่าวถึงด้านล่างได้ที่ส่วนที่ 3 ของ RFC 3986
| กฎการตรวจสอบความถูกต้อง | |
|---|---|
| รูปแบบ |
URI การเปลี่ยนเส้นทางต้องใช้รูปแบบ HTTPS ไม่ใช่ HTTP ธรรมดา URI ของ localhost (รวมถึง URI ของที่อยู่ IP ของ localhost) ได้รับการยกเว้นจากกฎนี้ |
| โฮสต์ |
โฮสต์ต้องไม่ใช่ที่อยู่ IP ดิบ ที่อยู่ IP ของ localhost จะได้รับการยกเว้นจากกฎนี้ |
| โดเมน |
“googleusercontent.com”goo.gl) เว้นแต่
แอปจะเป็นเจ้าของโดเมน นอกจากนี้ หากแอปที่เป็นเจ้าของโดเมนตัวย่อเลือกที่จะ
เปลี่ยนเส้นทางไปยังโดเมนนั้น URI การเปลี่ยนเส้นทางดังกล่า��ต้องมี
“/google-callback/” ในเส้นทางหรือลงท้ายด้วย
“/google-callback” |
| Userinfo |
URI การเปลี่ยนเส้นทางต้องไม่มีคอมโพเนนต์ย่อย userinfo |
| เส้นทาง |
URI การเปลี่ยนเส้นทางต้องไม่มี Path Traversal (หรือที่เรียกว่าการย้อนกลับไดเรกทอรี)
ซึ่งแสดงด้วย |
| การค้นหา |
URI การเปลี่ยนเส้นทางต้องไม่มี การเปลี่ยนเส้นทางแบบเปิด |
| Fragment |
URI การเปลี่ยนเส้นทางต้องไม่มีคอมโพเนนต์ Fragment |
| อักขระ |
URI การเปลี่ยนเส้นทางต้องไม่มีอักขระบางตัว ซึ่งรวมถึง
|
การให้สิทธิ์แบบเพิ่ม
ในโปรโตคอล OAuth 2.0 แอปของคุณจะขอสิทธิ์เข้าถึงทรัพยากรซึ่งระบุโดยขอบเขต แนวทางปฏิบัติที่ดีที่สุดสำหรับประสบการณ์ของผู้ใช้คือการขอสิทธิ์ สำหรับทรัพยากรในเวลาที่คุณต้องการ เซิร์ฟเวอร์การให้สิทธิ์ของ Google รองรับการให้สิทธิ์แบบเพิ่มทีละรายการเพื่อเปิดใช้แนวทางดังกล่าว ฟีเจอร์นี้ช่วยให้คุณขอขอบเขตได้ตามต้องการ และหากผู้ใช้ให้สิทธิ์สำหรับขอบเขตใหม่ ระบบจะแสดงรหัสการให้สิทธิ์ที่อาจแลกเปลี่ยนเป็นโทเค็นที่มีขอบเขตทั้งหมดที่ผู้ใช้ให้สิทธิ์โปรเจ็กต์
ตัวอย่างเช่น แอปที่ให้ผู้ใช้ทดลองฟังแทร็กเพลงและสร้างมิกซ์อาจต้องการทรัพยากรเพียงเล็กน้อย เมื่อลงชื่อเข้าใช้ หรืออาจไม่ต้องการอะไรเลยนอกเหนือจากชื่อของผู้ที่ลงชื่อเข้าใช้ อย่างไรก็ตาม การบันทึกมิกซ์ที่ทำ��สร็จแล้วจะต้องมีสิทธิ์เข้าถึง Google ไดรฟ์ของบุคคลนั้น ผู้ใช้ส่วนใหญ่จะรู้สึก เป็นธรรมชาติหากระบบขอสิทธิ์เข้าถึง Google ไดรฟ์ในเวลาที่แอปต้องการสิทธิ์นั้นจริงๆ
ในกรณีนี้ เมื่อลงชื่อเข้าใช้ แอปอาจขอขอบเขต openid และ
profile เพื่อดำเนินการลงชื่อเข้าใช้ขั้นพื้นฐาน จากนั้นจึงขอขอบเขต
https://www.googleapis.com/auth/drive.file ในเวลาที่ส่งคำขอแรกเพื่อบันทึกมิกซ์
หากต้องการใช้การให้สิทธิ์แบบเพิ่มทีละรายการ ให้ทำตามขั้นตอนปกติในการขอโทเค็นการเข้าถึง แต่ตรวจสอบว่าคำขอการให้สิทธิ์มีขอบเขตที่ได้รับก่อนหน้านี้ วิธีนี้ช่วยให้แอปไม่ต้องจัดการโทเค็นเพื่อการเข้าถึงหลายรายการ
กฎต่อไปนี้จะมีผลกับโทเค็นเพื่อการเข้าถึงที่ได้รับจากการให้สิทธิ์แบบเพิ่ม
- คุณใช้โทเค็นเพื่อเข้าถึงทรัพยากรที่สอดคล้องกับขอบเขตใดก็ได้ที่รวมอยู่ในการให้สิทธิ์แบบใหม่ที่รวมกันได้
- เมื่อใช้โทเค็นการรีเฟรชสำหรับการให้สิทธิ์แบบรวมเพื่อรับโทเค็นเพื่อการเข้าถึง โทเค็นเพื่อการเข้าถึงจะแสดงการให้สิทธิ์แบบรวมและใช้กับค่า
scopeใดก็ได้ที่รวมอยู่ในคำตอบ - การให้สิทธิ์แบบรวมจะรวมขอบเขตทั้งหมดที่ผู้ใช้ให้แก่โปรเจ็กต์ API แม้ว่าจะมีการขอสิทธิ์จากไคลเอ็นต์ที่แตกต่างกันก็ตาม เช่น หากผู้ใช้ให้สิทธิ์เข้าถึงขอบเขตหนึ่งโดยใช้ไคลเอ็นต์เดสก์ท็อปของแอปพลิเคชัน แล้วให้สิทธิ์เข้าถึงอีกขอบเขตหนึ่งแก่แอปพลิเคชันเดียวกันผ่านไคลเอ็นต์บนอุปกรณ์เคลื่อนที่ การให้สิทธิ์รวมจะรวมทั้ง 2 ขอบเขต
- หากเพิกถอนโทเค็นที่แสดงถึงการให้สิทธิ์แบบรวม ระบบจะเพิกถอนสิทธิ์เข้าถึงขอบเขตทั้งหมดของการให้สิทธิ์นั้นในนามของผู้ใช้ที่เชื่อมโยงพร้อมกัน
ตัวอย่างโค้ดเฉพาะภาษาในขั้นตอนที่ 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.metadata.readonly%20https%3A//www.googleapis.com/auth/calendar.readonly& redirect_uri=https%3A//oauth2.example.com/code& prompt=consent& include_granted_scopes=true
การรีเฟรชโทเค็นเพื่อการเข้าถึง (การเข้าถึงแบบออฟไลน์)
โทเค็นเพื่อการเข้าถึงจะหมดอายุเป็นระยะๆ และกลายเป็นข้อมูลเข้าสู่ระบบที่ไม่ถูกต้องสำหรับคำขอ API ที่เกี่ยวข้อง คุณ สามารถรีเฟรชโทเค็นเพื่อการเข้าถึงได้โดยไม่ต้องแจ้งให้ผู้ใช้ขอสิทธิ์ (รวมถึงเมื่อผู้ใช้ไม่ได้ อยู่) หากคุณขอสิทธิ์เข้าถึงแบบออฟไลน์ไปยังขอบเขตที่เชื่อมโย��กับโทเค็น
- หากใช้ไลบรารีของไคลเอ็นต์ Google API ออบเจ็กต์ไคลเอ็นต์จะรีเฟรช โทเค็นการเข้าถึงตามที่จำเป็น ตราบใดที่คุณกำหนดค่าออบเจ็กต์นั้นสำหรับการเข้าถึงแบบออฟไลน์
- หากไม่ได้ใช้ไลบรารีของไคลเอ็นต์ คุณต้องตั้งค่าพารามิเตอร์การค้นหา
access_typeHTTP เป็น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 APIs ในนามของผู้ใช้ได้เมื่อผู้ใช้ออฟไลน์ ออบเจ็กต์ไคลเอ็นต์ จะรีเฟรชโทเค็นการเข้าถึงตามที่จำเป็น
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 APIs ในนามของผู้ใช้ได้เมื่อผู้ใช้ออฟไลน์ ออบเจ็กต์ไคลเอ็นต์ จะรีเฟรชโทเค็นการเข้าถึงตามที่จำเป็น
โทเค็นเพื่อการเข้าถึงจะหมดอายุ ไลบรารีนี้จะใช้โทเค็นการรีเฟรชโดยอัตโนมัติเพื่อรับโทเค็นเพื่อเข้าถึงใหม่ หากโทเค็นกำลังจะหมดอายุ วิธีง่ายๆ ในการตรวจสอบว่าคุณจัดเก็บโทเค็นล่าสุดอยู่เสมอ คือการใช้เหตุการณ์โทเค็น ดังนี้
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
หากต้องการรีเฟรชโทเค็นการเข้าถึง แอปพลิเคชันของคุณจะส่งคำขอ HTTPS POST
ไปยังเซิร์ฟเวอร์การให้สิทธิ์ของ 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& 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 https://www.googleapis.com/auth/calendar.readonly", "token_type": "Bearer" }
โปรดทราบว่ามีการจำกัดจำนวนโทเค็นการรีเฟรชที่จะออกให้ โดยมีการจำกัด 1 รายการต่อ ชุดค่าผสมไคลเอ็นต์/ผู้ใช้ และอีก 1 รายการต่อผู้ใช้ในไคลเอ็นต์ทั้งหมด คุณควรบันทึกโทเค็นการรีเฟรช ไว้ในที่เก็บข้อมูลระยะยาวและใช้ต่อไปตราบใดที่โทเค็นยังคงใช้งานได้ หากแอปพลิเคชัน ขอโทเค็นการรีเฟรชมากเกินไป แอปพลิเคชันอาจถึงขีดจำกัดเหล่านี้ ในกรณีนี้ โทเค็นการรีเฟรชที่เก่ากว่า จะหยุดทำงาน
การเพิกถอนโทเค็น
ในบางกรณี ผู้ใช้อาจต้องการเพิกถอนสิทธิ์เข้าถึงที่ให้แก่แอปพลิเคชัน ผู้ใช้สามารถเพิกถอนสิทธิ์เข้าถึง ได้โดยไปที่ การตั้งค่าบัญชี ดูข้อมูลเพิ่มเติมได้ที่ส่วนนำสิทธิ์เข้าถึงเว็บไซต์หรือแอปออกในเอกสารสนับสนุนเกี่ยวกับเว็บไซต์และแอปของบุคคลที่สามซึ่งมีสิทธิ์เข้าถึงบัญชีของคุณ
นอกจากนี้ แอปพลิเคชันยังเพิกถอนสิทธิ์เข้าถึงที่ได้รับโดยใช้โปรแกรมได้ด้วย การเพิกถอนแบบเป็นโปรแกรมมีความสำคัญในกรณีที่ผู้ใช้ยกเลิกการสมัครรับข้อมูล นำแอปพลิเคชันออก หรือทรัพยากร 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
หากต้องการเพิกถอนโทเค็นโดยอัตโนมัติ ให้ส่งคำขอ HTTPS POST ไปยังปลายทาง /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 ในระหว่างขั้นตอนความยินยอม เพื่อให้ผู้ใช้มีตัวเลือกในการให้สิทธิ์เข้าถึงในช่วงระยะเวลาที่จำกัด ตัวอย่างเช่น Data Portability API ซึ่งช่วยให้โอนข้อมูลได้แบบครั้งเดียว
เมื่อผู้ใช้ให้สิทธิ์เข้าถึงแอปพลิเคชันของคุณตามเวลา โทเค็นการรีเฟรชจะหมดอายุหลังจาก
ระยะเวลาที่ระบุ โปรดทราบว่าโทเค็นการรีเฟรชอาจใช้ไม่ได้ก่อนหน้านี้ในบางกรณี
โปรดดูรายละเอียดในกรณีเหล่านี้
ฟิลด์ refresh_token_expires_in ที่แสดงในการตอบกลับรหัสการให้สิทธิ์
แลกเปลี่ยนจะแสดงเวลาที่เหลือจนกว่าโทเค็นการรีเฟรชจะหมดอายุในกรณีดังกล่าว
การติดตั้งใช้งานการป้องกันแบบครอบคลุมหลายบริการ
อีกขั้นตอนหนึ่งที่คุณควรทำเพื่อปกป้องบัญชีของผู้ใช้คือการใช้การปกป้องข้ามบัญชีโดยใช้บริการการปกป้องข้ามบัญชีของ 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
ดูข้อมูลเพิ่มเติมเกี่ยวกับวิธีใช้การป้องกันแบบครอบคลุมหลายบริการและรายการเหตุการณ์ทั้งหมดที่พร้อมใช้งานได้ที่หน้า ปกป้องบัญชีผู้ใช้ด้วยการป้องกันแบบครอบคลุมหลายบริการ