วิธีจัดการสิทธิ์แบบละเอียด

ภาพรวม

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

สิทธิ์แบบละเอียดคืออะไร

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

เมื่อมีการขอขอบเขตการไม่ลงชื่อเข้าใช้มากกว่า 1 ขอบเขต

ขอบเขตการลงชื่อเข้าใช้และไม่ได้ลงชื่อเข้าใช้

สำหรับแอปพลิเคชันที่ขอทั้งขอบเขตการลงชื่อเข้าใช้และไม่ได้ลงชื่อเข้าใช้ ผู้ใช้จะเห็นหน้าคำยินยอมสำหรับขอบเขตการลงชื่อเข้าใช้ (email, profile และ openid) ก่อน หลังจากที่ผู้ใช้ยินยอมที่จะแชร์ข้อมูลประจำตัวพื้นฐาน (ชื่อ อีเมล และรูปโปรไฟล์) ผู้ใช้จะเห็นหน้าจอคำยินยอมโดยละเอียดสำหรับขอบเขตที่ไม่ได้ลงชื่อเข้าใช้ ในกรณีนี้ แอปพลิเคชันต้องตรวจสอบว่าผู้ใช้ให้สิทธิ์ขอบเขตใด และจะคิดเอาเองว่าผู้ใช้ให้สิทธิ์ขอบเขตที่ขอทั้งหมดไม่ได้ ในตัวอย่างต่อไปนี้ เว็บแอปพลิเคชันจะขอขอบเขตการลงชื่อเข้าใช้ทั้ง 3 รายการและขอบเขตการไม่ได้ลงชื่อเข้าใช้ของ Google ไดรฟ์ หลังจากที่ผู้ใช้ยินยอมตามขอบเขตการลงชื่อเข้าใช้ ผู้ใช้จะเห็นหน้าจอขอความยินยอมสำหรับสิทธิ์แบบละเอียดสำหรับสิทธิ์ Google ไดรฟ์ ดังนี้

ขอบเขตการลงชื่อเข้าใช้และไม่ได้ลงชื่อเข้าใช้

ขอบเขตที่ไม่ได้ลงชื่อเข้าใช้มีมากกว่า 1 ขอบเขต

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

ขอบเขตที่ไม่ได้ลงชื่อเข้าใช้มีมากกว่า 1 ขอบเขต

สำหรับแอปพลิเคชันที่ขอเฉพาะขอบเขตการลงชื่อเข้าใช้ (email, profile และ openid) หน้าจอขอความยินยอมสำหรับสิทธิ์ #inspect-your-application-codegranular จะใช้ไม่ได้ ผู้ใช้จะอนุมัติหรือปฏิเสธคำขอลงชื่อเข้าใช้ทั้งหมดก็ได้ กล่าวคือ หากแอปพลิเคชันขอเฉพาะขอบเขตการลงชื่อเข้าใช้ (1, 2 หรือทั้ง 3) หน้าจอความยินยอมสำหรับสิทธิ์แบบละเอียดจะใช้ไม่ได้

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

จำนวนขอบเขตการลงชื่อเข้าใช้ จำนวนขอบเขตการไม่ลงชื่อเข้าใช้ หน้าจอขอความยินยอมโดยละเอียด
1-3 0 ไม่เกี่ยวข้อง
1-3 1+ เกี่ยวข้อง
0 1 ไม่เกี่ยวข้อง
0 2+ เกี่ยวข้อง

ตรวจสอบดูว่าแอปพลิเคชันของคุณได้รับผลกระทบหรือไม่

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

วิธีตรวจสอบว่าแอปพลิเคชันของคุณใช้ขอบเขตหลายขอบเขตหรือไม่

ตรวจสอบโค้ดของแอปหรือการโทรออกเพื่อดูว่าคำขอการให้สิทธิ์ Google OAuth 2.0 สร้างขึ้นจะทำให้หน้าจอขอความยินยอมสำหรับสิทธิ์แบบละเอียดแสดงขึ้นไหม

ตรวจสอบโค้ดของแอปพลิเคชัน

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

บริการ Google Identity

