Google มุ่งมั่นที่จะพัฒนาความเท่าเทียมทางเชื้อชาติให้กับชุมชนคนผิวดำ ดูวิธีการ
หน้านี้ได้รับการแปลโดย Cloud Translation API
Switch to English

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

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

โดยทั่วไปแอปพลิเคชันจะใช้บัญชีบริการเมื่อแอปพลิเคชันใช้ Google API เพื่อทำงานกับข้อมูลของตัวเองแทนที่จะเป็นข้อมูลของผู้ใช้ ตัวอย่างเช่นแอปพลิเคชันที่ใช้ Google Cloud Datastore เพื่อการคงอยู่ของข้อมูลจะใช้บัญชีบริการเพื่อตรวจสอบสิทธิ์การเรียกใช้ Google Cloud Datastore API

ผู้ดูแลระบบโดเมน G Suite ยังสามารถ ให้สิทธิ์บัญชีบริการทั่วทั้งโดเมนใน การเข้าถึงข้อมูลผู้ใช้ในนามของผู้ใช้ในโดเมน

เอกสารนี้อธิบายวิธีที่แอปพลิเคชันสามารถทำโฟลว์ OAuth 2.0 แบบเซิร์ฟเวอร์ต่อเซิร์ฟเวอร์โดยใช้ไลบรารีไคลเอ็นต์ Google APIs (แนะนำ) หรือ HTTP

ภาพรวม

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

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

สุดท้ายแอปพลิเคชันของคุณสามารถใช้โทเค็นการเข้าถึงเพื่อเรียก Google API

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

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

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

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

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

หากต้องการมอบอำนาจให้บัญชีบริการใช้ค่าที่คุณคัดลอกเป็นรหัสลูกค้า

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

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

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

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

ในการมอบอำนาจทั้งโดเมนให้กับบัญชีบริการขั้นแรกให้เปิดใช้งานการมอบสิทธิ์ทั่วโดเมนสำหรับบัญชีบริการที่มีอยู่ใน Service accounts page หรือ สร้างบัญชีบริการใหม่ โดยเปิดใช้งานการมอบสิทธิ์ทั่วทั้งโดเมน

จากนั้นผู้ดูแลระบบขั้นสูงของโดเมน G Suite จะต้องทำตามขั้นตอนต่อไปนี้:

  1. จาก G สวีทของโดเมน คอนโซลการดูแลระบบ ให้ไปที่เมนูหลัก > ความปลอดภัย> การควบคุมการ API
  2. ในบานหน้าต่างการ มอบสิทธิ์แบบกว้างของโดเมน ให้เลือก จัดการการมอบหมายแบบกว้างของโดเมน
  3. คลิก เพิ่มใหม่
  4. ในฟิลด์ รหัสลูกค้า ป้อน รหัสลูกค้า ของบัญชีบริการ คุณสามารถค้นหารหัสลูกค้าของบัญชีบริการของคุณได้ใน Service accounts page
  5. ในฟิลด์ ขอบเขต OAuth (คั่นด้วยจุลภาค) ให้ป้อนรายการขอบเขตที่แอปพลิเคชันของคุณควรได้รับอนุญาตให้เข้าถึง ตัวอย่างเช่นหากแอปพลิเคชันของคุณต้องการการเข้าถึง Google Drive API และ Google Calendar API แบบเต็มทั้งโดเมนให้ป้อน: 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));

หากคุณกำลังพัฒนาแอปบน 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 API ในแอปพลิเคชันของคุณ

Python

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

  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)

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

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

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

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

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

HTTP / REST

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

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

ส่วนต่อไปนี้อธิบายวิธีการดำเนินการขั้นตอนเหล่านี้

หากการตอบกลับมีโทเค็นการเข้าถึงคุณสามารถใช้โทเค็นการเข้าถึงเพื่อ เรียก Google API (หากการตอบกลับไม่มีโทเค็นการเข้าถึงคำขอ 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
}
การเรียกร้องเพิ่มเติม

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

เรียกใช้ Google API

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 ที่คุณต้องการเรียกใช้ คุณสร้างอ็อบเจ็กต์บริการโดยเรียกใช้ฟังก์ชัน build ด้วยชื่อและเวอร์ชันของ API และอ็อบเจ็กต์ Credentials ได้รับอนุญาต ตัวอย่างเช่นหากต้องการเรียกเวอร์ชัน 1beta3 ของ Cloud SQL Administration 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 หรือค่า Bearer ส่วนหัว HTTP ของ Authorization หากเป็นไปได้ควรใช้ส่วนหัว HTTP เนื่องจากสตริงการสืบค้นมักจะปรากฏในบันทึกของเซิร์ฟเวอร์ ในกรณีส่วนใหญ่คุณสามารถใช้ไลบรารีไคลเอ็นต์เพื่อตั้งค่าการโทรไปยัง Google APIs (เช่นเมื่อ เรียก Drive Files API )

คุณสามารถทดลองใช้ Google API ทั้งหมดและดูขอบเขตได้ที่ OAuth 2.0 Playground

ตัวอย่าง HTTP GET

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

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 & Admin> Service Accounts ให้เปิดใช้งานบัญชีบริการซึ่งมี "รหัสคีย์" ที่ใช้ในการลงนามในการยืนยัน

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