ระบบ Google OAuth 2.0 รองรับการโต้ตอบแบบเซิร์ฟเวอร์ต่อเซิร์ฟเวอร์ เช่น การโต้ตอบระหว่างเว็บแอปพลิเคชันกับบริการของ Google ในสถานการณ์นี้ คุณต้องมีบัญชีบริการซึ่งเป็นบัญชีของแอปพลิเคชันของคุณ ไม่ใช่สําหรับผู้ใช้ปลายทางแต่ละราย แอปพลิเคชันของคุณจะเรียก Google API ในนามของบัญชีบริการนั้น ดังนั้นผู้ใช้จึงไม่มีส่วนเกี่ยวข้องโดยตรง สถานการณ์นี้บางครั้งเรียกว่า "OAuth แบบสองทาง &&tt; หรือ"2LO." (คําที่เกี่ยวข้อง &"OAuth แบบ 3 ทางหมายถึงสถานการณ์ที่แอปพลิเคชันเรียกใช้ Google APIs ในนามผู้ใช้ปลายทางและบางครั้งต้องได้รับคํายินยอมจากผู้ใช้)
โดยปกติ แอปพลิเคชันจะใช้บัญชีบริการเมื่อแอปพลิเคชันใช้ Google API เพื่อทํางานกับข้อมูลของตัวเอง ไม่ใช่ข้อมูลของผู้ใช้ เช่น แอปพลิเคชันที่ใช้ Google Cloud Datastore เพื่อความต่อเนื่องของข้อมูลจะใช้บัญชีบริการในการตรวจสอบสิทธิ์การเรียกใช้ไปยัง Google Cloud Datastore API
นอกจากนี้ ผู้ดูแลระบบโดเมน Google Workspace ยังให้สิทธิ์ทั่วทั้งบัญชีบริการทั่วทั้งโดเมนเพื่อเข้าถึงข้อมูลผู้ใช้ในนามของผู้ใช้ในโดเมนได้อีกด้วย
เอกสารนี้จะอธิบายวิธีที่แอปพลิเคชันดําเนินการขั้นตอน OAuth 2.0 แบบเซิร์ฟเวอร์ต่อเซิร์ฟเวอร์ได้โดยใช้ไลบรารีของไคลเอ็นต์ Google APIs (แนะนํา) หรือ HTTP
ภาพรวม
หากต้องการรองรับการโต้ตอบแบบเซิร์ฟเวอร์ต่อเซิร์ฟเวอร์ ให้สร้างบัญชีบริการสําหรับโปรเจ็กต์ของคุณใน API Consoleหากต้องการเข้าถึงข้อมูลผู้ใช้สําหรับผู้ใช้ในบัญชี Google Workspace ให้มอบสิทธิ์การเข้าถึงบัญชีบริการให้ทั่วทั้งโดเมน
จากนั้นแอปพลิเคชันจะจัดเตรียมการเรียก API ที่ได้รับอนุญาตโดยใช้ข้อมูลเข้าสู่ระบบของบัญชีบริการเพื่อขอโทเค็นเพื่อการเข้าถึงจากเซิร์ฟเวอร์การตรวจสอบสิทธิ์ OAuth 2.0
และสุดท้าย แอปพลิเคชันจะใช้โทเค็นเพื่อการเข้าถึงเพื่อเรียก Google APIs ได้
การสร้างบัญชีบริการ
ข้อมูลเข้าสู่ระบบของบัญชีบริการประกอบด้วยอีเมลที่สร้างขึ้นที่ไม่ซ้ํากันและมีคู่คีย์สาธารณะ/ส่วนตัวอย่างน้อย 1 รายการ หากเปิดใช้การมอบสิทธิ์ทั่วทั้งโดเมน รหัสไคลเอ็นต์จะเป็นส่วนหนึ่งของข้อมูลเข้าสู่ระบบของบัญชีบริการด้วย
หากแอปพลิเคชันทํางานบน Google App Engine ระบบจะสร้างบัญชีบริการโดยอัตโนมัติเมื่อคุณสร้างโปรเจ็กต์
หากแอปพลิเคชันทํางานใน Google Compute Engine ระบบจะสร้างบัญชีบริการโดยอัตโนมัติเมื่อคุณสร้างโปรเจ็กต์ แต่คุณต้องระบุขอบเขตที่แอปพลิเคชันจําเป็นต้องมีสิทธิ์เข้าถึงเมื่ออินสแตนซ์ Google Compute Engine เพื่อสร้างอินสแตนซ์ ดูข้อมูลเพิ่มเติมได้ที่การเตรียมอินสแตนซ์เพื่อใช้บัญชีบริการ
หากแอปพลิเคชันไม่ทํางานใน Google App Engine หรือ Google Compute Engine คุณต้องมีข้อมูลเข้าสู่ระบบเหล่านี้ใน Google API Consoleหากต้องการสร้างข้อมูลเข้าสู่ระบบของบัญชีบริการ หรือดูข้อมูลเข้าสู่ระบบสาธารณะที่สร้างไว้แล้ว ให้ทําตามขั้นตอนต่อไปนี้
ขั้นแรก สร้างบัญชีบริการ:
- เปิด Service accounts page
- If prompted, select a project, or create a new one.
- คลิก สร้างบัญชีผู้ใช้บริการ
- ภายใต้รายละเอียดบัญชีบริการพิมพ์ชื่อ, ID, และคำอธิบายสำหรับบัญชีผู้ใช้บริการจากนั้นคลิกสร้างและดำเนินการต่อ
- ตัวเลือก: ภายใต้แกรนท์นี้การเข้าถึงบัญชีผู้ใช้บริการในโครงการเลือกบทบาท IAM จะกำหนดให้กับบัญชีผู้ใช้บริการ
- คลิกดำเนินการต่อ
- ตัวเลือก: การเข้าถึงผู้ใช้ภายใต้การให้กับบัญชีผู้ใช้บริการนี้เพิ่มผู้ใช้หรือกลุ่มที่ได้รับอนุญาตในการใช้และจัดการบัญชีผู้ใช้บริการ
- คลิกเสร็จสิ้น
- คลิก สร้างคีย์แล้วคลิกสร้าง
ถัดไป สร้างรหัสบัญชีบริการ:
- คลิกที่อยู่อีเมลสำหรับบัญชีบริการที่คุณสร้างขึ้น
- คลิกที่คีย์แท็บ
- ในการเพิ่มคีย์รายการแบบหล่นลงที่เลือกสร้างคีย์ใหม่
- คลิกสร้าง
คู่คีย์สาธารณะ/ส่วนตัวใหม่ของคุณถูกสร้างขึ้นและดาวน์โหลดไปยังเครื่องของคุณ มันทำหน้าที่เป็นสำเนาเฉพาะของคีย์ส่วนตัว คุณมีหน้าที่รับผิดชอบในการจัดเก็บอย่างปลอดภัย หากคุณทำคู่คีย์นี้หาย คุณจะต้องสร้างคู่คีย์ใหม่
คุณกลับไปที่ API Console ได้ทุกเมื่อเพื่อดูอีเมล ลายนิ้วมือของคีย์สาธารณะ และข้อมูลอื่นๆ หรือสร้างคู่คีย์สาธารณะ/ส่วนตัวเพิ่มเติม ดูรายละเอียดเพิ่มเติมเกี่ยวกับข้อมูลเข้าสู่ระบบของบัญชีบริการใน API Consoleได้ที่บัญชีบริการในไฟล์ความช่วยเหลือ API Console
จดอีเมลของบัญชีบริการและเก็บไฟล์คีย์ส่วนตัวของบัญชีบริการไว้ในตําแหน่งที่แอปพลิเคชันเข้าถึงได้ แอปพลิเคชันต้องการให้แอปพลิเคชันเรียก API ที่ได้รับอนุญาต
การมอบสิทธิ์ทั่วทั้งโดเมนให้กับบัญชีบริการ
หากคุณมีบัญชี Google Workspace ผู้ดูแลระบบขององค์กรจะให้สิทธิ์แอปพลิเคชันเพื่อเข้าถึงข้อมูลผู้ใช้ในนามของผู้ใช้ในโดเมน Google Workspace ได้ เช่น แอปพลิเคชันที่ใช้ Google Calendar API เพื่อเพิ่มกิจกรรมในปฏิทินของผู้ใช้ทั้งหมดในโดเมน Google Workspace จะใช้บัญชีบริการเพื่อเข้าถึง Google Calendar API ในนามของผู้ใช้ การให้สิทธิ์บัญชีบริการเพื่อเข้าถึงข้อมูลแทนผู้ใช้ในโดเมน บางครั้งเรียกว่า "การมอบสิทธิ์ทั่วทั้งโดเมน" ให้แก่บัญชีบริการ
หากต้องการมอบสิทธิ์ทั่วทั้งโดเมนให้กับบัญชีบริการ ผู้ดูแลระบบขั้นสูงของโดเมน Google Workspace ต้องทําตามขั้นตอนต่อไปนี้
- จากคอนโซลผู้ดูแลระบบของโดเมน Google Workspace ให้ไปที่เมนูหลัก > Security > การเข้าถึงและการควบคุมข้อมูล > การควบคุม API
- ในแผงการมอบสิทธิ์ทั่วทั้งโดเมน ให้เลือกจัดการการมอบสิทธิ์ทั่วทั้งโดเมน
- คลิก Add new
- ในช่องรหัสไคลเอ็นต์ ให้ป้อนรหัสไคลเอ็นต์ของบัญชีบริการ ดูรหัสไคลเอ็นต์ของบัญชีบริการได้ใน Service accounts page
- ป้อนรายการขอบเขตที่แอปพลิเคชันควรจะได้รับสิทธิ์เข้าถึงในช่องขอบเขต OAuth (คั่นด้วยเครื่องหมายจุลภาค) เช่น หากแอปพลิเคชันต้องการเข้าถึง Google ไดรฟ์ API และ Google ปฏิทิน API แบบทั่วทั้งโดเมน ให้ป้อน https://www.googleapis.com/auth/drive, https://www.googleapis.com/auth/calendar
- คลิกให้สิทธิ์
แอปพลิเคชันของคุณมีสิทธิ์เรียก API ในฐานะผู้ใช้ในโดเมน (และ "สวมบทบาทเป็น&ผู้ใช้) เมื่อคุณเตรียมที่จะเรียกใช้ API ที่ได้รับอนุญาต คุณต้องระบุผู้ใช้ที่จะแอบอ้าง
กําลังเตรียมการเรียก API ที่ได้รับอนุญาต
Java
หลังจากได้รับอีเมลของไคลเอ็นต์และคีย์ส่วนตัวจาก API Consoleแล้ว ให้ใช้ไลบรารีของไคลเอ็นต์ Google APIs สําหรับ Java เพื่อสร้างออบเจ็กต์ GoogleCredential
จากข้อมูลเข้าสู่ระบบของบัญชีบริการและขอบเขตที่แอปพลิเคชันจําเป็นต้องเข้าถึง เช่น
import com.google.api.client.googleapis.auth.oauth2.GoogleCredential; import com.google.api.services.sqladmin.SQLAdminScopes; // ... GoogleCredential credential = GoogleCredential.fromStream(new FileInputStream("MyProject-1234.json")) .createScoped(Collections.singleton(SQLAdminScopes.SQLSERVICE_ADMIN));
หากคุณกําลังพัฒนาแอปใน Google Cloud Platform คุณอาจใช้ข้อมูลเข้าสู่ระบบเริ่มต้นของแอปพลิเคชันแทน ซึ่งจะทําให้กระบวนการง่ายขึ้น
มอบสิทธิ์ทั่วทั้งโดเมน
หากคุณได้มอบสิทธิ์ทั่วทั้งบัญชีบริการให้กับบัญชีบริการและต้องการแอบอ้างเป็นบัญชีผู้ใช้ ให้ระบุอีเมลของบัญชีผู้ใช้ด้วยเมธอด createDelegated
ของออบเจ็กต์ GoogleCredential
เช่น
GoogleCredential credential = GoogleCredential.fromStream(new FileInputStream("MyProject-1234.json")) .createScoped(Collections.singleton(SQLAdminScopes.SQLSERVICE_ADMIN)) .createDelegated("user@example.com");
ใช้ออบเจ็กต์ GoogleCredential
เพื่อเรียก Google APIs ในแอปพลิเคชันของคุณ
Python
หลังจากได้รับอีเมลของไคลเอ็นต์และคีย์ส่วนตัวจาก API Consoleแล้ว ให้ใช้ไลบรารีของไคลเอ็นต์ Google APIs สําหรับ Python เพื่อทําตามขั้นตอนต่อไปนี้
- สร้างออบเจ็กต์
Credentials
จากข้อมูลรับรองของบัญชีบริการและขอบเขตที่แอปพลิเคชันจําเป็นต้องเข้าถึง ดังตัวอย่างต่อไปนี้from google.oauth2 import service_account SCOPES = ['https://www.googleapis.com/auth/sqlservice.admin'] SERVICE_ACCOUNT_FILE = '/path/to/service.json' credentials = service_account.Credentials.from_service_account_file( SERVICE_ACCOUNT_FILE, scopes=SCOPES)
หากคุณกําลังพัฒนาแอปใน Google Cloud Platform คุณอาจใช้ข้อมูลเข้าสู่ระบบเริ่มต้นของแอปพลิเคชันแทน ซึ่งจะทําให้กระบวนการง่ายขึ้น
- มอบสิทธิ์ทั่วทั้งโดเมน
หากคุณได้มอบสิทธิ์ทั่วทั้งบัญชีบริการให้กับบัญชีบริการและต้องการแอบอ้างเป็นบัญชีผู้ใช้ ให้ใช้วิธีการ
with_subject
ของออบเจ็กต์ServiceAccountCredentials
ที่มีอยู่ เช่นdelegated_credentials = credentials.with_subject('user@example.org')
ใช้ออบเจ็กต์ข้อมูลเข้าสู่ระบบเพื่อเรียก Google APIs ในแอปพลิเคชัน
HTTP/REST
หลังจากได้รับรหัสไคลเอ็นต์และคีย์ส่วนตัวจาก API Consoleแล้ว แอปพลิเคชันของคุณจะต้องทําตามขั้นตอนต่อไปนี้
- สร้างโทเค็นเว็บ JSON (JWT, ออกเสียง, "jot") ซึ่งประกอบด้วยส่วนหัว ชุดการอ้างสิทธิ์ และลายเซ็น
- ขอโทเค็นเพื่อการเข้าถึงจากเซิร์ฟเวอร์การให้สิทธิ์ Google OAuth 2.0
- จัดการการตอบสนองของ JSON ที่ Authorization Server แสดงผล
หัวข้อต่อไปนี้อธิบายวิธีดําเนินการขั้นตอนเหล่านี้
หากการตอบกลับมีโทเค็นเพื่อการเข้าถึง คุณจะใช้โทเค็นเพื่อการเข้าถึงเพื่อเรียก Google API ได้ (หากการตอบกลับไม่มีโทเค็นเพื่อการเข้าถึง คําขอ JWT และโทเค็นที่สร้างขึ้นอาจไม่ถูกต้อง หรือบัญชีบริการอาจไม่มีสิทธิ์เข้าถึงขอบเขตที่ขอ)
เมื่อโทเค็นเพื่อการเข้าถึงหมดอายุ แอปพลิเคชันจะสร้าง JWT, ลงชื่อ และส่งคําขอโทเค็นเพื่อการเข้าถึงอื่น

เนื้อหาที่เหลือของส่วนนี้จะอธิบายรายละเอียดของการสร้าง JWT, การลงชื่อ JWT, การสร้างคําขอโทเค็นเพื่อการเข้าถึง และการจัดการการตอบกลับ
การสร้าง JWT
JWT ประกอบด้วย 3 ส่วน ได้แก่ ส่วนหัว ชุดการอ้างสิทธิ์ และลายเซ็น ส่วนหัวและชุดการอ้างสิทธิ์คือออบเจ็กต์ JSON ออบเจ็กต์ JSON เหล่านี้มีการเรียงลําดับเป็น UTF-8 ไบต์ จากนั้นเข้ารหัสโดยใช้การเข้ารหัส Base64url การเข้ารหัสนี้ช่วยให้รับมือกับการเปลี่ยนแปลงการเข้ารหัสได้อย่างยืดหยุ่นเนื่องจากการดําเนินการเข้ารหัสซ้ําๆ ส่วนหัว ชุดการอ้างสิทธิ์ และลายเซ็นจะต่อกันด้วยอักขระจุด (.
)
JWT ประกอบด้วยดังนี้
{Base64url encoded header}.{Base64url encoded claim set}.{Base64url encoded signature}
สตริงฐานสําหรับลายเซ็นมีดังนี้
{Base64url encoded header}.{Base64url encoded claim set}
การสร้างส่วนหัว JWT
ส่วนหัวประกอบด้วย 2 ช่องที่ระบุอัลกอริทึมการลงนามและรูปแบบการยืนยัน ทั้งสองช่องเป็นช่องที่ต้องกรอก และแต่ละช่องจะมีค่าเดียวเท่านั้น เมื่อมีการเปิดตัวอัลกอริทึมและรูปแบบเพิ่มเติม ส่วนหัวนี้จะเปลี่ยนแปลงไปตามนั้น
บัญชีบริการจะใช้อัลกอริทึม RSA SHA-256 และรูปแบบโทเค็น JWT ด้วยเหตุนี้ การนําเสนอ JSON ของส่วนหัวจึงเป็นดังนี้
{"alg":"RS256","typ":"JWT"}
การเป็นตัวแทนของ Base64url มีดังนี้
eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9
การสร้างชุดการอ้างสิทธิ์ JWT
ชุดการอ้างสิทธิ์ JWT มีข้อมูลเกี่ยวกับ JWT รวมถึงสิทธิ์ที่ขอ (ขอบเขต) เป้าหมายของโทเค็น ผู้ออกใบรับรอง เวลาที่ออกโทเค็น และอายุการใช้งานของโทเค็น โดยช่องส่วนใหญ่เป็นช่องที่ต้องกรอก ชุดการอ้างสิทธิ์ JWT เป็นออบเจ็กต์ JSON ซึ่งใช้ในการคํานวณลายเซ็นเหมือนกับส่วนหัว JWT
การอ้างสิทธิ์ที่จําเป็น
การอ้างสิทธิ์ที่จําเป็นในชุดการอ้างสิทธิ์ JWT แสดงอยู่ด้านล่าง โดยอาจปรากฏตามลําดับใดก็ได้ในการตั้งค่าการอ้างสิทธิ์
ชื่อ | คำอธิบาย |
---|---|
iss |
อีเมลของบัญชีบริการ |
scope |
รายการสิทธิ์ที่แอปพลิเคชันส่งคําขอคั่นด้วยช่องว่าง |
aud |
ตัวบ่งชี้เป้าหมายที่ชัดเจนของการยืนยัน เมื่อสร้างโทเค็นเพื่อการเข้าถึง ค่านี้จะเป็น https://oauth2.googleapis.com/token เสมอ |
exp |
เวลาหมดอายุของการยืนยันซึ่งระบุเป็นวินาทีนับจากเวลา 00:00:00 น. (UTC) ซึ่งก็คือ 1 มกราคม 1970 ค่านี้มีเวลาไม่เกิน 1 ชั่วโมงหลังจากเวลาที่ออก |
iat |
เวลาที่ออกการยืนยัน โดยระบุเป็นวินาทีตั้งแต่ 00:00:00 น. (UTC) ซึ่งก็คือ 1 มกราคม 1970 |
การนําเสนอ JSON ในช่องที่จําเป็นในชุดการอ้างสิทธิ์ JWT แสดงอยู่ด้านล่าง
{ "iss": "761326798069-r5mljlln1rd4lrbhg75efgigp36m78j5@developer.gserviceaccount.com", "scope": "https://www.googleapis.com/auth/devstorage.read_only", "aud": "https://oauth2.googleapis.com/token", "exp": 1328554385, "iat": 1328550785 }
การอ้างสิทธิ์เพิ่มเติม
ในบางกรณี แอปพลิเคชันจะใช้การมอบสิทธิ์ทั่วทั้งโดเมนเพื่อดําเนินการในนามของผู้ใช้ในองค์กรหนึ่งๆ ได้ คุณต้องให้สิทธิ์การดําเนินการสวมบทบาทประเภทนี้ก่อน แอปพลิเคชันจึงจะสวมบทบาทเป็นผู้ใช้ได้ และโดยปกติจะจัดการโดยผู้ดูแลระบบขั้นสูง โปรดดูข้อมูลเพิ่มเติมที่หัวข้อควบคุมการเข้าถึง API ด้วยการมอบสิทธิ์ทั่วทั้งโดเมน
หากต้องการเข้าถึงโทเค็นเพื่อการเข้าถึงที่มอบสิทธิ์การเข้าถึงทรัพยากรให้แก่แอปพลิเคชัน ให้ใส่อีเมลของผู้ใช้ในการอ้างสิทธิ์ JWT เป็นค่าของช่อง sub
ชื่อ | คำอธิบาย |
---|---|
sub |
อีเมลของผู้ใช้ที่แอปพลิเคชันส่งคําขอรับสิทธิ์เข้าถึงที่ได้รับมอบอํานาจ |
หากแอปพลิเคชันไม่มีสิทธิ์สวมบทบาทเป็นผู้ใช้ การตอบกลับคําขอโทเค็นเพื่อการเข้าถึงที่มีช่อง sub
จะเป็นข้อผิดพลาด
ด้านล่างจะแสดงตัวอย่างของชุดการอ้างสิทธิ์ JWT ที่มีช่อง sub
{ "iss": "761326798069-r5mljlln1rd4lrbhg75efgigp36m78j5@developer.gserviceaccount.com", "sub": "some.user@example.com", "scope": "https://www.googleapis.com/auth/prediction", "aud": "https://oauth2.googleapis.com/token", "exp": 1328554385, "iat": 1328550785 }
การเข้ารหัสชุดการอ้างสิทธิ์ JWT
เช่นเดียวกับส่วนหัว JWT ชุดการอ้างสิทธิ์ JWT ควรเรียงแบบเดียวกันกับ UTF-8 และเข้ารหัสแบบ Base64url ได้อย่างปลอดภัย ด้านล่างนี้เป็นตัวอย่างการนําเสนอไฟล์การอ้างสิทธิ์ JWT ในรูปแบบ JSON
{ "iss": "761326798069-r5mljlln1rd4lrbhg75efgigp36m78j5@developer.gserviceaccount.com", "scope": "https://www.googleapis.com/auth/prediction", "aud": "https://oauth2.googleapis.com/token", "exp": 1328554385, "iat": 1328550785 }
การประมวลผลลายเซ็น
JSON Web Signature (JWS) คือข้อกําหนดที่ช่วยแนะนํากลไกในการสร้างลายเซ็นสําหรับ JWT อินพุตสําหรับลายเซ็นคืออาร์เรย์ไบต์ของเนื้อหาต่อไปนี้
{Base64url encoded header}.{Base64url encoded claim set}
โดยต้องใช้อัลกอริทึมการลงนามในส่วนหัว JWT เมื่อคํานวณลายเซ็น โดยอัลกอริทึมการลงชื่อเท่านั้นที่รองรับโดยเซิร์ฟเวอร์การให้สิทธิ์ Google OAuth 2.0 คือ RSA ที่ใช้อัลกอริทึมการแฮช SHA-256 ซึ่งจะแสดงเป็น RS256
ในช่อง alg
ในส่วนหัว JWT
รับรองการนําเสนออินพุต UTF-8 โดยใช้ SHA256withRSA (หรือที่เรียกว่า RSASSA-PKCS1-V1_5-SIGN ที่มีฟังก์ชันแฮช SHA-256) ด้วยคีย์ส่วนตัวที่ได้รับจาก Google API Consoleผลลัพธ์จะเป็นอาร์เรย์ไบต์
ลายเซ็นต้องมีการเข้ารหัส Base64url ส่วนหัว ชุดการอ้างสิทธิ์ และลายเซ็นจะต่อด้วยอักขระจุด (.
) ผลลัพธ์ที่ได้คือ JWT โดยควรเป็นค่าต่อไปนี้ (เพิ่มตัวแบ่งบรรทัดเพื่อความชัดเจน)
{Base64url encoded header}. {Base64url encoded claim set}. {Base64url encoded signature}
ด้านล่างนี้เป็นตัวอย่างของ JWT ก่อนการเข้ารหัส Base64url
{"alg":"RS256","typ":"JWT"}. { "iss":"761326798069-r5mljlln1rd4lrbhg75efgigp36m78j5@developer.gserviceaccount.com", "scope":"https://www.googleapis.com/auth/prediction", "aud":"https://oauth2.googleapis.com/token", "exp":1328554385, "iat":1328550785 }. [signature bytes]
ด้านล่างนี้คือตัวอย่างของ JWT ที่ลงนามแล้วและพร้อมส่งข้อมูล
eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiI3NjEzMjY3OTgwNjktcjVtbGpsbG4xcmQ0bHJiaGc3NWVmZ2lncDM2bTc4ajVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJzY29wZSI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL2F1dGgvcHJlZGljdGlvbiIsImF1ZCI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL29hdXRoMi92NC90b2tlbiIsImV4cCI6MTMyODU1NDM4NSwiaWF0IjoxMzI4NTUwNzg1fQ.UFUt59SUM2_AW4cRU8Y0BYVQsNTo4n7AFsNrqOpYiICDu37vVt-tw38UKzjmUKtcRsLLjrR3gFW3dNDMx_pL9DVjgVHDdYirtrCekUHOYoa1CMR66nxep5q5cBQ4y4u2kIgSvChCTc9pmLLNoIem-ruCecAJYgI9Ks7pTnW1gkOKs0x3YpiLpzplVHAkkHztaXiJdtpBcY1OXyo6jTQCa3Lk2Q3va1dPkh_d--GU2M5flgd8xNBPYw4vxyt0mP59XZlHMpztZt0soSgObf7G3GXArreF_6tpbFsS3z2t5zkEiHuWJXpzcYr5zWTRPDEHsejeBSG8EgpLDce2380ROQ
การส่งคําขอโทเค็นเพื่อการเข้าถึง
หลังจากสร้าง JWT ที่ลงชื่อแล้ว แอปพลิเคชันสามารถใช้แอปพลิเคชันเพื่อขอโทเค็นเพื่อการเข้าถึงได้
คําขอโทเค็นเพื่อการเข้าถึงนี้เป็นคําขอ POST
HTTPS และตัวเนื้อหาได้รับการเข้ารหัส URL URL แสดงอยู่ด้านล่าง
https://oauth2.googleapis.com/token
ต้องมีพารามิเตอร์ต่อไปนี้ในคําขอ HTTPS POST
ชื่อ | คำอธิบาย |
---|---|
grant_type |
ใช้สตริงต่อไปนี้ โดยเข้ารหัส URL ตามที่จําเป็น
urn:ietf:params:oauth:grant-type:jwt-bearer |
assertion |
JWT รวมถึงลายเซ็น |
ด้านล่างนี้คือไฟล์ RAW ของคําขอ HTTPS POST
ที่ใช้ในคําขอโทเค็นเพื่อการเข้าถึง
POST /token HTTP/1.1 Host: oauth2.googleapis.com Content-Type: application/x-www-form-urlencoded grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Ajwt-bearer&assertion=eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiI3NjEzMjY3OTgwNjktcjVtbGpsbG4xcmQ0bHJiaGc3NWVmZ2lncDM2bTc4ajVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJzY29wZSI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL2F1dGgvcHJlZGljdGlvbiIsImF1ZCI6Imh0dHBzOi8vYWNjb3VudHMuZ29vZ2xlLmNvbS9vL29hdXRoMi90b2tlbiIsImV4cCI6MTMyODU3MzM4MSwiaWF0IjoxMzI4NTY5NzgxfQ.ixOUGehweEVX_UKXv5BbbwVEdcz6AYS-6uQV6fGorGKrHf3LIJnyREw9evE-gs2bmMaQI5_UbabvI4k-mQE4kBqtmSpTzxYBL1TCd7Kv5nTZoUC1CmwmWCFqT9RE6D7XSgPUh_jF1qskLa2w0rxMSjwruNKbysgRNctZPln7cqQ
ด้านล่างนี้เป็นคําขอเดียวกัน โดยใช้ curl
curl -d 'grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Ajwt-bearer&assertion=eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiI3NjEzMjY3OTgwNjktcjVtbGpsbG4xcmQ0bHJiaGc3NWVmZ2lncDM2bTc4ajVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJzY29wZSI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL2F1dGgvcHJlZGljdGlvbiIsImF1ZCI6Imh0dHBzOi8vYWNjb3VudHMuZ29vZ2xlLmNvbS9vL29hdXRoMi90b2tlbiIsImV4cCI6MTMyODU3MzM4MSwiaWF0IjoxMzI4NTY5NzgxfQ.RZVpzWygMLuL-n3GwjW1_yhQhrqDacyvaXkuf8HcJl8EtXYjGjMaW5oiM5cgAaIorrqgYlp4DPF_GuncFqg9uDZrx7pMmCZ_yHfxhSCXru3gbXrZvAIicNQZMFxrEEn4REVuq7DjkTMyCMGCY1dpMa8aWfTQFt3Eh7smLchaZsU ' https://oauth2.googleapis.com/token
ตอบกลับ
หากคําขอ JWT และโทเค็นเพื่อการเข้าถึงมีรูปแบบที่ถูกต้องและบัญชีบริการมีสิทธิ์ในการดําเนินการ การตอบกลับ JSON จากเซิร์ฟเวอร์การให้สิทธิ์จะมีโทเค็นเพื่อการเข้าถึง ตัวอย่างคําตอบมีดังนี้
{ "access_token": "1/8xbJqaOZXSUZbHLl5EOtu1pxz3fmmetKx9W8CV4t79M", "scope": "https://www.googleapis.com/auth/prediction" "token_type": "Bearer", "expires_in": 3600 }
ใช้โทเค็นเพื่อการเข้าถึงซ้ําได้ในระหว่างกรอบเวลาที่ระบุโดยค่า expires_in
การเรียก Google APIs
Java
ใช้ออบเจ็กต์ GoogleCredential
เพื่อเรียก Google APIs โดยทําตามขั้นตอนต่อไปนี้
- สร้างออบเจ็กต์บริการสําหรับ API ที่คุณต้องการเรียกใช้โดยใช้ออบเจ็กต์
GoogleCredential
ดังตัวอย่างต่อไปนี้SQLAdmin sqladmin = new SQLAdmin.Builder(httpTransport, JSON_FACTORY, credential).build();
- ส่งคําขอไปยังบริการ API โดยใช้อินเทอร์เฟซที่ออบเจ็กต์บริการให้บริการ
ตัวอย่างเช่น หากต้องการแสดงอินสแตนซ์ของฐานข้อมูล Cloud SQL ในโปรเจ็กต์ที่น่าตื่นเต้นตัวอย่าง 123 ให้ทําดังนี้
SQLAdmin.Instances.List instances = sqladmin.instances().list("exciting-example-123").execute();
Python
ใช้ออบเจ็กต์ Credentials
ที่ได้รับอนุญาตเพื่อเรียก Google APIs โดยทําตามขั้นตอนต่อไปนี้
- สร้างออบเจ็กต์บริการสําหรับ API ที่ต้องการเรียกใช้ คุณสร้างออบเจ็กต์บริการโดยเรียกใช้ฟังก์ชัน
build
ด้วยชื่อและเวอร์ชันของ API และออบเจ็กต์Credentials
ที่ได้รับอนุญาต ตัวอย่างเช่น หากต้องการเรียกใช้เวอร์ชัน 1beta3 ของ Cloud SQL Administration API ให้ทําดังนี้import googleapiclient.discovery sqladmin = googleapiclient.discovery.build('sqladmin', 'v1beta3', credentials=credentials)
- ส่งคําขอไปยังบริการ API โดยใช้อินเทอร์เฟซที่ออบเจ็กต์บริการให้บริการ
ตัวอย่างเช่น หากต้องการแสดงอินสแตนซ์ของฐานข้อมูล Cloud SQL ในโปรเจ็กต์ที่น่าตื่นเต้นตัวอย่าง 123 ให้ทําดังนี้
response = sqladmin.instances().list(project='exciting-example-123').execute()
HTTP/REST
หลังจากที่แอปพลิเคชันได้รับโทเค็นเพื่อการเข้าถึงแล้ว คุณจะใช้โทเค็นเพื่อเรียก API ของ Google ในนามของบัญชีบริการหรือบัญชีผู้ใช้หนึ่งๆ ได้หากมอบสิทธิ์การเข้าถึงที่ API ต้องการ โดยให้รวมโทเค็นเพื่อการเข้าถึงในคําขอไปยัง API โดยรวมพารามิเตอร์การค้นหา access_token
หรือค่า Authorization
ของส่วนหัว HTTP Bearer
หากเป็นไปได้ คุณควรใช้ส่วนหัว HTTP เนื่องจากสตริงการค้นหามีแนวโน้มที่จะแสดงในบันทึกของเซิร์ฟเวอร์ ในกรณีส่วนใหญ่ คุณจะใช้ไลบรารีของไคลเอ็นต์เพื่อตั้งค่าการเรียกไปยัง Google API ได้ (เช่น เมื่อเรียกใช้ Drive Files API)
คุณจะลองใช้ Google 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
เมื่อโทเค็นเพื่อการเข้าถึงหมดอายุ
โทเค็นเพื่อการเข้าถึงที่เซิร์ฟเวอร์การให้สิทธิ์ Google OAuth 2.0 จะหมดอายุหลังจากระยะเวลาที่ระบุโดยค่า expires_in
เมื่อโทเค็นเพื่อการเข้าถึงหมดอายุ แอปพลิเคชันควรสร้าง JWT อื่น แล้วลงชื่อและขอโทเค็นเพื่อการเข้าถึงอื่น
รหัสข้อผิดพลาด JWT
error ช่อง |
error_description ช่อง |
ความหมาย | วิธีแก้ไข |
---|---|---|---|
unauthorized_client |
Unauthorized client or scope in request. |
หากคุณพยายามใช้การมอบสิทธิ์ทั่วทั้งโดเมน บัญชีบริการดังกล่าวจะไม่ได้รับอนุญาตในคอนโซลผู้ดูแลระบบของโดเมนของผู้ใช้ |
ตรวจสอบว่าบัญชีบริการได้รับอนุญาตในหน้าการมอบสิทธิ์ทั่วทั้งโดเมนของคอนโซลผู้ดูแลระบบสําหรับผู้ใช้ในการอ้างสิทธิ์ (ช่อง) แม้ว่าโดยปกติจะใช้เวลา 24-34 ชั่วโมงจึงจะมีผล แต่การให้สิทธิ์จะ มีผลกับผู้ใช้ทั้งหมดในบัญชี Google ของคุณ |
unauthorized_client |
Client is unauthorized to retrieve access tokens using this method, or client not
authorized for any of the scopes requested. |
บัญชีบริการได้รับสิทธิ์ให้ใช้อีเมลไคลเอ็นต์แทนรหัสไคลเอ็นต์ (ตัวเลข) ในคอนโซลผู้ดูแลระบบ | ในหน้าการมอบสิทธิ์ทั่วทั้งโดเมนในคอนโซลผู้ดูแลระบบ ให้นําไคลเอ็นต์ออกและเพิ่มไปยังรหัสตัวเลขอีกครั้ง |
access_denied |
(ค่าใดก็ได้) | หากคุณใช้การมอบสิทธิ์ทั่วทั้งโดเมน ขอบเขตที่ขออย่างน้อย 1 รายการจะไม่ได้รับอนุญาตในคอนโซลผู้ดูแลระบบ |
ตรวจสอบว่าบัญชีบริการได้รับสิทธิ์ในหน้าการมอบสิทธิ์ทั่วทั้งโดเมนของคอนโซลผู้ดูแลระบบสําหรับผู้ใช้ในการอ้างสิทธิ์ แม้ว่าโดยปกติจะใช้เวลา 24-34 ชั่วโมงจึงจะมีผล แต่การให้สิทธิ์จะ มีผลกับผู้ใช้ทั้งหมดในบัญชี Google ของคุณ |
invalid_grant |
Not a valid email. |
ไม่มีผู้ใช้รายนี้ | ตรวจสอบว่าอีเมลในการอ้างสิทธิ์ช่อง sub (ช่อง) ถูกต้อง |
invalid_grant |
|
โดยปกติจะหมายความว่าเวลาระบบท้องถิ่นไม่ถูกต้อง กรณีนี้อาจเกิดขึ้นได้หากค่า exp มากกว่า 65 นาทีในอนาคตจากค่า iat หรือค่า exp ต่ํากว่า iat |
ตรวจสอบว่านาฬิกาในระบบที่สร้าง JWT ถูกต้อง หากจําเป็น ให้ซิงค์เวลาของคุณกับ Google NTP |
invalid_grant |
Invalid JWT Signature. |
การยืนยัน JWT ได้ลงชื่อด้วยคีย์ส่วนตัวที่ไม่ได้เชื่อมโยงกับบัญชีบริการที่อีเมลของลูกค้าระบุไว้ หรือคีย์ที่ใช้นั้นถูกลบ ปิดใช้ หรือหมดอายุแล้ว นอกจากนี้ การยืนยัน JWT อาจเข้ารหัสไม่ถูกต้อง ต้องมีการเข้ารหัสแบบ Base64 โดยไม่มีเครื่องหมายขึ้นบรรทัดใหม่หรือระยะห่างจากขอบเท่ากัน |
ถอดรหัสชุดการอ้างสิทธิ์ JWT และยืนยันคีย์ที่รับรองการยืนยันว่ามีการเชื่อมโยงกับบัญชีบริการ พยายามใช้ไลบรารี OAuth ที่ Google จัดหาให้เพื่อให้แน่ใจว่ามีการสร้าง JWT อย่างถูกต้อง |
invalid_scope |
Invalid OAuth scope or ID token audience provided. |
ไม่มีคําขอขอบเขต (รายการขอบเขตที่ว่างเปล่า) หรือไม่มีขอบเขตที่ขอ (ไม่มี) (ไม่ถูกต้อง) |
ตรวจสอบว่าได้สร้างการอ้างสิทธิ์ โปรดทราบว่ารายการขอบเขตในการอ้างสิทธิ์ |
disabled_client |
The OAuth client was disabled. |
คีย์ที่ใช้ลงชื่อยืนยัน JWT ปิดอยู่ |
ไปที่ Google API Consoleและในส่วน IAM & Admin > Service Accounts ให้เปิดใช้บัญชีบริการที่มี "Key ID" เพื่อใช้รับรอง |
ภาคผนวก: การให้สิทธิ์บัญชีบริการโดยไม่มี OAuth
API บางรายการของ Google จะให้คุณเรียกใช้ API ที่ได้รับอนุญาตได้โดยใช้ JWT ที่ลงชื่อแล้วเป็นโทเค็นสําหรับผู้ถือโดยตรง แทนที่จะใช้โทเค็นเพื่อการเข้าถึง OAuth 2.0 หากเป็นไปได้ โปรดหลีกเลี่ยงการส่งคําขอเครือข่ายไปยังเซิร์ฟเวอร์การให้สิทธิ์ของ Google ก่อนเรียก API
หาก API ที่คุณต้องการเรียกใช้มีคําจํากัดความของบริการที่เผยแพร่ในที่เก็บ Google APIs GitHub คุณเรียกใช้ API ที่ได้รับอนุญาตได้โดยใช้ JWT แทนโทเค็นเพื่อการเข้าถึง วิธีการมีดังนี้
- สร้างบัญชีบริการตามที่อธิบายไว้ข้างต้น และอย่าลืมเก็บไฟล์ JSON ที่คุณได้รับเมื่อสร้างบัญชี
- ใช้ไลบรารี JWT มาตรฐาน เช่น ไลบรารีที่พบใน jwt.io โดยสร้าง JWT ด้วยส่วนหัวและเพย์โหลดดังตัวอย่างต่อไปนี้
{ "alg": "RS256", "typ": "JWT", "kid": "abcdef1234567890" } . { "iss": "123456-compute@developer.gserviceaccount.com", "sub": "123456-compute@developer.gserviceaccount.com", "aud": "https://firestore.googleapis.com/", "iat": 1511900000, "exp": 1511903600 }
- สําหรับช่อง
kid
ในส่วนหัว ให้ระบุรหัสคีย์ส่วนตัวของบัญชีบริการ คุณดูค่านี้ได้ในช่องprivate_key_id
ของไฟล์ JSON ของบัญชีบริการ - สําหรับช่อง
iss
และsub
ให้ระบุอีเมลของบัญชีบริการ คุณจะพบค่านี้ในช่องclient_email
ของไฟล์ JSON ของบัญชีบริการ - สําหรับช่อง
aud
ให้ระบุปลายทางของ API ดังตัวอย่างต่อไปนี้https://SERVICE.googleapis.com/
- สําหรับช่อง
iat
ให้ระบุเวลา Unix ปัจจุบัน สําหรับช่องexp
ให้ระบุเวลาที่แน่นอน 3,600 วินาทีเมื่อ JWT หมดอายุ
ลงนามใน JWT กับ RSA-256 โดยใช้คีย์ส่วนตัวที่พบในไฟล์ JSON ของบัญชีบริการ
เช่น
Java
การใช้ google-api-java-client และ java-jwt ให้ดําเนินการดังนี้
GoogleCredential credential = GoogleCredential.fromStream(new FileInputStream("MyProject-1234.json")); PrivateKey privateKey = credential.getServiceAccountPrivateKey(); String privateKeyId = credential.getServiceAccountPrivateKeyId(); long now = System.currentTimeMillis(); try { Algorithm algorithm = Algorithm.RSA256(null, privateKey); String signedJwt = JWT.create() .withKeyId(privateKeyId) .withIssuer("123456-compute@developer.gserviceaccount.com") .withSubject("123456-compute@developer.gserviceaccount.com") .withAudience("https://firestore.googleapis.com/") .withIssuedAt(new Date(now)) .withExpiresAt(new Date(now + 3600 * 1000L)) .sign(algorithm); } catch ...
Python
การใช้ PyJWT
iat = time.time() exp = iat + 3600 payload = {'iss': '123456-compute@developer.gserviceaccount.com', 'sub': '123456-compute@developer.gserviceaccount.com', 'aud': 'https://firestore.googleapis.com/', 'iat': iat, 'exp': exp} additional_headers = {'kid': PRIVATE_KEY_ID_FROM_JSON} signed_jwt = jwt.encode(payload, PRIVATE_KEY_FROM_JSON, headers=additional_headers, algorithm='RS256')
- เรียก API โดยใช้ JWT ที่ลงชื่อแล้วเป็นโทเค็นสําหรับผู้ถือ:
GET /v1/projects/abc/databases/123/indexes HTTP/1.1 Authorization: Bearer SIGNED_JWT Host: firestore.googleapis.com