ข้อมูลโค้ดไลบรารี JavaScript ของ Google Identity Services ต่อไปนี้จะเริ่มต้น TokenClient ด้วยขอบเขตการไม่ลงชื่อเข้าใช้หลายรายการ หน้าจอความยินยอมเกี่ยวกับสิทธิ์แบบละเอียดจะแสดงขึ้นเมื่อเว็บแอปขอสิทธิ์จากผู้ใช้

const client = google.accounts.oauth2.initTokenClient({
  client_id: 'YOUR_CLIENT_ID',
  scope: 'https://www.googleapis.com/auth/calendar.readonly \
  https://www.googleapis.com/auth/contacts.readonly',
  callback: (response) => {
    ...
  },
});

Python

ข้อมูลโค้ดต่อไปนี้ใช้โมดูล google-auth-oauthlib.flow เพื่อสร้างคำขอการให้สิทธิ์ พารามิเตอร์ scope มีขอบเขตที่ไม่ใช่การลงชื่อเข้าใช้ 2 ขอบเขต หน้าจอขอความยินยอมสำหรับสิทธิ์แบบละเอียดจะแสดงขึ้นเมื่อเว็บแอปพลิเคชันขอสิทธิ์จากผู้ใช้

import google.oauth2.credentials
import google_auth_oauthlib.flow

# Use the client_secret.json file to identify the application requesting
# authorization. The client ID (from that file) and access scopes are required.
flow = google_auth_oauthlib.flow.Flow.from_client_secrets_file(
    'client_secret.json',
    scopes=['https://www.googleapis.com/auth/calendar.readonly',
                    'https://www.googleapis.com/auth/contacts.readonly'])

Node.js

ข้อมูลโค้ดต่อไปนี้จะสร้างออบเจ็กต์ google.auth.OAuth2 ซึ่งกำหนดพารามิเตอร์ในคำขอการให้สิทธิ์ซึ่งมีพารามิเตอร์ scope รวมขอบเขตที่ไม่ใช่การลงชื่อเข้าใช้ 2 รายการ หน้าจอความยินยอมเกี่ยวกับสิทธิ์แบบละเอียดจะแสดงขึ้นเมื่อเว็บแอปขอสิทธิ์จากผู้ใช้

const {google} = require('googleapis');

/**
  * To use OAuth2 authentication, we need access to a CLIENT_ID, CLIENT_SECRET, AND REDIRECT_URI
  * from the client_secret.json file. To get these credentials for your application, visit
  * https://console.cloud.google.com/apis/credentials.
  */
const oauth2Client = new google.auth.OAuth2(
  YOUR_CLIENT_ID,
  YOUR_CLIENT_SECRET,
  YOUR_REDIRECT_URL
);

// Access scopes for read-only Calendar and Contacts.
const scopes = [
  'https://www.googleapis.com/auth/calendar.readonly',
  'https://www.googleapis.com/auth/contacts.readonly']
];

// Generate a url that asks permissions
const authorizationUrl = oauth2Client.generateAuthUrl({
  // 'online' (default) or 'offline' (gets refresh_token)
  access_type: 'offline',
  /** Pass in the scopes array defined above.
    * Alternatively, if only one scope is needed, you can pass a scope URL as a string */
  scope: scopes,
  // Enable incremental authorization. Recommended as best practices.
  include_granted_scopes: true
});

ตรวจสอบสายที่โทรออกผ่านเครือข่าย

วิธีการตรวจสอบการเรียกเครือข่ายจะแตกต่างกันไปตามประเภทไคลเอ็นต์ของแอปพลิเคชัน

ขณะตรวจสอบการเรียกเครือข่าย ให้มองหาคำขอที่ส่งไปยังปลายทางการให้สิทธิ์ของ OAuth ของ Google และตรวจสอบพารามิเตอร์ scope

