ระบบ Google OAuth 2.0 รองรับการโต้ตอบแบบเซิร์ฟเวอร์ต่อเซิร์ฟเวอร์ เช่น การโต้ตอบระหว่างเว็บแอปพลิเคชันและบริการของ Google สําหรับกรณีนี้ คุณจะต้องมีบัญชีบริการซึ่งเป็นบัญชีที่เป็นของแอปพลิเคชันของคุณ ไม่ใช่ของผู้ใช้แต่ละราย แอปพลิเคชันของคุณเรียกใช้ Google APIs ในนามบัญชีบริการนั้น ผู้ใช้จึงไม่มีส่วนเกี่ยวข้องโดยตรง สถานการณ์นี้บางครั้งเรียกว่า "OAuth แบบสองทาง" หรือ "2LO" (คําว่า "OAuth แบบ 3 ทาง" ที่เกี่ยวข้องหมายถึงสถานการณ์ที่แอปพลิเคชันของคุณเรียก Google API ในนามของผู้ใช้ปลายทาง และบางครั้งต้องได้รับคํายินยอมจากผู้ใช้)
โดยทั่วไป แอปพลิเคชันจะใช้บัญชีบริการเมื่อแอปพลิเคชันใช้ Google APIs เพื่อทํางานกับข้อมูลของตนเอง ไม่ใช่ข้อมูลของผู้ใช้ เช่น แอปพลิเคชันที่ใช้ 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 ที่ได้รับอนุญาต
การมอบสิทธิ์ทั่วทั้งโดเมนให้กับบัญชีบริการ
ผู้ดูแลระบบ Workspace ขององค์กรสามารถให้สิทธิ์แอปพลิเคชันในการเข้าถึงข้อมูลผู้ใช้ Workspace ในนามของผู้ใช้ในโดเมน Google Workspace ได้โดยใช้บัญชี Google Workspace เช่น แอปพลิเคชันที่ใช้ Google Calendar API เพื่อเพิ่มกิจกรรมลงในปฏิทินของผู้ใช้ทุกคนในโดเมน Google Workspace จะใช้บัญชีบริการเพื่อเข้าถึง Google Calendar API ในนามของผู้ใช้ บางครั้งการให้สิทธิ์บัญชีบริการเพื่อเข้าถึงข้อมูลในนามของผู้ใช้ในโดเมนจะเรียกว่า "การมอบสิทธิ์ทั่วทั้งโดเมน" ให้กับบัญชีบริการ
หากต้องการมอบสิทธิ์ทั่วทั้งโดเมนให้กับบัญชีบริการ ผู้ดูแลระบบขั้นสูงของโดเมน Google Workspace ต้องทําตามขั้นตอนต่อไปนี้
- จาก คอนโซลผู้ดูแลระบบของโดเมน Google Workspace ให้ไปที่เมนูหลัก > ความปลอดภัย > การเข้าถึงและการควบคุมข้อมูล > การควบคุม API
- ในแผงการมอบสิทธิ์ทั่วทั้งโดเมน ให้เลือกจัดการการมอบสิทธิ์ทั่วทั้งโดเมน
- คลิกเพิ่มใหม่
- กรอกรหัสไคลเอ็นต์ของบัญชีบริการในช่องรหัสไคลเอ็นต์ ดูรหัสไคลเอ็นต์ของบัญชีบริการได้ใน Service accounts page
- ในช่องขอบเขต OAuth (คั่นด้วยเครื่องหมายจุลภาค) ให้ป้อนรายการขอบเขตที่แอปพลิเคชันของคุณควรได้รับสิทธิ์เข้าถึง เช่น หากแอปพลิเคชันของคุณต้องการเข้าถึง Google Drive API และ Google Calendar API แบบทั้งโดเมน ให้ป้อน https://www.googleapis.com/auth/drive, https://www.googleapis.com/auth/calendar
- คลิกให้สิทธิ์
แอปพลิเคชันของคุณมีสิทธิ์เรียก API เป็นผู้ใช้ในโดเมน Workspace ของคุณ (เพื่อ "สวมบทบาท" ผู้ใช้) เมื่อคุณเตรียมที่จะเรียกใช้ 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("workspace-user@example.com");
โค้ดด้านบนใช้ออบเจ็กต์ GoogleCredential
เพื่อเรียกเมธอด createDelegated()
อาร์กิวเมนต์ของเมธอด createDelegated()
ต้องเป็นของผู้ใช้บัญชี Workspace ของคุณ โค้ดที่ส่งคําขอจะใช้ข้อมูลเข้าสู่ระบบนี้เพื่อเรียกใช้ Google API โดยใช้บัญชีบริการของคุณ
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 API ในแอปพลิเคชัน
HTTP/REST
หลังจากได้รับรหัสไคลเอ็นต์และคีย์ส่วนตัวจาก API Consoleแล้ว แอปพลิเคชันจะต้องทําตามขั้นตอนต่อไปนี้
- สร้าง JSON Web Token (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
ส่วนหัวประกอบด้วย 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 และเข้ารหัสแบบ Safe64url เหมือนกับส่วนหัว 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 เมื่อประมวลผลลายเซ็น อัลกอริทึมการให้สิทธิ์เดียวที่เซิร์ฟเวอร์การให้สิทธิ์ของ 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 ที่ลงชื่อแล้ว แอปพลิเคชันจะสามารถใช้โทเค็นดังกล่าวเพื่อขอโทเค็นเพื่อการเข้าถึงได้
คําขอโทเค็นเพื่อการเข้าถึงนี้เป็นคําขอ HTTPS POST
และส่วนเนื้อหามีการเข้ารหัส URL URL จะแสดงด้านล่างนี้
https://oauth2.googleapis.com/token
ต้องมีพารามิเตอร์ต่อไปนี้ในคําขอ HTTPS POST
ชื่อ | คำอธิบาย |
---|---|
grant_type |
ใช้สตริงต่อไปนี้ โดยเข้ารหัส URL ตามความจําเป็น
urn:ietf:params:oauth:grant-type:jwt-bearer |
assertion |
JWT รวมถึงลายเซ็น |
ด้านล่างนี้คือดัมพ์ดิบของคําขอ 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
การเรียกใช้ API ของ Google
Java
ใช้ออบเจ็กต์ GoogleCredential
เพื่อเรียกใช้ Google APIs โดยทําตามขั้นตอนต่อไปนี้
- สร้างออบเจ็กต์บริการสําหรับ API ที่คุณต้องการเรียกใช้โดยใช้ออบเจ็กต์
GoogleCredential
ตัวอย่างเช่นSQLAdmin sqladmin = new SQLAdmin.Builder(httpTransport, JSON_FACTORY, credential).build();
- ส่งคําขอไปยังบริการ API โดยใช้อินเทอร์เฟซที่ออบเจ็กต์บริการมีให้
ตัวอย่างเช่น หากต้องการแสดงอินสแตนซ์ของฐานข้อมูล Cloud SQL ในโปรเจ็กต์ที่น่าตื่นเต้น example-123
SQLAdmin.Instances.List instances = sqladmin.instances().list("exciting-example-123").execute();
Python
ใช้ออบเจ็กต์ Credentials
ที่ได้รับอนุญาตเพื่อเรียก Google APIs โดยทําตามขั้นตอนต่อไปนี้
- สร้างออบเจ็กต์บริการสําหรับ API ที่คุณต้องการเรียกใช้ คุณสร้างออบเจ็กต์บริการโดยเรียกฟังก์ชัน
build
ด้วยชื่อและเวอร์ชันของ API และออบเจ็กต์Credentials
ที่ได้รับอนุญาต เช่น หากต้องการเรียกเวอร์ชัน 1 เบต้า 3 ของ Cloud SQL Administration APIimport googleapiclient.discovery sqladmin = googleapiclient.discovery.build('sqladmin', 'v1beta3', credentials=credentials)
- ส่งคําขอไปยังบริการ API โดยใช้อินเทอร์เฟซที่ออบเจ็กต์บริการมีให้
ตัวอย่างเช่น หากต้องการแสดงอินสแตนซ์ของฐานข้อมูล Cloud SQL ในโปรเจ็กต์ที่น่าตื่นเต้น example-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. |
หากพยายามใช้การมอบสิทธิ์ทั่วทั้งโดเมน บัญชีบริการนั้นจะไม่ได้รับอนุญาตในคอนโซลผู้ดูแลระบบของโดเมนของผู้ใช้ |
ตรวจสอบว่าบัญชีบริการได้รับอนุญาตในหน้า
การมอบสิทธิ์ทั่วทั้งโดเมนของคอนโซลผู้ดูแลระบบสําหรับผู้ใช้ในการอ้างสิทธิ์ (ช่อง) แม้ว่าโดยปกติจะใช้เวลา 2-3 นาที แต่การอนุมัติอาจใช้เวลาถึง 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 รายการในคอนโซลผู้ดูแลระบบ |
ตรวจสอบว่าบัญชีบริการได้รับอนุญาตในหน้า
การมอบสิทธิ์ทั่วทั้งโดเมนของคอนโซลผู้ดูแลระบบสําหรับผู้ใช้ในการอ้างสิทธิ์ (ช่อง) แม้ว่าโดยปกติจะใช้เวลา 2-3 นาที แต่การอนุมัติอาจใช้เวลาถึง 24 ชั่วโมงจึงจะมีผลกับผู้ใช้ทุกคนในบัญชี Google ของคุณ |
admin_policy_enforced |
(ค่าใดก็ได้) | บัญชี Google ให้สิทธิ์ขอบเขตที่ขออย่างน้อย 1 รายการไม่ได้เนื่องจากนโยบายของผู้ดูแลระบบ Google Workspace |
อ่านบทความความช่วยเหลือสําหรับผู้ดูแลระบบ Google Workspace เพื่อควบคุมว่าจะให้แอปของบุคคลที่สามและแอปภายในรายการใดเข้าถึงข้อมูล Google Workspace ได้บ้าง เพื่อดูข้อมูลเพิ่มเติมเกี่ยวกับวิธีที่ผู้ดูแลระบบอาจจํากัดการเข้าถึงขอบเขตทั้งหมดหรือขอบเขตที่จํากัดและละเอียดอ่อนจนกว่าสิทธิ์เข้าถึงรหัสไคลเอ็นต์ OAuth จะมีความชัดเจน |
invalid_client |
(ค่าใดก็ได้) |
ไคลเอ็นต์ OAuth หรือโทเค็น JWT ไม่ถูกต้องหรือกําหนดค่าไม่ถูกต้อง โปรดดูรายละเอียดในคําอธิบายข้อผิดพลาด |
ตรวจสอบว่าโทเค็น JWT ถูกต้องและมีการอ้างสิทธิ์ที่ถูกต้อง ตรวจสอบว่าไคลเอ็นต์ OAuth และบัญชีบริการมีการกําหนดค่าอย่างถูกต้อง และคุณใช้ที่อยู่อีเมลที่ถูกต้อง ตรวจสอบว่าโทเค็น JWT ถูกต้องและออกให้สําหรับไคลเอ็นต์ในคําขอ |
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 > บัญชีบริการ ให้เปิดใช้บัญชีบริการซึ่งมี "รหัสคีย์" ที่ใช้เพื่อรับรองการยืนยัน |
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 ที่คุณต้องการเรียกใช้มีคําจํากัดความของบริการที่เผยแพร่ในที่เก็บ 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 ปัจจุบันและระบุเวลาที่แน่นอนในอีก 3,600 วินาทีสําหรับช่องexp
เพื่อระบุเวลาที่ 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