การใช้ OAuth 2.0 สำหรับแอปพลิเคชันเซิร์ฟเวอร์ถึงเซิร์ฟเวอร์

ระบบ Google OAuth 2.0 รองรับการโต้ตอบระหว่างเซิร์ฟเวอร์กับเซิร์ฟเวอร์ เช่น ระหว่างเว็บแอปพลิเคชันและบริการของ Google สำหรับสถานการณ์สมมตินี้คุณจำเป็นต้องมีบัญชีบริการซึ่งเป็นบัญชีที่เป็นของแอพลิเคชันของคุณแทนการไปยังผู้ใช้แต่ละคน แอปพลิเคชันของคุณเรียกใช้ Google API ในนามของบัญชีบริการ ดังนั้นผู้ใช้จะไม่เกี่ยวข้องโดยตรง สถานการณ์นี้บางครั้งเรียกว่า "OAuth แบบสองทาง" หรือ "2LO" (คำว่า "OAuth แบบสามทาง" ที่เกี่ยวข้องหมายถึงสถานการณ์ที่แอปพลิเคชันของคุณเรียกใช้ Google API ในนามของผู้ใช้ปลายทาง และจำเป็นต้องได้รับความยินยอมจากผู้ใช้ในบางครั้ง)

โดยปกติ แอปพลิเคชันจะใช้บัญชีบริการเมื่อแอปพลิเคชันใช้ 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 API

การสร้างบัญชีบริการ

ข้อมูลประจำตัวของบัญชีบริการประกอบด้วยที่อยู่อีเมลที่สร้างขึ้นซึ่งไม่ซ้ำกันและมีคู่คีย์สาธารณะ/ส่วนตัวอย่างน้อยหนึ่งคู่ หากเปิดใช้การมอบสิทธิ์ทั่วทั้งโดเมน รหัสไคลเอ็นต์จะเป็นส่วนหนึ่งของข้อมูลรับรองของบัญชีบริการด้วย

หากแอปพลิเคชันของคุณทำงานบน Google App Engine บัญชีบริการจะได้รับการตั้งค่าโดยอัตโนมัติเมื่อคุณสร้างโครงการ

หากแอปพลิเคชันของคุณทำงานบน Google Compute Engine บัญชีบริการจะได้รับการตั้งค่าโดยอัตโนมัติเมื่อคุณสร้างโครงการ แต่คุณต้องระบุขอบเขตที่แอปพลิเคชันของคุณต้องการเข้าถึงเมื่อคุณสร้างอินสแตนซ์ Google Compute Engine สำหรับข้อมูลเพิ่มเติมโปรดดูที่การ เตรียมความพร้อมตัวอย่างการใช้บัญชีผู้ใช้บริการ

หากใบสมัครของคุณไม่ได้ทำงานบน Google App Engine หรือ Google Compute Engine คุณจะต้องได้รับสิทธิเหล่านี้ใน Google API Consoleในการสร้างข้อมูลประจำตัวของบัญชีบริการ หรือเพื่อดูข้อมูลประจำตัวสาธารณะที่คุณได้สร้างไว้แล้ว ให้ทำดังต่อไปนี้:

ขั้นแรก สร้างบัญชีบริการ:

  1. เปิด Service accounts page
  2. If prompted, select a project, or create a new one.
  3. คลิก สร้างบัญชีผู้ใช้บริการ
  4. ภายใต้รายละเอียดบัญชีบริการพิมพ์ชื่อ, ID, และคำอธิบายสำหรับบัญชีผู้ใช้บริการจากนั้นคลิกสร้างและดำเนินการต่อ
  5. ตัวเลือก: ภายใต้แกรนท์นี้การเข้าถึงบัญชีผู้ใช้บริการในโครงการเลือกบทบาท IAM จะกำหนดให้กับบัญชีผู้ใช้บริการ
  6. คลิกดำเนินการต่อ
  7. ตัวเลือก: การเข้าถึงผู้ใช้ภายใต้การให้กับบัญชีผู้ใช้บริการนี้เพิ่มผู้ใช้หรือกลุ่มที่ได้รับอนุญาตในการใช้และจัดการบัญชีผู้ใช้บริการ
  8. คลิกเสร็จสิ้น
  9. คลิก สร้างคีย์แล้วคลิกสร้าง