ค่าเหล่านี้causeหน้าจอขอความยินยอมสำหรับสิทธิ์แบบละเอียด

  • พารามิเตอร์ scope มีขอบเขตการลงชื่อเข้าใช้และขอบเขตที่ไม่ได้ลงชื่อเข้าใช้

    ตัวอย่างคำขอต่อไปนี้มีขอบเขตการลงชื่อเข้าใช้ทั้ง 3 แบบและขอบเขตที่ไม่ได้ลงชื่อเข้าใช้ 1 รายการเพื่อดูข้อมูลเมตาของไฟล์ Google ไดรฟ์ของผู้ใช้

    https://accounts.google.com/o/oauth2/v2/auth?
    access_type=offline&
    scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.email%20https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.profile%20openid%20https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fdrive.metadata.readonly&
    include_granted_scopes=true&
    response_type=code&
    redirect_uri=YOUR_REDIRECT_URL&
    client_id=YOUR_CLIENT_ID
  • พารามิเตอร์ scope มีขอบเขตที่ไม่ลงชื่อเข้าใช้มากกว่า 1 ขอบเขต

    ตัวอย่างคำขอต่อไปนี้มีขอบเขตการไม่ลงชื่อเข้าใช้ 2 ขอบเขตเพื่อดูข้อมูลเมตา Google ไดรฟ์ของผู้ใช้และจัดการไฟล์ Google ไดรฟ์ที่ต้องการ

  • https://accounts.google.com/o/oauth2/v2/auth?
    access_type=offline&
    scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fdrive.metadata.readonly%20https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fdrive.file&
    include_granted_scopes=true&
    response_type=code&
    redirect_uri=YOUR_REDIRECT_URL&
    client_id=YOUR_CLIENT_ID

แนวทางปฏิบัติแนะนำในการจัดการกับสิทธิ์แบบละเอียด

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

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

อัปเดตแอปพลิเคชันเพื่อจัดการสิทธิ์แบบละเอียด

แอปพลิเคชัน Android

คุณควรอ่านเอกสารประกอบของ SDK ที่คุณใช้เพื่อโต้ตอบกับ Google OAuth 2.0 และอัปเดตแอปพลิเคชันให้จัดการสิทธิ์แบบละเอียดตามแนวทางปฏิบัติแนะนำ

หากใช้ SDK ของ auth.api.signin จากบริการ Google Play เพื่อโต้ตอบกับ Google OAuth 2.0 คุณสามารถใช้ฟังก์ชัน requestPermissions เพื่อขอชุดขอบเขตขนาดเล็กที่สุดที่จำเป็น และใช้ฟังก์ชัน hasPermissions เพื่อตรวจสอบซึ่งกำหนดขอบเขตที่ผู้ใช้ให้สิทธิ์เมื่อขอสิทธิ์แบบละเอียด

แอปพลิเคชันส่วนขยาย Chrome

คุณควรใช้ Chrome Identity API เพื่อใช้งานร่วมกับ Google OAuth 2.0 โดยอิงตามแนวทางปฏิบัติแนะนำ

ตัวอย่างต่อไปนี้แสดงวิธีจัดการสิทธิ์แบบละเอียดอย่างเหมาะสม

manifest.json

ตัวอย่างไฟล์ Manifest ประกาศขอบเขต 2 ขอบเขตที่ไม่มีการลงชื่อเข้าใช้สำหรับแอปพลิเคชันส่วนขยาย Chrome

{
  "name": "Example Chrome extension application",
  ...
  "permissions": [
      "identity"
    ],
  "oauth2" : {
      "client_id": "YOUR_CLIENT_ID",
      "scopes":["https://www.googleapis.com/auth/calendar.readonly",
                "https://www.googleapis.com/auth/contacts.readonly"]
  }
}

แนวทางที่ไม่ถูกต้อง

ทั้งหมดหรือไม่ใช้เลย

ผู้ใช้จะคลิกปุ่มนี้เพื่อเริ่มกระบวนการให้สิทธิ์ ข้อมูลโค้ดนี้จะถือว่าผู้ใช้เห็นหน้าจอขอความยินยอม "ทั้งหมดหรือไม่ยินยอม" สำหรับขอบเขต 2 ขอบเขตที่ระบุไว้ในไฟล์ manifest.json เนื่องจากจะไม่ตรวจสอบขอบเขตที่ผู้ใช้ให้สิทธิ์

oauth.js

