เอกสารนี้อธิบายวิธีที่แอปพลิเคชันเว็บเซิร์ฟเวอร์ใช้ไลบรารีของไคลเอ็นต์ Google API หรือปลายทาง OAuth 2.0 ของ Google เพื่อใช้การให้สิทธิ์ OAuth 2.0 เพื่อเข้าถึง YouTube Analytics API หรือ YouTube Reporting API
OAuth 2.0 อนุญาตให้ผู้ใช้แชร์ข้อมูลบางอย่างกับแอปพลิเคชันโดยที่ยังเก็บชื่อผู้ใช้ รหัสผ่าน และข้อมูลอื่นๆ ไว้เป็นส่วนตัว เช่น แอปพลิเคชันสามารถใช้ OAuth 2.0 เพื่อขอสิทธิ์ดึงข้อมูล YouTube Analytics ของช่อง
ขั้นตอน OAuth 2.0 นี้มีไว้สำหรับการให้สิทธิ์ผู้ใช้โดยเฉพาะ ออกแบบมาสำหรับแอปพลิเคชันที่สามารถจัดเก็บข้อมูลที่เป็นความลับและรักษาสถานะ แอปพลิเคชันเซิร์ฟเวอร์เว็บที่ได้รับอนุญาตอย่างเหมาะสมจะเข้าถึง API ได้ขณะที่ผู้ใช้โต้ตอบกับแอปพลิเคชันหรือหลังจากที่ผู้ใช้ออกจากแอปพลิเคชันแล้ว
แอปพลิเคชันเว็บเซิร์ฟเวอร์มักใช้ บัญชีบริการเพื่อให้สิทธิ์คำขอ API ด้วย โดยเฉพาะเมื่อเรียกใช้ Cloud API เพื่อเข้าถึงข้อมูลตามโปรเจ็กต์แทนข้อมูลเฉพาะผู้ใช้ แอปพลิเคชันเว็บเซิร์ฟเวอร์สามารถใช้บัญชีบริการร่วมกับการให้สิทธิ์ของผู้ใช้
- YouTube Analytics API ไม่รองรับขั้นตอนของบัญชีบริการ
- YouTube Reporting API รองรับเฉพาะขั้นตอนการขอสิทธิ์ผ่านบัญชีบริการสำหรับเจ้าของเนื้อหา YouTube ที่เป็นเจ้าของและจัดการช่อง YouTube หลายช่อง
กล่าวโดยละเอียดคือ เจ้าของเนื้อหาสามารถใช้บัญชีบริการในคำขอ API ที่กําหนดค่าสําหรับพารามิเตอร์คําขอ
onBehalfOfContentOwner
ไลบรารีของไคลเอ็นต์
ตัวอย่างเฉพาะภาษาในหน้านี้ใช้ไลบรารีของไคลเอ็นต์ Google API เพื่อใช้การให้สิทธิ์ OAuth 2.0 หากต้องการเรียกใช้ตัวอย่างโค้ด คุณต้องติดตั้งไลบรารีไคลเอ็นต์สำหรับภาษาของคุณก่อน
เมื่อคุณใช้ไลบรารีของไคลเอ็นต์ Google API เพื่อจัดการขั้นตอน OAuth 2.0 ของแอปพลิเคชัน ไลบรารีของไคลเอ็นต์จะดําเนินการหลายอย่างที่แอปพลิเคชันจะต้องจัดการด้วยตนเอง เช่น กำหนดว่าแอปพลิเคชันจะใช้หรือรีเฟรชโทเค็นการเข้าถึงที่จัดเก็บไว้ได้เมื่อใด รวมถึงกำหนดว่าแอปพลิเคชันต้องขอความยินยอมอีกครั้งเมื่อใด นอกจากนี้ ไลบรารีไคลเอ็นต์ยังสร้าง URL การเปลี่ยนเส้นทางที่ถูกต้องและช่วยติดตั้งใช้งานตัวแฮนเดิลการเปลี่ยนเส้นทางที่แลกเปลี่ยนรหัสการให้สิทธิ์กับโทเค็นการเข้าถึง
ไลบรารีของไคลเอ็นต์ Google API สําหรับแอปพลิเคชันฝั่งเซิร์ฟเวอร์พร้อมให้บริการในภาษาต่อไปนี้
ข้อกำหนดเบื้องต้น
เปิดใช้ API สําหรับโปรเจ็กต์
แอปพลิเคชันใดก็ตามที่เรียกใช้ Google API จะต้องเปิดใช้ API เหล่านั้นใน API Console
วิธีเปิดใช้ API สําหรับโปรเจ็กต์
- Open the API Library ใน Google API Console
- If prompted, select a project, or create a new one.
- ใช้หน้าไลบรารีเพื่อค้นหาและเปิดใช้ YouTube Analytics API และ YouTube Reporting API แอปพลิเคชันจำนวนมากที่ดึงข้อมูล YouTube Analytics ยังทำงานร่วมกับ YouTube Data API ด้วย ค้นหา API อื่นๆ ที่แอปพลิเคชันของคุณจะใช้และเปิดใช้ API เหล่านั้นด้วย
สร้างข้อมูลเข้าสู่ระบบการให้สิทธิ์
แอปพลิเคชันที่ใช้ OAuth 2.0 เพื่อเข้าถึง Google APIs ต้องมีข้อมูลเข้าสู่ระบบการให้สิทธิ์ที่ระบุแอปพลิเคชันนั้นแก่เซิร์ฟเวอร์ OAuth 2.0 ของ Google ขั้นตอนต่อไปนี้จะอธิบายวิธีสร้างข้อมูลเข้าสู่ระบบสำหรับโปรเจ็กต์ จากนั้นแอปพลิเคชันจะใช้ข้อมูลเข้าสู่ระบบดังกล่าวเพื่อเข้าถึง API ที่คุณเปิดใช้สำหรับโปรเจ็กต์นั้นได้
- Go to the Credentials page.
- คลิกสร้างข้อมูลเข้าสู่ระบบ > รหัสไคลเอ็นต์ OAuth
- เลือกประเภทแอปพลิเคชันเว็บแอปพลิเคชัน
- กรอกแบบฟอร์มแล้วคลิกสร้าง แอปพลิเคชันที่ใช้ภาษาและเฟรมเวิร์กต่างๆ เช่น 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 ของข้อมูลวิเคราะห์ YouTube ใช้ขอบเขตต่อไปนี้
ขอบเขต | |
---|---|
https://www.googleapis.com/auth/youtube | จัดการบัญชี YouTube ของคุณ |
https://www.googleapis.com/auth/youtube.readonly | ดูบัญชี YouTube ของคุณ |
https://www.googleapis.com/auth/youtubepartner | ดูและจัดการพื้นที่ของคุณและเนื้อหาที่เกี่ยวข้องใน YouTube |
https://www.googleapis.com/auth/yt-analytics-monetary.readonly | ดูรายงาน YouTube Analytics ด้านการเงินและไม่ใช่ด้านการเงินสำหรับเนื้อหา YouTube ของคุณ |
https://www.googleapis.com/auth/yt-analytics.readonly | ดูรายงาน YouTube Analytics สำหรับเนื้อหา YouTube ของคุณ |
YouTube Reporting API ใช้ขอบเขตต่อไปนี้
ขอบเขต | |
---|---|
https://www.googleapis.com/auth/yt-analytics-monetary.readonly | ดูรายงาน YouTube Analytics ด้านการเงินและไม่ใช่ด้านการเงินสำหรับเนื้อหา YouTube ของคุณ |
https://www.googleapis.com/auth/yt-analytics.readonly | ดูรายงาน YouTube Analytics สำหรับเนื้อหา YouTube ของคุณ |
เอกสารขอบเขต OAuth 2.0 API มีรายการขอบเขตทั้งหมดที่คุณอาจใช้เพื่อเข้าถึง 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
- เฟรมเวิร์กเว็บแอปพลิเคชัน Flask Python
pip install --upgrade flask
- ไลบรารี HTTP ของ
requests
pip 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
-
เฟรมเวิร์กเว็บแอปพลิเคชัน Ruby ของ Sinatra
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 คุณจะต้องสร้างและกำหนดค่าออบเจ็กต์ที่กำหนดพารามิเตอร์เหล่านี้
- หากเรียกใช้ปลายทาง OAuth 2.0 ของ Google โดยตรง คุณจะต้องสร้าง URL และตั้งค่าพารามิเตอร์ใน URL นั้น
แท็บด้านล่างจะกำหนดพารามิเตอร์การให้สิทธิ์ที่รองรับสำหรับแอปพลิเคชันเว็บเซิร์ฟเวอร์ ตัวอย่างเฉพาะภาษายังแสดงวิธีใช้ไลบรารีไคลเอ็นต์หรือไลบรารีการให้สิทธิ์เพื่อกำหนดค่าออบเจ็กต์ที่ตั้งค่าพารามิเตอร์เหล่านั้นด้วย
PHP
ข้อมูลโค้ดต่อไปนี้สร้างออบเจ็กต์ Google\Client()
ซึ่งกําหนดพารามิเตอร์ในคําขอการให้สิทธิ์
ออบเจ็กต์ดังกล่าวใช้ข้อมูลจากไฟล์ client_secret.json เพื่อระบุแอปพลิเคชันของคุณ (ดูข้อมูลเพิ่มเติมเกี่ยวกับไฟล์ดังกล่าวได้ที่การสร้างข้อมูลเข้าสู่ระบบสำหรับการให้สิทธิ์) ออบเจ็กต์จะระบุขอบเขตที่แอปพลิเคชันขอสิทธิ์เข้าถึงและ URL ไปยังปลายทางการตรวจสอบสิทธิ์ของแอปพลิเคชันด้วย ซึ่งจะจัดการการตอบกลับจากเซิร์ฟเวอร์ OAuth 2.0 ของ Google สุดท้าย โค้ดจะตั้งค่าพารามิเตอร์ access_type
และ include_granted_scopes
(ไม่บังคับ)
ตัวอย่างเช่น หากต้องการขอสิทธิ์เข้าถึงแบบออฟไลน์เพื่อเรียกดูรายงาน YouTube Analytics ของผู้ใช้ ให้ทำดังนี้
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_YouTubeAnalytics::YT_ANALYTICS_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
(ไม่บังคับ)
ตัวอย่างเช่น หากต้องการขอสิทธิ์เข้าถึงแบบออฟไลน์เพื่อเรียกดูรายงาน YouTube Analytics ของผู้ใช้ ให้ทำดังนี้
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/yt-analytics.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
ตัวอย่างเช่น หากต้องการขอสิทธิ์เข้าถึงแบบออฟไลน์เพื่อเรียกดูรายงาน YouTube Analytics ของผู้ใช้ ให้ทำดังนี้
require 'googleauth' require 'googleauth/web_user_authorizer' require 'googleauth/stores/redis_token_store' require 'google/apis/youtube_analytics_v1' 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/yt-analytics.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 |
จำเป็น
รหัสไคลเอ็นต์สําหรับแอปพลิเคชัน คุณดูค่านี้ได้ในส่วน API Console Credentials page |
||||||||||||||||||
redirect_uri |
จำเป็น
กำหนดตำแหน่งที่เซิร์ฟเวอร์ API จะเปลี่ยนเส้นทางผู้ใช้หลังจากที่ผู้ใช้ทำตามขั้นตอนการให้สิทธิ์จนเสร็จสมบูรณ์ ค่าต้องตรงกับ URI การเปลี่ยนเส้นทางที่ได้รับอนุญาตรายการใดรายการหนึ่งสำหรับไคลเอ็นต์ OAuth 2.0 ที่คุณกำหนดค่าไว้ใน API Console
Credentials pageของลูกค้า หากค่านี้ไม่ตรงกับ URI การเปลี่ยนเส้นทางที่ได้รับอนุญาตสําหรับ โปรดทราบว่ารูปแบบ |
||||||||||||||||||
response_type |
จำเป็น
กำหนดว่าปลายทาง OAuth 2.0 ของ Google จะแสดงผลรหัสการให้สิทธิ์หรือไม่ ตั้งค่าพารามิเตอร์เป็น |
||||||||||||||||||
scope |
จำเป็น
รายการขอบเขตที่คั่นด้วยเว้นวรรคซึ่งระบุทรัพยากรที่แอปพลิเคชันของคุณเข้าถึงในนามของผู้ใช้ได้ ค่าเหล่านี้จะระบุหน้าจอความยินยอมที่ Google แสดงต่อผู้ใช้ ขอบเขตช่วยให้แอปพลิเคชันขอสิทธิ์เข้าถึงเฉพาะทรัพยากรที่จําเป็นเท่านั้น และช่วยให้ผู้ใช้ควบคุมระดับการเข้าถึงที่มอบให้กับแอปพลิเคชันได้ด้วย ดังนั้น จำนวนขอบเขตที่ขอจึงมีความสัมพันธ์แบบผกผันกับแนวโน้มที่จะได้รับความยินยอมจากผู้ใช้ API ของข้อมูลวิเคราะห์ YouTube ใช้ขอบเขตต่อไปนี้
YouTube Reporting API ใช้ขอบเขตต่อไปนี้
เอกสารขอบเขต OAuth 2.0 API มีรายการขอบเขตทั้งหมดที่คุณอาจใช้เพื่อเข้าถึง Google API เราขอแนะนำให้แอปพลิเคชันขอสิทธิ์เข้าถึงขอบเขตการให้สิทธิ์ในบริบทเมื่อใดก็ตามที่เป็นไปได้ การขอสิทธิ์เข้าถึงข้อมูลผู้ใช้ตามบริบทผ่านการตรวจสอบสิทธิ์ทีละส่วนจะช่วยให้ผู้ใช้เข้าใจได้ง่ายขึ้นว่าเหตุใดแอปพลิเคชันจึงต้องการสิทธิ์เข้าถึงที่ขอ |
||||||||||||||||||
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
ที่สร้างขึ้นจากขั้นตอนที่ 1generateAuthUrl
เพื่อขอสิทธิ์เข้าถึงจากเซิร์ฟเวอร์ OAuth 2.0 ของ Google -
เปลี่ยนเส้นทางผู้ใช้ไปยัง
authorizationUrl
res.redirect(authorizationUrl);
HTTP/REST
ตัวอย่างการเปลี่ยนเส้นทางไปยังเซิร์ฟเวอร์การให้สิทธิ์ของ Google
URL ตัวอย่างด้านล่างขอสิทธิ์เข้าถึงแบบออฟไลน์ (access_type=offline
) ในสโคปที่อนุญาตให้เข้าถึงเพื่อดึงข้อมูลรายงาน YouTube Analytics ของผู้ใช้ โดยจะใช้การให้สิทธิ์แบบเพิ่มเพื่อให้มั่นใจว่าโทเค็นการเข้าถึงใหม่จะครอบคลุมขอบเขตทั้งหมดที่ผู้ใช้เคยให้สิทธิ์เข้าถึงแอปพลิเคชันไว้ก่อนหน้านี้ นอกจากนี้ URL ยังตั้งค่าสําหรับพารามิเตอร์ redirect_uri
, response_type
และ client_id
ที่จําเป็น รวมถึงพารามิเตอร์ state
ด้วย URL มีการเว้นบรรทัดและการเว้นวรรคเพื่อให้อ่านได้ง่าย
https://accounts.google.com/o/oauth2/v2/auth?
scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fyt-analytics.readonly&
access_type=offline&
include_granted_scopes=true&
state=state_parameter_passthrough_value&
redirect_uri=http%3A%2F%2Flocalhost%2Foauth2callback&
response_type=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 ไม่อนุญาต
Android
นักพัฒนาแอป Android อาจเห็นข้อความแสดงข้อผิดพลาดนี้เมื่อเปิดคําขอการให้สิทธิ์ใน android.webkit.WebView
นักพัฒนาแอปควรใช้ไลบรารี Android เช่น Google Sign-In สำหรับ Android หรือ AppAuth สำหรับ Android ของ OpenID Foundation แทน
นักพัฒนาเว็บอาจพบข้อผิดพลาดนี้เมื่อแอป Android เปิดลิงก์เว็บทั่วไปใน User Agent ที่ฝังอยู่ และผู้ใช้ไปยังปลายทางการให้สิทธิ์ OAuth 2.0 ของ Google จากเว็บไซต์ของคุณ นักพัฒนาแอปควรอนุญาตให้ลิงก์ทั่วไปเปิดในตัวแฮนเดิลลิงก์เริ่มต้นของระบบปฏิบัติการ ซึ่งรวมถึงตัวแฮนเดิล App Link ของ Android หรือแอปเบราว์เซอร์เริ่มต้น นอกจากนี้ ระบบยังรองรับตัวเลือกไลบรารี Android Custom Tabs ด้วย
iOS
นักพัฒนาแอป 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 รวมถึงรหัสไคลเอ็นต์และรหัสลับที่ใช้สำหรับคำขอนี้
invalid_grant
เมื่อรีเฟรชโทเค็นการเข้าถึงหรือใช้การให้สิทธิ์เพิ่มเติม โทเค็นอาจหมดอายุหรือไม่ถูกต้อง ตรวจสอบสิทธิ์ผู้ใช้อีกครั้งและขอความยินยอมจากผู้ใช้เพื่อรับโทเค็นใหม่ หากยังเห็นข้อผิดพลาดนี้อยู่ ให้ตรวจสอบว่าได้กําหนดค่าแอปพลิเคชันอย่างถูกต้องและใช้โทเค็นและพารามิเตอร์ที่ถูกต้องในคําขอ มิฉะนั้น บัญชีผู้ใช้อาจถูกลบหรือปิดใช้
redirect_uri_mismatch
redirect_uri
ที่ส่งในคําขอการให้สิทธิ์ไม่ตรงกับ URI การเปลี่ยนเส้นทางที่ได้รับอนุญาตสําหรับรหัสไคลเอ็นต์ OAuth ตรวจสอบ URI การเปลี่ยนเส้นทางที่ได้รับอนุญาตใน Google API Console Credentials page
พารามิเตอร์ redirect_uri
อาจหมายถึงขั้นตอนการส่งผ่านข้อมูลนอกแบนด์ (OOB) ของ OAuth ซึ่งเลิกใช้งานแล้วและไม่รองรับอีกต่อไป โปรดดูคู่มือการย้ายข้อมูลเพื่ออัปเดตการผสานรวม
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 ไดรฟ์และสิทธิ์เข้าถึงระดับอ่านอย่างเดียวเพื่อดูกิจกรรมใน Google ปฏิทิน
https://accounts.google.com/o/oauth2/v2/auth? scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fyt-analytics.readonly& access_type=offline& include_granted_scopes=true& state=state_parameter_passthrough_value& redirect_uri=http%3A%2F%2Flocalhost%2Foauth2callback& response_type=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/yt-analytics.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, '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 |
รหัสไคลเอ็นต์ที่ได้รับจาก 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/yt-analytics.readonly https://www.googleapis.com/auth/calendar.readonly", "refresh_token": "1//xEoDL4iW3cxlI7yDbSRFYNG01kVKM2C-259HOF2aQbI" }
ข้อผิดพลาด
เมื่อแลกเปลี่ยนรหัสการให้สิทธิ์เป็นโทเค็นการเข้าถึง คุณอาจพบข้อผิดพลาดต่อไปนี้แทนการตอบกลับที่คาดไว้ รหัสข้อผิดพลาดที่พบบ่อยและวิธีแก้ไขที่แนะนำมีดังนี้
invalid_grant
รหัสการตรวจสอบสิทธิ์ที่ระบุไม่ถูกต้องหรืออยู่ในรูปแบบที่ไม่ถูกต้อง ขอรหัสใหม่โดยเริ่มกระบวนการ OAuth อีกครั้งเพื่อแจ้งให้ผู้ใช้ให้ความยินยอมอีกครั้ง
ขั้นตอนที่ 6: ตรวจสอบขอบเขตที่ผู้ใช้ให้สิทธิ์
เมื่อขอขอบเขตหลายรายการพร้อมกัน ผู้ใช้อาจไม่ให้สิทธิ์ขอบเขตทั้งหมดที่แอปขอ แอปของคุณควรตรวจสอบขอบเขตที่ผู้ใช้ให้สิทธิ์ไว้เสมอ และจัดการกับการปฏิเสธขอบเขตด้วยการปิดใช้ฟีเจอร์ที่เกี่ยวข้อง ดูข้อมูลเพิ่มเติมที่วิธีจัดการสิทธิ์แบบละเอียด
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, 'token_uri': credentials.token_uri, 'client_id': credentials.client_id, 'client_secret': credentials.client_secret, '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/yt-analytics.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
ในการตอบกลับโทเค็นการเข้าถึง ขอบเขตการเข้าถึงที่ granted โดย access_token ที่แสดงเป็นรายการสตริงที่คำนึงถึงตัวพิมพ์เล็กและตัวพิมพ์ใหญ่และเว้นวรรคคั่น
ตัวอย่างเช่น ตัวอย่างการตอบกลับโทเค็นการเข้าถึงต่อไปนี้บ่งชี้ว่าผู้ใช้ได้ให้สิทธิ์เข้าถึงกิจกรรมในไดรฟ์และกิจกรรมในปฏิทินแบบอ่านอย่างเดียวแก่แอปพลิเคชันของคุณ
{ "access_token": "1/fFAGRNJru1FTz70BzhT3Zg", "expires_in": 3920, "token_type": "Bearer", "scope": "https://www.googleapis.com/auth/yt-analytics.readonly https://www.googleapis.com/auth/calendar.readonly", "refresh_token": "1//xEoDL4iW3cxlI7yDbSRFYNG01kVKM2C-259HOF2aQbI" }
เรียกใช้ Google API
PHP
ใช้โทเค็นการเข้าถึงเพื่อเรียกใช้ Google API โดยทําตามขั้นตอนต่อไปนี้
- หากต้องการใช้โทเค็นการเข้าถึงกับออบเจ็กต์
Google\Client
ใหม่ เช่น หากคุณจัดเก็บโทเค็นการเข้าถึงไว้ในเซสชันผู้ใช้ ให้ใช้เมธอดsetAccessToken
ดังนี้$client->setAccessToken($access_token);
- สร้างออบเจ็กต์บริการสําหรับ API ที่ต้องการเรียกใช้ คุณสร้างออบเจ็กต์บริการได้โดยระบุออบเจ็กต์
Google\Client
ที่มีสิทธิ์ให้กับคอนสตรคเตอร์สําหรับ API ที่ต้องการเรียกใช้ ตัวอย่างเช่น หากต้องการเรียกใช้ YouTube Analytics API ให้ทำดังนี้$youtube = new Google_Service_YouTubeAnalytics($client);
- ส่งคําขอไปยังบริการ API โดยใช้
อินเทอร์เฟซที่ออบเจ็กต์บริการระบุ
ตัวอย่างเช่น หากต้องการเรียกข้อมูลรายงาน YouTube Analytics สำหรับช่องของผู้ใช้ที่ตรวจสอบสิทธิ์แล้ว ให้ทำดังนี้
$report = $youtube->reports->query('channel==MINE', '2016-05-01', '2016-06-30', 'views');
Python
หลังจากได้รับโทเค็นการเข้าถึงแล้ว แอปพลิเคชันจะใช้โทเค็นดังกล่าวเพื่อให้สิทธิ์คําขอ API ในนามของบัญชีผู้ใช้หรือบัญชีบริการที่ระบุได้ ใช้ข้อมูลเข้าสู่ระบบการให้สิทธิ์เฉพาะผู้ใช้เพื่อสร้างออบเจ็กต์บริการสําหรับ API ที่ต้องการเรียกใช้ จากนั้นใช้ออบเจ็กต์ดังกล่าวเพื่อส่งคําขอ API ที่ได้รับอนุญาต
- สร้างออบเจ็กต์บริการสําหรับ API ที่ต้องการเรียกใช้ คุณสร้างออบเจ็กต์บริการได้โดยเรียกใช้เมธอด
build
ของgoogleapiclient.discovery
ไลบรารีพร้อมชื่อและเวอร์ชันของ API และข้อมูลเข้าสู่ระบบของผู้ใช้ ดังนี้ ตัวอย่างเช่น หากต้องการเรียกใช้ YouTube Analytics API เวอร์ชัน 1 ให้ทำดังนี้from googleapiclient.discovery import build youtube = build('youtubeAnalytics', 'v1', credentials=credentials)
- ส่งคําขอไปยังบริการ API โดยใช้อินเทอร์เฟซที่ออบเจ็กต์บริการระบุ
ตัวอย่างเช่น หากต้องการเรียกข้อมูลรายงาน YouTube Analytics สำหรับช่องของผู้ใช้ที่ตรวจสอบสิทธิ์แล้ว ให้ทำดังนี้
report = youtube.reports().query(ids='channel==MINE', start_date='2016-05-01', end_date='2016-06-30', metrics='views').execute()
Ruby
หลังจากได้รับโทเค็นการเข้าถึงแล้ว แอปพลิเคชันจะใช้โทเค็นดังกล่าวเพื่อส่งคําขอ API ในนามของบัญชีผู้ใช้หรือบัญชีบริการหนึ่งๆ ได้ ใช้ข้อมูลเข้าสู่ระบบการให้สิทธิ์เฉพาะผู้ใช้เพื่อสร้างออบเจ็กต์บริการสําหรับ API ที่ต้องการเรียกใช้ จากนั้นใช้ออบเจ็กต์ดังกล่าวเพื่อส่งคําขอ API ที่ได้รับอนุญาต
- สร้างออบเจ็กต์บริการสําหรับ API ที่ต้องการเรียกใช้
ตัวอย่างเช่น หากต้องการเรียกใช้ YouTube Analytics API เวอร์ชัน 1 ให้ทำดังนี้
youtube = Google::Apis::YoutubeAnalyticsV1::YouTubeAnalyticsService.new
- ตั้งค่าข้อมูลเข้าสู่ระบบในบริการ
youtube.authorization = credentials
- ส่งคําขอไปยังบริการ API โดยใช้อินเทอร์เฟซที่ออบเจ็กต์บริการระบุ
ตัวอย่างเช่น หากต้องการเรียกข้อมูลรายงาน YouTube Analytics สำหรับช่องของผู้ใช้ที่ตรวจสอบสิทธิ์แล้ว ให้ทำดังนี้
report = youtube.query_report('channel==MINE', '2016-05-01', '2016-06-30', 'views')
หรือจะให้สิทธิ์ตามวิธีการแต่ละวิธีก็ได้โดยระบุพารามิเตอร์ options
ให้กับวิธีการ
report = youtube.query_report('channel==MINE', '2016-05-01', '2016-06-30', 'views', options: { authorization: auth_client })
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 (เช่น เมื่อเรียกใช้ YouTube Analytics API)
โปรดทราบว่า YouTube Analytics API ไม่รองรับขั้นตอนสำหรับบัญชีบริการ YouTube Reporting API รองรับบัญชีบริการสำหรับเจ้าของเนื้อหา YouTube ที่เป็นเจ้าของและจัดการช่อง YouTube หลายช่องเท่านั้น เช่น ค่ายเพลงและสตูดิโอภาพยนตร์
คุณสามารถลองใช้ Google API ทั้งหมดและดูขอบเขตของ API เหล่านั้นได้ที่ OAuth 2.0 Playground
ตัวอย่าง HTTP GET
การเรียกใช้ปลายทาง (YouTube Analytics API)
reports.query
โดยใช้ส่วนหัว Authorization: Bearer
HTTP อาจมีลักษณะดังนี้ โปรดทราบว่าคุณต้องระบุโทเค็นการเข้าถึงของคุณเอง โดยทำดังนี้
GET /youtube/analytics/v1/reports?ids=channel%3D%3DMINE&start-date=2016-05-01&end-date=2016-06-30&metrics=views HTTP/1.1 Host: www.googleapis.com Authorization: Bearer access_token
นี่คือการเรียก API เดียวกันสําหรับผู้ใช้ที่ตรวจสอบสิทธิ์แล้วโดยใช้พารามิเตอร์สตริงการค้นหา access_token
GET https://www.googleapis.com/youtube/analytics/v1/reports?access_token=access_token&ids=channel%3D%3DMINE&start-date=2016-05-01&end-date=2016-06-30&metrics=views
ตัวอย่างของ curl
คุณสามารถทดสอบคําสั่งเหล่านี้ด้วยแอปพลิเคชันบรรทัดคําสั่ง curl
ต่อไปนี้คือตัวอย่างที่ใช้ตัวเลือกส่วนหัว HTTP (แนะนำ)
curl -H "Authorization: Bearer access_token" https://www.googleapis.com/youtube/analytics/v1/reports?ids=channel%3D%3DMINE&start-date=2016-05-01&end-date=2016-06-30&metrics=views
หรือจะใช้ตัวเลือกพารามิเตอร์สตริงการค้นหาก็ได้
curl https://www.googleapis.com/youtube/analytics/v1/reports?access_token=access_token&ids=channel%3D%3DMINE&start-date=2016-05-01&end-date=2016-06-30&metrics=views
ตัวอย่างที่สมบูรณ์
ตัวอย่างต่อไปนี้จะแสดงออบเจ็กต์รูปแบบ JSON ที่แสดงข้อมูลยอดดูสำหรับช่อง YouTube ของผู้ใช้ที่ตรวจสอบสิทธิ์แล้ว หลังจากที่ผู้ใช้ให้สิทธิ์แอปพลิเคชันเรียกข้อมูลรายงาน YouTube Analytics
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_YouTubeAnalytics::YT_ANALYTICS_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
- หน้าจำลองเพื่อเรียกใช้ปฏิทิน 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" # 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/yt-analytics.readonly', 'https://www.googleapis.com/auth/calendar.readonly'] API_SERVICE_NAME = 'youtubeAnalytics' API_VERSION = 'v1' 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 credentials from the session. credentials = google.oauth2.credentials.Credentials( **flask.session['credentials']) youtube = googleapiclient.discovery.build( API_SERVICE_NAME, API_VERSION, credentials=credentials) report = youtube.reports().query(ids='channel==MINE', start_date='2016-05-01', end_date='2016-06-30', metrics='views').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(**report) else: # User didn't authorize read-only Drive activity permission. # Update UX and application accordingly 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.') 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, 'granted_scopes': credentials.granted_scopes} def check_granted_scopes(credentials): features = {} if 'https://www.googleapis.com/auth/yt-analytics.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="/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' # 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/youtube_analytics_v1' 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. youtube = Google::Apis::YoutubeAnalyticsV1::YouTubeAnalyticsService.new report = youtube.query_report('channel==MINE', '2016-05-01', '2016-06-30', 'views', options: { authorization: auth_client }) "<pre>#{JSON.pretty_generate(report.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
- ตรวจสอบว่าคุณได้ติดตั้ง LTS เวอร์ชันปัจจุบัน, 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 two non-Sign-In scopes: Read-only Drive activity and Google Calendar. const scopes = [ 'https://www.googleapis.com/auth/yt-analytics.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/yt-analytics.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/yt-analytics.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/youtube/analytics/v1/reports' 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 ที่กล่าวถึงด้านล่างได้จาก RFC 3986 ส่วนที่ 3
กฎการตรวจสอบความถูกต้อง | |
---|---|
รูปแบบ |
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 การเปลี่ยนเส้นทางต้องไม่มีการเปลี่ยนเส้นทางแบบเปิด |
เศษข้อความ |
URI การเปลี่ยนเส้นทางต้องไม่มีคอมโพเนนต์ของ URL ย่อย |
อักขระ |
URI การเปลี่ยนเส้นทางต้องไม่มีอักขระบางตัว ดังนี้
|
การให้สิทธิ์เพิ่มเติม
ในโปรโตคอล OAuth 2.0 แอปจะขอสิทธิ์เข้าถึงทรัพยากร ซึ่งระบุด้วยขอบเขต การขอสิทธิ์เข้าถึงทรัพยากรเมื่อต้องการถือเป็นแนวทางปฏิบัติแนะนําด้านประสบการณ์ของผู้ใช้ เซิร์ฟเวอร์การให้สิทธิ์ของ Google รองรับการให้สิทธิ์แบบเพิ่มทีละรายการเพื่อเปิดใช้แนวทางปฏิบัติดังกล่าว ฟีเจอร์นี้ช่วยให้คุณขอขอบเขตได้ตามต้องการ และหากผู้ใช้ให้สิทธิ์สําหรับขอบเขตใหม่ ระบบจะแสดงรหัสการให้สิทธิ์ซึ่งอาจแลกเป็นโทเค็นที่มีขอบเขตทั้งหมดที่ผู้ใช้ให้สิทธิ์โปรเจ็กต์
ตัวอย่างเช่น สมมติว่าแอปดึงข้อมูลรายงาน YouTube Analytics ซึ่งรายงานบางรายการเป็นรายงานด้านการเงินที่ต้องเข้าถึงขอบเขตเพิ่มเติมที่ไม่จําเป็นสําหรับรายงานอื่นๆ ในกรณีนี้ เมื่อลงชื่อเข้าใช้ แอปอาจขอสิทธิ์เข้าถึงขอบเขต https://www.googleapis.com/auth/yt-analytics.readonly
เท่านั้น
อย่างไรก็ตาม หากผู้ใช้พยายามเรียกข้อมูลรายงานทางการเงิน แอปอาจขอสิทธิ์เข้าถึงhttps://www.googleapis.com/auth/yt-analytics-monetary.readonly
ขอบเขตดังกล่าวได้ด้วย
หากต้องการใช้การให้สิทธิ์แบบเพิ่ม ให้ทำตามขั้นตอนปกติในการขอโทเค็นการเข้าถึง แต่ตรวจสอบว่าคำขอการให้สิทธิ์มีขอบเขตที่ได้รับอนุญาตก่อนหน้านี้ แนวทางนี้ช่วยให้แอปไม่ต้องจัดการโทเค็นการเข้าถึงหลายรายการ
กฎต่อไปนี้จะมีผลกับโทเค็นการเข้าถึงที่ได้รับจากการให้สิทธิ์เพิ่มเติม
- โทเค็นนี้สามารถใช้เพื่อเข้าถึงทรัพยากรที่เกี่ยวข้องกับขอบเขตใดก็ได้ที่รวมอยู่ในการให้สิทธิ์แบบรวมใหม่
- เมื่อคุณใช้โทเค็นการรีเฟรชสำหรับการให้สิทธิ์แบบรวมเพื่อให้ได้โทเค็นการเข้าถึง โทเค็นการเข้าถึงจะแสดงถึงการให้สิทธิ์แบบรวมและสามารถใช้กับค่า
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
ในตัวอย่างนี้ แอปพลิเคชันที่เรียกใช้ขอสิทธิ์เข้าถึงเพื่อดึงข้อมูล YouTube Analytics ของผู้ใช้ นอกเหนือจากสิทธิ์เข้าถึงอื่นๆ ที่ผู้ใช้ให้สิทธิ์แอปพลิเคชันแล้ว
GET https://accounts.google.com/o/oauth2/v2/auth? scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fyt-analytics.readonly& access_type=offline& state=security_token%3D138rk%3Btarget_url%3Dhttp...index& redirect_uri=http%3A%2F%2Flocalhost%2Foauth2callback& response_type=code& client_id=client_id& include_granted_scopes=true
Refreshing an access token (offline access)
Access tokens periodically expire and become invalid credentials for a related API request. You can refresh an access token without prompting the user for permission (including when the user is not present) if you requested offline access to the scopes associated with the token.
- If you use a Google API Client Library, the client object refreshes the access token as needed as long as you configure that object for offline access.
- If you are not using a client library, you need to set the
access_type
HTTP query parameter tooffline
when redirecting the user to Google's OAuth 2.0 server. In that case, Google's authorization server returns a refresh token when you exchange an authorization code for an access token. Then, if the access token expires (or at any other time), you can use a refresh token to obtain a new access token.
Requesting offline access is a requirement for any application that needs to access a Google
API when the user is not present. For example, an app that performs backup services or
executes actions at predetermined times needs to be able to refresh its access token when the
user is not present. The default style of access is called online
.
Server-side web applications, installed applications, and devices all obtain refresh tokens during the authorization process. Refresh tokens are not typically used in client-side (JavaScript) web applications.
PHP
If your application needs offline access to a Google API, set the API client's access type to
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 |
คุณต้องตั้งค่าช่องนี้เป็น refresh_token ตามที่ระบุไว้ในข้อกำหนดเฉพาะของ OAuth 2.0 |
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 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 บริการนี้ช่วยให้คุณสมัครรับการแจ้งเตือนเหตุการณ์ด้านความปลอดภัยซึ่งจะส่งข้อมูลเกี่ยวกับการเปลี่ยนแปลงที่สำคัญในบัญชีผู้ใช้ไปยังแอปพลิเคชัน จากนั้น คุณสามารถใช้ข้อมูลดังกล่าวเพื่อดําเนินการโดยขึ้นอยู่กับวิธีตอบสนองต่อเหตุการณ์
ตัวอย่างประเภทเหตุการณ์ที่บริการการปกป้องบัญชีข้ามของ 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
ดูข้อมูลเพิ่มเติมเกี่ยวกับวิธีใช้การป้องกันแบบครอบคลุมหลายบริการและรายการเหตุการณ์ทั้งหมดที่ใช้ได้ได้จากหน้า ปกป้องบัญชีผู้ใช้ด้วยการป้องกันแบบครอบคลุมหลายบริการ