ถัดไป สร้างรหัสบัญชีบริการ:

  1. คลิกที่อยู่อีเมลสำหรับบัญชีบริการที่คุณสร้างขึ้น
  2. คลิกที่คีย์แท็บ
  3. ในการเพิ่มคีย์รายการแบบหล่นลงที่เลือกสร้างคีย์ใหม่
  4. คลิกสร้าง

คู่คีย์สาธารณะ/ส่วนตัวใหม่ของคุณถูกสร้างขึ้นและดาวน์โหลดไปยังเครื่องของคุณ มันทำหน้าที่เป็นสำเนาเฉพาะของคีย์ส่วนตัว คุณมีหน้าที่รับผิดชอบในการจัดเก็บอย่างปลอดภัย หากคุณทำคู่คีย์นี้หาย คุณจะต้องสร้างคู่คีย์ใหม่

คุณสามารถกลับไปที่ API Console ได้ตลอดเวลาเพื่อดูที่อยู่อีเมลลายนิ้วมือคีย์สาธารณะและข้อมูลอื่น ๆ หรือการสร้างสาธารณะ / คู่คีย์เพิ่มเติมส่วนตัว สำหรับรายละเอียดเพิ่มเติมเกี่ยวกับข้อมูลประจำตัวของบัญชีผู้ใช้บริการใน API Consoleดู บัญชีบริการ ใน API Consoleแฟ้มความช่วยเหลือ

จดที่อยู่อีเมลของบัญชีบริการและจัดเก็บไฟล์คีย์ส่วนตัวของบัญชีบริการไว้ในตำแหน่งที่แอปพลิเคชันของคุณสามารถเข้าถึงได้ แอปพลิเคชันของคุณต้องการให้เรียกใช้ API ที่ได้รับอนุญาต

การมอบอำนาจทั่วทั้งโดเมนให้กับบัญชีบริการ

หากคุณมีบัญชี Google Workspace ผู้ดูแลระบบขององค์กรจะอนุญาตให้แอปพลิเคชันเข้าถึงข้อมูลผู้ใช้ในนามของผู้ใช้ในโดเมน Google Workspace ตัวอย่างเช่น แอปพลิเคชันที่ใช้ Google Calendar API เพื่อเพิ่มกิจกรรมในปฏิทินของผู้ใช้ทั้งหมดในโดเมน Google Workspace จะใช้บัญชีบริการเพื่อเข้าถึง Google Calendar API ในนามของผู้ใช้ การอนุญาตให้บัญชีบริการเข้าถึงข้อมูลในนามของผู้ใช้ในโดเมนบางครั้งเรียกว่า "การมอบอำนาจทั่วทั้งโดเมน" ให้กับบัญชีบริการ

ในการมอบอำนาจทั่วทั้งโดเมนให้กับบัญชีบริการ ผู้ดูแลระบบขั้นสูงของโดเมน Google Workspace ต้องทำตามขั้นตอนต่อไปนี้

  1. จาก Google พื้นที่ทำงานของโดเมน คอนโซลการดูแลระบบ ให้ไปที่เมนูหลัก > ความปลอดภัย> การควบคุมการ API
  2. ในบานหน้าต่างกว้างคณะผู้แทนโดเมนเลือกจัดการโดเมนคณะผู้แทนไวด์
  3. คลิกที่เพิ่มใหม่
  4. ในฟิลด์รหัสลูกค้าให้ป้อนรหัสลูกค้าบัญชีผู้ใช้บริการของ คุณสามารถค้นหารหัสลูกค้าบัญชีผู้ใช้บริการของคุณใน Service accounts page
  5. ในขอบเขต OAuth ฟิลด์ (คั่นด้วยจุลภาค) ป้อนรายการขอบเขตว่าโปรแกรมที่คุณควรจะได้รับการเข้าถึง ตัวอย่างเช่นถ้าใบสมัครของคุณต้องการการเข้าถึงทั้งโดเมนแบบเต็มไปยัง API ของ Google ไดรฟ์และ API ของ Google ปฏิทินป้อน: https://www.googleapis.com/auth/drive, https://www.googleapis.com/auth / ปฏิทิน
  6. คลิกอนุญาต