...
document.querySelector('button').addEventListener('click', function () {
  chrome.identity.getAuthToken({ interactive: true },
      function (token) {
          if (token === undefined) {
            // User didn't authorize both scopes.
            // Updating the UX and application accordingly
            ...
          } else {
            // User authorized both or one of the scopes.
            // It neglects to check which scopes users granted and assumes users granted all scopes.

            // Calling the APIs, etc.
            ...
          }
      });
});

แนวทางที่ถูกต้อง

ขอบเขตที่เล็กที่สุด

เลือกชุดขอบเขตที่เล็กที่สุดเท่าที่จำเป็น

แอปพลิเคชันควรขอเฉพาะขอบเขตที่น้อยที่สุดเท่าที่จำเป็น เราขอแนะนำให้แอปพลิเคชันส่งคำขอไปทีละ 1 ขอบเขตเมื่อจำเป็นต้องทำงานให้เสร็จสิ้น

ในตัวอย่างนี้ ระบบจะถือว่าขอบเขตทั้ง 2 รายการที่ประกาศในไฟล์ manifest.json เป็นชุดขอบเขตที่เล็กที่สุดเท่าที่จำเป็น ไฟล์ oauth.js ใช้ Chrome Identity API เพื่อเริ่มกระบวนการให้สิทธิ์กับ Google คุณควรเลือกใช้ เปิดใช้สิทธิ์แบบละเอียด เพื่อให้ผู้ใช้ควบคุมการให้สิทธิ์ในแอปพลิเคชันของคุณได้มากขึ้น แอปพลิเคชันควรจัดการคำตอบจากผู้ใช้อย่างเหมาะสมโดยตรวจสอบขอบเขตที่ผู้ใช้ให้สิทธิ์

oauth.js

...
document.querySelector('button').addEventListener('click', function () {
  chrome.identity.getAuthToken({ interactive: true, enableGranularPermissions: true },
      function (token, grantedScopes) {
          if (token === undefined) {
            // User didn't authorize any scope.
            // Updating the UX and application accordingly
            ...
          } else {
            // User authorized the request. Now, check which scopes were granted.
            if (grantedScopes.includes('https://www.googleapis.com/auth/calendar.readonly'))
            {
              // User authorized Calendar read permission.
              // Calling the APIs, etc.
              ...
            }
            else
            {
              // User didn't authorize Calendar read permission.
              // Update UX and application accordingly
              ...
            }

            if (grantedScopes.includes('https://www.googleapis.com/auth/contacts.readonly'))
            {
              // User authorized Contacts read permission.
              // Calling the APIs, etc.
              ...
            }
            else
            {
              // User didn't authorize Contacts read permission.
              // Update UX and application accordingly
              ...
            }
          }
      });
});

แอปพลิเคชัน iOS, iPadOS และ macOS

คุณควรอ่านเอกสารประกอบของ SDK ที่คุณใช้เพื่อโต้ตอบกับ Google OAuth 2.0 และอัปเดตแอปพลิเคชันให้จัดการสิทธิ์แบบละเอียดตามแนวทางปฏิบัติแนะนำ

หากใช้ไลบรารี Google Sign-In สำหรับ iOS และ macOS เพื่อโต้ตอบกับ Google OAuth 2.0 คุณควรอ่านเอกสารประกอบเกี่ยวกับการจัดการสิทธิ์โดยละเอียด

เว็บแอปพลิเคชัน

คุณควรอ่านเอกสารประกอบของ SDK ที่คุณใช้เพื่อโต้ตอบกับ Google OAuth 2.0 และอัปเดตแอปพลิเคชันให้จัดการสิทธิ์แบบละเอียดตามแนวทางปฏิบัติแนะนำ

การเข้าถึงฝั่งเซิร์ฟเวอร์ (ออฟไลน์)

โหมดการเข้าถึงฝั่งเซิร์ฟเวอร์ (ออฟไลน์) กำหนดให้คุณดำเนินการต่อไปนี้
  • ยืนเซิร์ฟเวอร์และกำหนดปลายทางที่เข้าถึงได้แบบสาธารณะเพื่อรับรหัสการให้สิทธิ์
  • กำหนดค่า URI การเปลี่ยนเส้นทาง ของปลายทางสาธารณะใน Credentials page คอนโซล Google Cloud

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

