ระบบ OAuth 2.0 ของ Google รองรับการโต้ตอบระหว่างเซิร์ฟเวอร์ เช่น การโต้ตอบระหว่างแอปพลิเคชันเว็บกับบริการของ Google ในกรณีนี้ คุณต้องมีบัญชีบริการ ซึ่งเป็นบัญชีของแอปพลิเคชัน ไม่ใช่ของผู้ใช้ปลายทางแต่ละราย แอปพลิเคชันจะเรียกใช้ Google APIs ในนามบัญชีบริการนั้น ผู้ใช้จึงไม่มีส่วนเกี่ยวข้องโดยตรง บางครั้งสถานการณ์นี้เรียกว่า "OAuth แบบ 2 ฝ่าย" หรือ "2LO" (คําที่เกี่ยวข้อง "OAuth แบบ 3 ทาง" หมายถึงสถานการณ์ที่แอปพลิเคชันเรียกใช้ Google APIs ในนามของผู้ใช้ปลายทาง และบางครั้งต้องได้รับความยินยอมจากผู้ใช้)
โดยปกติแล้ว แอปพลิเคชันจะใช้บัญชีบริการเมื่อแอปพลิเคชันใช้ Google API เพื่อทำงานกับข้อมูลของตนเองแทนข้อมูลของผู้ใช้ ตัวอย่างเช่น แอปพลิเคชันที่ใช้ Google Cloud Datastore สำหรับการคงข้อมูลไว้จะใช้บัญชีบริการเพื่อตรวจสอบสิทธิ์การเรียกใช้ Google Cloud Datastore API
นอกจากนี้ ผู้ดูแลระบบโดเมน Google Workspace ยังให้สิทธิ์ทั่วทั้งโดเมนแก่บัญชีบริการเพื่อเข้าถึงข้อมูลผู้ใช้ในนามของผู้ใช้โดเมนได้ด้วย
เอกสารนี้อธิบายวิธีที่แอปพลิเคชันสามารถทําตามโฟลว์ OAuth 2.0 แบบเซิร์ฟเวอร์ต่อเซิร์ฟเวอร์ให้เสร็จสมบูรณ์ได้โดยใช้ไลบรารีไคลเอ็นต์ Google APIs (แนะนำ) หรือ HTTP
ภาพรวม
หากต้องการรองรับการโต้ตอบระหว่างเซิร์ฟเวอร์ ก่อนอื่นให้สร้างบัญชีบริการสําหรับโปรเจ็กต์ใน หากต้องการเข้าถึงข้อมูลผู้ใช้ในบัญชี Google Workspace ให้มอบสิทธิ์เข้าถึงทั่วทั้งโดเมนแก่บัญชีบริการ
จากนั้นแอปพลิเคชันจะเตรียมการเรียก API ที่มีสิทธิ์โดยใช้ข้อมูลเข้าสู่ระบบของบัญชีบริการเพื่อขอโทเค็นการเข้าถึงจากเซิร์ฟเวอร์การตรวจสอบสิทธิ์ OAuth 2.0
สุดท้าย แอปพลิเคชันจะใช้โทเค็นการเข้าถึงเพื่อเรียกใช้ Google API ได้
การสร้างบัญชีบริการ
ข้อมูลเข้าสู่ระบบของบัญชีบริการประกอบด้วยอีเมลที่สร้างขึ้นซึ่งไม่ซ้ำกัน และคู่คีย์สาธารณะ/คีย์ส่วนตัวอย่างน้อย 1 คู่ หากเปิดใช้การมอบสิทธิ์ทั่วทั้งโดเมน รหัสไคลเอ็นต์ก็จะเป็นส่วนหนึ่งของข้อมูลเข้าสู่ระบบของบัญชีบริการด้วย
หากแอปพลิเคชันของคุณทำงานบน Google App Engine ระบบจะตั้งค่าบัญชีบริการโดยอัตโนมัติเมื่อคุณสร้างโปรเจ็กต์
หากแอปพลิเคชันของคุณทำงานบน Google Compute Engine ระบบจะตั้งค่าบัญชีบริการโดยอัตโนมัติเมื่อคุณสร้างโปรเจ็กต์ แต่คุณต้องระบุขอบเขตที่แอปพลิเคชันของคุณจำเป็นต้องเข้าถึงเมื่อสร้างอินสแตนซ์ Google Compute Engine ดูข้อมูลเพิ่มเติมได้ที่การเตรียมอินสแตนซ์ให้ใช้บัญชีบริการ
หากแอปพลิเคชันของคุณไม่ทํางานบน Google App Engine หรือ Google Compute Engine คุณต้องรับข้อมูลเข้าสู่ระบบเหล่านี้ใน หากต้องการสร้างข้อมูลเข้าสู่ระบบของบัญชีบริการหรือดูข้อมูลเข้าสู่ระบบสาธารณะที่คุณสร้างไว้แล้ว ให้ทําดังนี้
คุณกลับมาที่ ได้ทุกเมื่อเพื่อดูอีเมล ลายนิ้วมือของคีย์สาธารณะ และข้อมูลอื่นๆ หรือเพื่อสร้างคู่คีย์สาธารณะ/ส่วนตัวเพิ่มเติม โปรดดูรายละเอียดเพิ่มเติมเกี่ยวกับข้อมูลเข้าสู่ระบบของบัญชีบริการใน ที่หัวข้อบัญชีบริการใน ไฟล์ความช่วยเหลือ
จดบันทึกอีเมลของบัญชีบริการและจัดเก็บไฟล์คีย์ส่วนตัวของบัญชีบริการไว้ในตำแหน่งที่แอปพลิเคชันเข้าถึงได้ แอปพลิเคชันของคุณต้องใช้โทเค็นเหล่านี้เพื่อทำการเรียก API ที่ได้รับอนุญาต
การมอบสิทธิ์ทั่วทั้งโดเมนให้กับบัญชีบริการ
เมื่อใช้บัญชี Google Workspace ผู้ดูแลระบบ Workspace ขององค์กรสามารถให้สิทธิ์แอปพลิเคชันเข้าถึงข้อมูลผู้ใช้ Workspace ในนามของผู้ใช้ในโดเมน Google Workspace ได้ ตัวอย่างเช่น แอปพลิเคชันที่ใช้ Google Calendar API เพื่อเพิ่มกิจกรรมในปฏิทินของผู้ใช้ทั้งหมดในโดเมน Google Workspace จะใช้บัญชีบริการเพื่อเข้าถึง Google Calendar API ในนามของผู้ใช้ การให้สิทธิ์บัญชีบริการเข้าถึงข้อมูลในนามของผู้ใช้ในโดเมนบางครั้งเรียกว่า "การมอบสิทธิ์ทั่วทั้งโดเมน" ให้กับบัญชีบริการ
หากต้องการมอบสิทธิ์ทั่วทั้งโดเมนให้กับบัญชีบริการ ผู้ดูแลระบบขั้นสูงของโดเมน Google Workspace ต้องทำตามขั้นตอนต่อไปนี้
- จาก คอนโซลผู้ดูแลระบบของโดเมน Google Workspace ให้ไปที่เมนูหลัก > ความปลอดภัย > การเข้าถึงและการควบคุมข้อมูล > การควบคุม API
- ในแผงการมอบสิทธิ์ทั่วทั้งโดเมน ให้เลือกจัดการการมอบสิทธิ์ทั่วทั้งโดเมน
- คลิกเพิ่มใหม่
- กรอกรหัสไคลเอ็นต์ของบัญชีบริการในช่องรหัสไคลเอ็นต์ คุณสามารถดูรหัสไคลเอ็นต์ของบัญชีบริการได้ใน
- ในช่องขอบเขต OAuth (คั่นด้วยคอมมา) ให้ป้อนรายการขอบเขตที่แอปพลิเคชันควรได้รับสิทธิ์เข้าถึง เช่น หากแอปพลิเคชันต้องการสิทธิ์เข้าถึง Google Drive API และ Google Calendar API แบบทั่วทั้งโดเมนโดยสมบูรณ์ ให้ป้อนข้อมูลดังนี้ https://www.googleapis.com/auth/drive, https://www.googleapis.com/auth/calendar
- คลิกให้สิทธิ์
ตอนนี้แอปพลิเคชันของคุณมีสิทธิ์เรียก API ในฐานะผู้ใช้ในโดเมน Workspace (เพื่อ "แอบอ้างเป็น" ผู้ใช้) เมื่อเตรียมที่จะเรียก API ที่มอบสิทธิ์เหล่านี้ คุณจะระบุผู้ใช้ที่จะแอบอ้างเป็นอย่างชัดเจน
เตรียมการเรียก API ที่มอบสิทธิ์
Java
หลังจากได้รับอีเมลและคีย์ส่วนตัวของลูกค้าจาก แล้ว ให้ใช้ไลบรารีของไคลเอ็นต์ 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("workspace-user@example.com");
โค้ดด้านบนใช้ออบเจ็กต์ GoogleCredential
เพื่อเรียกใช้เมธอด createDelegated()
อาร์กิวเมนต์สำหรับเมธอด createDelegated()
ต้องเป็นผู้ใช้ที่เป็นของบัญชี Workspace โค้ดที่ส่งคําขอจะใช้ข้อมูลเข้าสู่ระบบนี้เพื่อเรียกใช้ Google API โดยใช้บัญชีบริการของคุณ
Python
หลังจากได้รับอีเมลและคีย์ส่วนตัวของลูกค้าจาก แล้ว ให้ใช้ไลบรารีของไคลเอ็นต์ Google API สำหรับ 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
หลังจากได้รับรหัสไคลเอ็นต์และคีย์ส่วนตัวจาก แล้ว แอปพลิเคชันของคุณจะต้องทําตามขั้นตอนต่อไปนี้
- สร้างโทเค็นเว็บ JSON (JWT ซึ่งออกเสียงว่า "jot") ซึ่งมีส่วนหัว ชุดการอ้างสิทธิ์ และลายเซ็น
- ขอโทเค็นการเข้าถึงจากเซิร์ฟเวอร์การให้สิทธิ์ OAuth 2.0 ของ Google
- จัดการการตอบกลับ JSON ที่เซิร์ฟเวอร์การให้สิทธิ์แสดง
ส่วนต่อไปนี้จะอธิบายวิธีดำเนินการตามขั้นตอนเหล่านี้
หากการตอบกลับมีโทเค็นการเข้าถึง คุณจะใช้โทเค็นการเข้าถึงเพื่อเรียกใช้ 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
ส่วนหัวประกอบด้วย 3 ช่องที่ระบุอัลกอริทึมการลงชื่อ รูปแบบของข้อความยืนยัน และ [รหัสคีย์ของคีย์บัญชีบริการ](https://cloud.google.com/iam/docs/reference/rest/v1/projects.serviceAccounts.keys) ที่ใช้ลงชื่อ JWT คุณต้องระบุอัลกอริทึมและรูปแบบ และแต่ละช่องจะมีเพียงค่าเดียว เมื่อมีการเปิดตัวอัลกอริทึมและรูปแบบเพิ่มเติม ส่วนหัวนี้จะเปลี่ยนแปลงไปตามความเหมาะสม รหัสคีย์เป็นตัวเลือก หากระบุรหัสคีย์ที่ไม่ถูกต้อง GCP จะพยายามใช้คีย์ทั้งหมดที่เชื่อมโยงกับบัญชีบริการเพื่อยืนยันโทเค็นและปฏิเสธโทเค็นหากไม่พบคีย์ที่ถูกต้อง Google ขอสงวนสิทธิ์ในการปฏิเสธโทเค็นที่มีรหัสคีย์ไม่ถูกต้องในอนาคต
บัญชีบริการใช้อัลกอริทึม RSA SHA-256 และรูปแบบโทเค็น JWT ด้วยเหตุนี้ การแสดง JSON ของส่วนหัวจึงมีดังนี้
{"alg":"RS256","typ":"JWT", "kid":"370ab79b4513eb9bad7c9bd16a95cb76b5b2a56a"}
การนําเสนอ Base64url ของข้อมูลนี้คือ
eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsICJraWQiOiIzNzBhYjc5YjQ1MTNlYjliYWQ3YzliZDE2YTk1Y2I3NmI1YjJhNTZhIn0=
การสร้างชุดการอ้างสิทธิ์ 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 ควรจัดรูปแบบเป็น UTF-8 และเข้ารหัส Base64url-safe เช่นเดียวกับส่วนหัว JWT ด้านล่างนี้คือตัวอย่างการนําเสนอ JSON ของชุดการอ้างสิทธิ์ JWT
{ "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 เมื่อคํานวณลายเซ็น อัลกอริทึมการเซ็นชื่อเพียงอัลกอริทึมเดียวที่เซิร์ฟเวอร์การให้สิทธิ์ OAuth 2.0 ของ Google รองรับคือ RSA โดยใช้อัลกอริทึมการแฮช SHA-256 ซึ่งจะแสดงเป็น RS256
ในช่อง alg
ในส่วนหัวของ JWT
ลงนามการนำเสนอ UTF-8 ของอินพุตโดยใช้ SHA256withRSA (หรือที่เรียกว่า RSASSA-PKCS1-V1_5-SIGN ที่มีฟังก์ชันแฮช SHA-256) ด้วยคีย์ส่วนตัวที่ได้รับจาก ผลลัพธ์จะเป็นอาร์เรย์ไบต์
จากนั้นต้องเข้ารหัสลายเซ็นเป็น 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 ที่ลงชื่อแล้ว แอปพลิเคชันจะใช้ JWT ดังกล่าวเพื่อขอโทเค็นการเข้าถึงได้
คำขอโทเค็นการเข้าถึงนี้เป็นคำขอ POST
ของ HTTPS และเนื้อหาได้รับการเข้ารหัส URL URL แสดงอยู่ด้านล่าง
https://oauth2.googleapis.com/token
พารามิเตอร์ต่อไปนี้ต้องระบุในคําขอ POST
ของ HTTPS
ชื่อ | คำอธิบาย |
---|---|
grant_type |
ใช้สตริงต่อไปนี้ซึ่งเข้ารหัส URL ตามที่จำเป็น
urn:ietf:params:oauth:grant-type:jwt-bearer |
assertion |
JWT รวมถึงลายเซ็น |
ด้านล่างนี้คือข้อมูลการพุลดิบของคำขอ POST
ผ่าน HTTPS ที่ใช้ในคำขอโทเค็นการเข้าถึง
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 API
Java
ใช้ออบเจ็กต์ GoogleCredential
เพื่อเรียกใช้ Google APIs โดยทําตามขั้นตอนต่อไปนี้
- สร้างออบเจ็กต์บริการสําหรับ API ที่ต้องการเรียกใช้โดยใช้ออบเจ็กต์
GoogleCredential
เช่นSQLAdmin sqladmin = new SQLAdmin.Builder(httpTransport, JSON_FACTORY, credential).build();
- ส่งคําขอไปยังบริการ API โดยใช้อินเทอร์เฟซที่ออบเจ็กต์บริการระบุ
เช่น หากต้องการแสดงรายการอินสแตนซ์ของฐานข้อมูล Cloud SQL ในโปรเจ็กต์ exciting-example-123 ให้ทำดังนี้
SQLAdmin.Instances.List instances = sqladmin.instances().list("exciting-example-123").execute();
Python
ใช้ออบเจ็กต์ Credentials
ที่ได้รับอนุญาตเพื่อเรียกใช้ Google APIs โดยทําตามขั้นตอนต่อไปนี้
- สร้างออบเจ็กต์บริการสําหรับ API ที่ต้องการเรียกใช้ คุณสร้างออบเจ็กต์บริการโดยเรียกใช้ฟังก์ชัน
build
พร้อมชื่อและเวอร์ชันของ API รวมถึงออบเจ็กต์Credentials
ที่ได้รับอนุญาต เช่น หากต้องการเรียกใช้ Cloud SQL Administration API เวอร์ชัน 1beta3 ให้ทำดังนี้import googleapiclient.discovery sqladmin = googleapiclient.discovery.build('sqladmin', 'v1beta3', credentials=credentials)
- ส่งคําขอไปยังบริการ API โดยใช้อินเทอร์เฟซที่ออบเจ็กต์บริการระบุ
เช่น หากต้องการแสดงรายการอินสแตนซ์ของฐานข้อมูล Cloud SQL ในโปรเจ็กต์ exciting-example-123 ให้ทำดังนี้
response = sqladmin.instances().list(project='exciting-example-123').execute()
HTTP/REST
หลังจากแอปพลิเคชันได้รับโทเค็นการเข้าถึงแล้ว คุณจะใช้โทเค็นดังกล่าวเพื่อเรียกใช้ Google API ในนามของบัญชีบริการหรือบัญชีผู้ใช้ที่ระบุได้ หากได้รับสิทธิ์เข้าถึงตามขอบเขตที่ API กำหนด โดยใส่โทเค็นการเข้าถึงในคำขอไปยัง API โดยใส่พารามิเตอร์การค้นหา access_token
หรือค่าส่วนหัว HTTP Authorization
Bearer
หากเป็นไปได้ เราขอแนะนำให้ใช้ส่วนหัว HTTP เนื่องจากสตริงการค้นหามีแนวโน้มที่จะปรากฏในบันทึกของเซิร์ฟเวอร์ ในกรณีส่วนใหญ่ คุณสามารถใช้ไลบรารีของไคลเอ็นต์เพื่อตั้งค่าการเรียกใช้ Google API (เช่น เมื่อเรียกใช้ Drive Files API)
คุณสามารถลองใช้ Google API ทั้งหมดและดูขอบเขตของ 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
เมื่อโทเค็นการเข้าถึงหมดอายุ
โทเค็นการเข้าถึงที่ออกโดยเซิร์ฟเวอร์การให้สิทธิ์ OAuth 2.0 ของ Google จะหมดอายุหลังจากระยะเวลาที่ระบุโดยค่า expires_in
เมื่อโทเค็นการเข้าถึงหมดอายุ แอปพลิเคชันควรสร้าง JWT ใหม่ ลงนาม และขอโทเค็นการเข้าถึงใหม่
รหัสข้อผิดพลาด JWT
error ฟิลด์ |
error_description ฟิลด์ |
ความหมาย | วิธีแก้ไข |
---|---|---|---|
unauthorized_client |
Unauthorized client or scope in request. |
หากคุณพยายามใช้การมอบสิทธิ์ทั่วทั้งโดเมน บัญชีบริการไม่ได้รับสิทธิ์ในคอนโซลผู้ดูแลระบบของโดเมนผู้ใช้ |
ตรวจสอบว่าบัญชีบริการได้รับสิทธิ์ในหน้า
การมอบสิทธิ์ทั่วทั้งโดเมนของคอนโซลผู้ดูแลระบบสำหรับผู้ใช้ใน แม้ว่าโดยปกติจะใช้เวลาเพียงไม่กี่นาที แต่อาจใช้เวลาถึง 24 ชั่วโมงเพื่อให้การให้สิทธิ์มีผลกับผู้ใช้ทุกคนในบัญชี 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 ชั่วโมงเพื่อให้การให้สิทธิ์มีผลกับผู้ใช้ทุกคนในบัญชี Google |
admin_policy_enforced |
(ค่าใดก็ได้) | บัญชี Google ไม่สามารถให้สิทธิ์ขอบเขตอย่างน้อย 1 รายการที่ขอเนื่องจากนโยบายของผู้ดูแลระบบ Google Workspace |
โปรดดูข้อมูลเพิ่มเติมเกี่ยวกับวิธีที่ผู้ดูแลระบบอาจจำกัดการเข้าถึงขอบเขตทั้งหมดหรือขอบเขตที่มีความละเอียดอ่อนและถูกจํากัดจนกว่าจะมีการให้สิทธิ์เข้าถึงรหัสไคลเอ็นต์ OAuth ของคุณอย่างชัดเจนที่บทความความช่วยเหลือสําหรับผู้ดูแลระบบ Google Workspace เรื่องควบคุมว่าจะให้แอปของบุคคลที่สามและแอปภายในรายการใดเข้าถึงข้อมูล Google Workspace ได้บ้าง |
invalid_client |
(ค่าใดก็ได้) |
ไคลเอ็นต์ OAuth หรือโทเค็น JWT ไม่ถูกต้องหรือกําหนดค่าไม่ถูกต้อง โปรดดูรายละเอียดในคำอธิบายข้อผิดพลาด |
ตรวจสอบว่าโทเค็น JWT ถูกต้องและมีข้อมูลอ้างสิทธิ์ที่ถูกต้อง ตรวจสอบว่าไคลเอ็นต์ OAuth และบัญชีบริการได้รับการกําหนดค่าอย่างถูกต้องและคุณใช้อีเมลที่ถูกต้อง ตรวจสอบว่าโทเค็น JWT ถูกต้องและออกให้สำหรับรหัสไคลเอ็นต์ในคำขอ |
invalid_grant |
Not a valid email. |
ไม่พบผู้ใช้ | ตรวจสอบว่าอีเมลในsub การอ้างสิทธิ์ (ช่อง) ถูกต้อง |
invalid_grant |
|
ซึ่งโดยปกติแล้วหมายความว่าเวลาของระบบในเครื่องไม่ถูกต้อง หรืออาจเกิดขึ้นหากค่า exp อยู่ในอนาคตมากกว่า 65 นาทีจากค่า iat หรือค่า exp ต่ำกว่าค่า iat |
ตรวจสอบว่านาฬิกาในระบบที่สร้าง JWT ถูกต้อง หากจำเป็น ให้ซิงค์เวลากับ NTP ของ Google |
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 ถูกปิดใช้ |
ไปที่ และในส่วน IAM และผู้ดูแลระบบ > บัญชีบริการ ให้เปิดใช้บัญชีบริการที่มี "รหัสคีย์" ที่ใช้ลงนามในข้อความยืนยัน |
org_internal |
This client is restricted to users within its organization. |
รหัสไคลเอ็นต์ OAuth ในคำขอเป็นส่วนหนึ่งของโปรเจ็กต์ที่จำกัดการเข้าถึงบัญชี Google ใน องค์กร Google Cloud ที่เฉพาะเจาะจง |
ใช้บัญชีบริการจากองค์กรเพื่อตรวจสอบสิทธิ์ ยืนยันการกำหนดค่าประเภทผู้ใช้สำหรับแอปพลิเคชัน OAuth |
ภาคผนวก: การให้สิทธิ์บัญชีบริการโดยไม่ใช้ OAuth
Google API บางรายการช่วยให้คุณเรียก API ที่มีสิทธิ์ได้โดยใช้ JWT ที่ลงนามแล้วโดยตรงเป็นโทเค็นของผู้ถือแทนโทเค็นการเข้าถึง OAuth 2.0 ซึ่งจะช่วยให้คุณไม่ต้องส่งคําขอเครือข่ายไปยังเซิร์ฟเวอร์การให้สิทธิ์ของ Google ก่อนทำการเรียก API
หาก API ที่ต้องการเรียกมีคำจำกัดความของบริการที่เผยแพร่ในที่เก็บ GitHub ของ Google APIs คุณจะเรียก 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
ให้ระบุเวลาหลังจากนั้น 3600 วินาทีโดยประมาณ ซึ่งเป็นเวลาที่ 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
การใช้การป้องกันแบบครอบคลุมหลายบริการ
ขั้นตอนเพิ่มเติมที่คุณควรทำเพื่อปกป้องบัญชีของผู้ใช้คือการใช้การปกป้องข้ามบัญชีโดยใช้บริการการปกป้องข้ามบัญชีของ 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
ดูข้อมูลเพิ่มเติมเกี่ยวกับวิธีใช้การป้องกันแบบครอบคลุมหลายบริการและรายการเหตุการณ์ทั้งหมดที่ใช้ได้ได้จากหน้า ปกป้องบัญชีผู้ใช้ด้วยการป้องกันแบบครอบคลุมหลายบริการ