ตอนนี้ แอปพลิเคชันของคุณมีอำนาจในการเรียก 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));

หากคุณมีการพัฒนา app บนแพลตฟอร์มคลาวด์ของ Google คุณสามารถใช้ ข้อมูลประจำตัวของโปรแกรมเริ่มต้น แทนซึ่งสามารถลดความซับซ้อนของกระบวนการ

มอบอำนาจทั่วทั้งโดเมน

หากคุณได้มอบการเข้าถึงทั้งโดเมนไปยังบัญชีของบริการและคุณต้องการที่จะเลียนแบบบัญชีผู้ใช้ที่ระบุที่อยู่อีเมลของบัญชีผู้ใช้ที่มี 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 สำหรับหลาม ทำตามขั้นตอนต่อไปนี้:

  1. สร้าง 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)

    หากคุณมีการพัฒนา app บนแพลตฟอร์มคลาวด์ของ Google คุณสามารถใช้ ข้อมูลประจำตัวของโปรแกรมเริ่มต้น แทนซึ่งสามารถลดความซับซ้อนของกระบวนการ

  2. มอบอำนาจทั่วทั้งโดเมน

    หากคุณได้มอบการเข้าถึงทั้งโดเมนไปยังบัญชีของบริการและคุณต้องการที่จะเลียนแบบบัญชีผู้ใช้ที่ใช้ with_subject วิธีการที่มีอยู่ ServiceAccountCredentials วัตถุ ตัวอย่างเช่น:

    delegated_credentials = credentials.with_subject('user@example.org')

ใช้อ็อบเจ็กต์ Credentials เพื่อเรียก Google APIs ในแอปพลิเคชันของคุณ

HTTP/REST

หลังจากที่คุณได้รับรหัสลูกค้าและคีย์ส่วนตัวจาก API Consoleแอพลิเคชันของคุณต้องทำตามขั้นตอนต่อไปนี้:

  1. สร้าง JSON Web Token (JWT ออกเสียงว่า "jot") ซึ่งประกอบด้วยส่วนหัว ชุดการอ้างสิทธิ์ และลายเซ็น
  2. ขอโทเค็นการเข้าถึงจากเซิร์ฟเวอร์การให้สิทธิ์ Google OAuth 2.0
  3. จัดการการตอบสนอง JSON ที่ Authorization Server ส่งคืน

ส่วนต่างๆ ที่ตามมาจะอธิบายวิธีการทำตามขั้นตอนเหล่านี้

ถ้าตอบรวมถึงโทเค็นการเข้าถึงคุณสามารถใช้การเข้าถึงโทเค็นการ เรียก API ของ Google (หากการตอบกลับไม่มีโทเค็นเพื่อการเข้าถึง คำขอ JWT และโทเค็นของคุณอาจมีรูปแบบไม่ถูกต้อง หรือบัญชีบริการอาจไม่ได้รับอนุญาตให้เข้าถึงขอบเขตที่ร้องขอ)

เมื่อโทเค็นการเข้าถึง หมดอายุ แอพลิเคชันของคุณสร้าง JWT อีกสัญญาณมันและขอโทเค็นการเข้าถึงอื่น

แอปพลิเคชันเซิร์ฟเวอร์ของคุณใช้ JWT เพื่อขอโทเค็นจากเซิร์ฟเวอร์การอนุญาตของ Google จากนั้นใช้โทเค็นเพื่อเรียกตำแหน่งข้อมูล Google API ไม่มีผู้ใช้ปลายทางที่เกี่ยวข้อง

ส่วนที่เหลือของส่วนนี้จะอธิบายรายละเอียดเฉพาะของการสร้าง JWT การลงนาม JWT การสร้างคำขอโทเค็นการเข้าถึง และการจัดการการตอบกลับ