แนวทางที่ไม่ถูกต้อง

ทั้งหมดหรือไม่ใช้เลย

ผู้ใช้จะถูกเปลี่ยนเส้นทางไปยัง URL การให้สิทธิ์ ข้อมูลโค้ดจะถือว่าผู้ใช้เห็นหน้าจอคำยินยอม "ทั้งหมดหรือไม่ยินยอม" สำหรับขอบเขต 2 ขอบเขตที่ระบุไว้ในเขต scopes เนื่องจากจะไม่ตรวจสอบขอบเขตที่ผู้ใช้ให้สิทธิ์

main.js

...
const oauth2Client = new google.auth.OAuth2(
  YOUR_CLIENT_ID,
  YOUR_CLIENT_SECRET,
  YOUR_REDIRECT_URL
);

// Access scopes for two non-Sign-In scopes - Google Calendar and Contacts
const scopes = [
  'https://www.googleapis.com/auth/contacts.readonly',
  'https://www.googleapis.com/auth/calendar.readonly'
];

// Generate a url that asks permissions for the Google Calendar and Contacts scopes
const authorizationUrl = oauth2Client.generateAuthUrl({
  // 'online' (default) or 'offline' (gets refresh_token)
  access_type: 'offline',
  // Pass in the scopes array defined above
  scope: scopes,
  // Enable incremental authorization. Recommended as best practices.
  include_granted_scopes: true
});

async function main() {
  const server = http.createServer(async function (req, res) {
    // Example on redirecting user to Google OAuth 2.0 server.
    if (req.url == '/') {
      res.writeHead(301, { "Location": authorizationUrl });
    }
    // Receive the callback from Google OAuth 2.0 server.
    if (req.url.startsWith('/oauth2callback')) {
      // Handle the Google OAuth 2.0 server response
      let q = url.parse(req.url, true).query;

      if (q.error) {
        // User didn't authorize both scopes.
        // Updating the UX and application accordingly
        ...
      } else {
        // User authorized both or one of the scopes.
        // It neglects to check which scopes users granted and assumes users granted all scopes.

        // Get access and refresh tokens (if access_type is offline)
        let { tokens } = await oauth2Client.getToken(q.code);
        // Calling the APIs, etc.
        ...
      }
    }
    res.end();
  }).listen(80);
}
แนวทางที่ถูกต้อง

ขอบเขตที่เล็กที่สุด

เลือกชุดขอบเขตที่เล็กที่สุดเท่าที่จำเป็น

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

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

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

main.js

...
const oauth2Client = new google.auth.OAuth2(
  YOUR_CLIENT_ID,
  YOUR_CLIENT_SECRET,
  YOUR_REDIRECT_URL
);

// Access scopes for two non-Sign-In scopes - Google Calendar and Contacts
const scopes = [
  'https://www.googleapis.com/auth/contacts.readonly',
  'https://www.googleapis.com/auth/calendar.readonly'
];

// Generate a url that asks permissions for the Google Calendar and Contacts scopes
const authorizationUrl = oauth2Client.generateAuthUrl({
  // 'online' (default) or 'offline' (gets refresh_token)
  access_type: 'offline',
  // Pass in the scopes array defined above
  scope: scopes,
  // Enable incremental authorization. Recommended as best practices.
  include_granted_scopes: true,
  // Set to true to enable more granular permissions for Google OAuth 2.0 client IDs created before 2019.
  // No effect for newer Google OAuth 2.0 client IDs, since more granular permissions is always enabled for them.
  enable_granular_consent: true
});

async function main() {
  const server = http.createServer(async function (req, res) {
    // Redirect users to Google OAuth 2.0 server.
    if (req.url == '/') {
      res.writeHead(301, { "Location": authorizationUrl });
    }
    // Receive the callback from Google OAuth 2.0 server.
    if (req.url.startsWith('/oauth2callback')) {
      // Handle the Google OAuth 2.0 server response
      let q = url.parse(req.url, true).query;

      if (q.error) {
        // User didn't authorize both scopes.
        // Updating the UX and application accordingly
        ...
      } else {
        // Get access and refresh tokens (if access_type is offline)
        let { tokens } = await oauth2Client.getToken(q.code);
        oauth2Client.setCredentials(tokens);

        // User authorized the request. Now, check which scopes were granted.
        if (tokens.scope.includes('https://www.googleapis.com/auth/calendar.readonly'))
        {
          // User authorized Calendar read permission.
          // Calling the APIs, etc.
          ...
        }
        else
        {
          // User didn't authorize Calendar read permission.
          // Calling the APIs, etc.
          ...
        }

        // Check which scopes user granted the permission to application
        if (tokens.scope.includes('https://www.googleapis.com/auth/contacts.readonly'))
        {
          // User authorized Contacts read permission.
          // Calling the APIs, etc.
          ...
        }
        else
        {
          // User didn't authorize Contacts read permission.
          // Update UX and application accordingly
          ...
        }
      }
    }
    res.end();
  }).listen(80);
}

อ่าน คำแนะนำของเว็บแอปฝั่งเซิร์ฟเวอร์เกี่ยวกับวิธีเข้าถึง Google APIs จากแอปพลิเคชันบนเซิร์ฟเวอร์

การเข้าถึงฝั่งไคลเอ็นต์เท่านั้น

  • สำหรับแอปพลิเคชันที่ใช้ไลบรารี JavaScript ของ Google Identity Services เพื่อโต้ตอบกับ Google OAuth 2.0 คุณควรอ่านเอกสารประกอบนี้เกี่ยวกับการจัดการสิทธิ์โดยละเอียด
  • สำหรับแอปพลิเคชันที่มีการเรียกโดยใช้ JavaScript ไปยังปลายทางการให้สิทธิ์ของ Google OAuth 2.0 โดยตรง คุณควรอ่านเอกสารประกอบนี้เกี่ยวกับการจัดการสิทธิ์แบบละเอียด

ทดสอบแอปพลิเคชันที่อัปเดตแล้วเกี่ยวกับการจัดการสิทธิ์แบบละเอียด

  1. Outline สำหรับทุกกรณีที่ผู้ใช้ตอบสนองต่อคำขอสิทธิ์และลักษณะการทำงานที่คาดไว้จากแอปพลิเคชันของคุณได้ เช่น หากผู้ใช้ให้สิทธิ์เพียง 2 ใน 3 ขอบเขตที่ขอ แอปพลิเคชันก็ควรจะทำงานตามนั้น
  2. ทดสอบแอปพลิเคชันที่เปิดใช้สิทธิ์แบบละเอียด การเปิดใช้สิทธิ์แบบละเอียดมี 2 วิธีดังนี้
    1. ตรวจสอบหน้าจอความยินยอม OAuth 2.0 ของแอปพลิเคชันเพื่อดูว่าได้เปิดใช้สิทธิ์แบบละเอียดสำหรับแอปพลิเคชันแล้วหรือยัง นอกจากนี้ คุณยังสร้างรหัสไคลเอ็นต์ Google OAuth 2.0 สำหรับเว็บ, Android หรือ iOS ใหม่ผ่านคอนโซล Google Cloud เพื่อวัตถุประสงค์ในการทดสอบได้ด้วย เนื่องจากสิทธิ์แบบละเอียดจะเปิดใช้อยู่เสมอ
    2. ตั้งค่าพารามิเตอร์ enable_granular_consent เป็น true เมื่อเรียกใช้ ปลายทางการให้สิทธิ์ของ Google OAuth SDK บางรายการมีการรองรับพารามิเตอร์นี้อย่างชัดแจ้ง สำหรับแหล่งข้อมูลอื่นๆ โปรดดูเอกสารประกอบเพื่อดูวิธีที่คุณจะเพิ่มพารามิเตอร์นี้และค่าด้วยตนเอง หากการใช้งานของคุณไม่รองรับการเพิ่มพารามิเตอร์ คุณจะสร้างรหัสไคลเอ็นต์ Google OAuth 2.0 สำหรับเว็บ, Android หรือ iOS ใหม่ได้ผ่านคอนโซล Google Cloud เพื่อวัตถุประสงค์ในการทดสอบเท่านั้นตามที่ระบุไว้ในประเด็นก่อนหน้านี้