การสร้าง JWT

JWT ประกอบด้วยสามส่วน: ส่วนหัว ชุดการอ้างสิทธิ์ และลายเซ็น ส่วนหัวและชุดการอ้างสิทธิ์เป็นออบเจ็กต์ JSON ออบเจ็กต์ JSON เหล่านี้จัดลำดับเป็นไบต์ UTF-8 จากนั้นเข้ารหัสโดยใช้การเข้ารหัส Base64url การเข้ารหัสนี้ให้ความยืดหยุ่นต่อการเปลี่ยนแปลงการเข้ารหัสอันเนื่องมาจากการดำเนินการเข้ารหัสซ้ำๆ ส่วนหัวชุดเรียกร้องและลายเซ็นจะตัดแบ่งกันที่มีระยะเวลา ( . ) ตัวละคร

JWT ประกอบด้วย:

{Base64url encoded header}.{Base64url encoded claim set}.{Base64url encoded signature}

สตริงฐานสำหรับลายเซ็นมีดังนี้:

{Base64url encoded header}.{Base64url encoded claim set}
การสร้างส่วนหัว JWT

ส่วนหัวประกอบด้วยสองฟิลด์ที่ระบุอัลกอริทึมการเซ็นชื่อและรูปแบบของการยืนยัน ทั้งสองฟิลด์เป็นฟิลด์บังคับ และแต่ละฟิลด์มีค่าเพียงค่าเดียว เมื่อมีการแนะนำอัลกอริธึมและรูปแบบเพิ่มเติม ส่วนหัวนี้จะเปลี่ยนไปตามนั้น

บัญชีบริการใช้อัลกอริทึม RSA SHA-256 และรูปแบบโทเค็น JWT ด้วยเหตุนี้ การแสดง JSON ของส่วนหัวจึงเป็นดังนี้:

{"alg":"RS256","typ":"JWT"}

การแสดง Base64url ของสิ่งนี้มีดังนี้:

eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9
การสร้างชุดการเรียกร้อง JWT

ชุดการอ้างสิทธิ์ JWT ประกอบด้วยข้อมูลเกี่ยวกับ JWT รวมถึงการอนุญาตที่ร้องขอ (ขอบเขต) เป้าหมายของโทเค็น ผู้ออก เวลาที่ออกโทเค็น และอายุการใช้งานของโทเค็น ฟิลด์ส่วนใหญ่เป็นฟิลด์บังคับ เช่นเดียวกับส่วนหัว JWT ชุดการอ้างสิทธิ์ JWT เป็นอ็อบเจ็กต์ JSON และใช้ในการคำนวณลายเซ็น

การเรียกร้องที่จำเป็น

การอ้างสิทธิ์ที่จำเป็นในชุดการเคลม 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 ด้านล่างนี้เป็นตัวอย่างของการแทนค่า JSON ของชุด JWT Claim:

{
  "iss": "761326798069-r5mljlln1rd4lrbhg75efgigp36m78j5@developer.gserviceaccount.com",
  "scope": "https://www.googleapis.com/auth/prediction",
  "aud": "https://oauth2.googleapis.com/token",
  "exp": 1328554385,
  "iat": 1328550785
}
การคำนวณลายเซ็น

JSON เว็บลายเซ็น (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 เข้าสู่ระบบด้วยฟังก์ชันแฮช 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 ค่า

เรียก Google APIs

Java

ใช้ GoogleCredential วัตถุที่จะเรียก Google APIs โดยทำตามขั้นตอนต่อไปนี้:

  1. สร้างวัตถุบริการ API ที่คุณต้องการที่จะเรียกใช้ GoogleCredential วัตถุ ตัวอย่างเช่น:
    SQLAdmin sqladmin =
        new SQLAdmin.Builder(httpTransport, JSON_FACTORY, credential).build();
  2. ร้องขอทำให้การให้บริการ API โดยใช้ อินเตอร์เฟซที่จัดไว้ให้โดยวัตถุบริการ ตัวอย่างเช่นในกรณีของรายการฐานข้อมูล Cloud SQL ในน่าตื่นเต้นเช่น-123 โครงการ:
    SQLAdmin.Instances.List instances =
        sqladmin.instances().list("exciting-example-123").execute();

Python

ใช้ผู้มีอำนาจของ Credentials คัดค้านการเรียก Google APIs โดยทำตามขั้นตอนต่อไปนี้:

  1. สร้างวัตถุบริการสำหรับ API ที่คุณต้องการเรียกใช้ คุณสร้างวัตถุบริการ AA โดยการเรียก build ฟังก์ชั่นที่มีชื่อและรุ่นของ API และได้รับอนุญาต Credentials วัตถุ ตัวอย่างเช่นในการเรียกรุ่น 1beta3 ของ Cloud SQL บริหาร API:
    import googleapiclient.discovery
    
    sqladmin = googleapiclient.discovery.build('sqladmin', 'v1beta3', credentials=credentials)
  2. ร้องขอทำให้การให้บริการ API โดยใช้ อินเตอร์เฟซที่จัดไว้ให้โดยวัตถุบริการ ตัวอย่างเช่นในกรณีของรายการฐานข้อมูล Cloud SQL ในน่าตื่นเต้นเช่น-123 โครงการ:
    response = sqladmin.instances().list(project='exciting-example-123').execute()

HTTP/REST

หลังจากที่แอปพลิเคชันของคุณได้รับโทเค็นเพื่อการเข้าถึงแล้ว คุณสามารถใช้โทเค็นดังกล่าวเพื่อทำการเรียกไปยัง Google API ในนามของบัญชีบริการหรือบัญชีผู้ใช้ที่ระบุได้ หากได้รับการอนุญาตขอบเขตการเข้าถึงที่กำหนดโดย API การทำเช่นนี้รวมถึงการเข้าถึงโทเค็นในการร้องขอไปยัง API โดยรวมทั้ง access_token พารามิเตอร์การค้นหาหรือ Authorization ส่วนหัว HTTP Bearer คุ้มค่า หากเป็นไปได้ ควรใช้ส่วนหัว HTTP เนื่องจากสตริงการสืบค้นมักจะมองเห็นได้ในบันทึกของเซิร์ฟเวอร์ ในกรณีส่วนใหญ่คุณสามารถใช้ห้องสมุดลูกค้าในการตั้งค่าการโทรของคุณไปยัง Google APIs (ตัวอย่างเช่นเมื่อ การเรียกไฟล์ API ไดรฟ์ )

คุณสามารถลองออกทั้งหมดของ Google APIs และดูขอบเขตของพวกเขาที่ สนามเด็กเล่น OAuth 2.0

ตัวอย่าง HTTP GET

โทรไป drive.files ปลายทาง (ไฟล์ไดรฟ์ API) โดยใช้ Authorization: Bearer HTTP ส่วนหัวอาจมีลักษณะดังต่อไปนี้ โปรดทราบว่าคุณต้องระบุโทเค็นการเข้าถึงของคุณเอง:

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. หากคุณกำลังพยายามใช้การมอบสิทธิ์ทั่วทั้งโดเมน บัญชีบริการจะไม่ได้รับสิทธิ์ในคอนโซลผู้ดูแลระบบของโดเมนของผู้ใช้

ตรวจสอบให้แน่ใจว่าบัญชีผู้ใช้บริการเป็นผู้มีอำนาจใน คณะผู้แทนโดเมนกว้าง หน้าของคอนโซลผู้ดูแลระบบสำหรับผู้ใช้ใน sub เรียกร้อง (เขต)

แม้ว่าโดยทั่วไปจะใช้เวลาสองสามนาที แต่อาจใช้เวลาถึง 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 (ค่าใดก็ได้) หากคุณกำลังใช้การมอบสิทธิ์ทั่วทั้งโดเมน ขอบเขตที่ขออย่างน้อยหนึ่งขอบเขตจะไม่ได้รับสิทธิ์ในคอนโซลผู้ดูแลระบบ

ตรวจสอบให้แน่ใจว่าบัญชีผู้ใช้บริการเป็นผู้มีอำนาจใน คณะผู้แทนโดเมนกว้าง หน้าของคอนโซลผู้ดูแลระบบสำหรับผู้ใช้ใน sub เรียกร้อง (เขต) และว่ามันรวมทั้งหมดของขอบเขตคุณขอใน scope การเรียกร้องของ JWT ของคุณ

แม้ว่าโดยทั่วไปจะใช้เวลาสองสามนาที แต่อาจใช้เวลาถึง 24 ชั่วโมงในการให้สิทธิ์ในการเผยแพร่ไปยังผู้ใช้ทั้งหมดในบัญชี Google ของคุณ

invalid_grant Not a valid email. ไม่มีผู้ใช้รายนี้ ตรวจสอบว่าที่อยู่อีเมลใน sub เรียกร้อง (เขต) เป็นที่ถูกต้อง
invalid_grant

Invalid JWT: Token must be a short-lived token (60 minutes) and in a reasonable timeframe. Check your 'iat' and 'exp' values and use a clock with skew to account for clock differences between systems.

โดยปกติหมายความว่าเวลาของระบบท้องถิ่นไม่ถูกต้อง นอกจากนี้ยังอาจเกิดขึ้นได้หาก 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. ไม่มีการร้องขอขอบเขต (รายการขอบเขตที่ว่างเปล่า) หรือหนึ่งในขอบเขตที่ร้องขอไม่มีอยู่ (เช่น ไม่ถูกต้อง)

ตรวจสอบให้แน่ใจว่า scope การเรียกร้อง (เขต) ของ JWT เป็นประชากรและเปรียบเทียบขอบเขตที่ว่ามันมีกับขอบเขตเอกสารสำหรับ API ที่คุณต้องการใช้งานเพื่อให้แน่ใจว่าไม่มีข้อผิดพลาดหรือความผิดพลาด

หมายเหตุว่ารายการของขอบเขตในส่วน scope ความต้องการเรียกร้องที่จะคั่นด้วยช่องว่างไม่จุลภาค

disabled_client The OAuth client was disabled. คีย์ที่ใช้ในการลงนามในการยืนยัน JWT ถูกปิดใช้งาน

ไปที่ Google API Consoleและภายใต้ IAM และผู้ดูแลระบบ> บัญชีบริการให้เปิดใช้งานบัญชีผู้ใช้บริการซึ่งมี "รหัสคีย์" ใช้ในการลงชื่อยืนยัน

ภาคผนวก: การอนุญาตบัญชีบริการโดยไม่มี OAuth

ด้วย Google API บางตัว คุณสามารถทำการเรียก API ที่ได้รับอนุญาตโดยใช้ JWT ที่ลงนามโดยตรงเป็นโทเค็นสำหรับผู้ถือ แทนที่จะเป็นโทเค็นการเข้าถึง OAuth 2.0 เมื่อเป็นไปได้ คุณสามารถหลีกเลี่ยงการร้องขอเครือข่ายไปยังเซิร์ฟเวอร์การให้สิทธิ์ของ Google ก่อนทำการเรียก API

หาก API ที่คุณต้องการโทรมีความหมายบริการที่ตีพิมพ์ใน พื้นที่เก็บข้อมูล Google APIs GitHub คุณสามารถโทร API ที่ได้รับอนุญาตใช้ JWT แทนโทเค็นการเข้าถึง ในการทำเช่นนั้น:

  1. สร้างบัญชีผู้ใช้บริการ ตามที่อธิบายไว้ข้างต้น อย่าลืมเก็บไฟล์ JSON ที่คุณได้รับเมื่อคุณสร้างบัญชี
  2. การใช้ห้องสมุด 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 ลูกค้า และ 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')
  1. โทร API ที่ใช้ลงนาม JWT เป็นผู้ถือ token:
    GET /v1/projects/abc/databases/123/indexes HTTP/1.1
    Authorization: Bearer SIGNED_JWT
    Host: firestore.googleapis.com