การใช้โมเดลโทเค็น

ไลบรารี JavaScript ของ google.accounts.oauth2 ช่วยให้คุณแจ้งขอความยินยอมจากผู้ใช้และรับโทเค็นเพื่อการเข้าถึงเพื่อทำงานกับข้อมูลผู้ใช้ โดยอิงตามขั้นตอนการให้สิทธิ์โดยนัย OAuth 2.0 และออกแบบมาเพื่อให้คุณสามารถเรียก Google API ได้โดยตรงโดยใช้ REST และ CORS หรือใช้ไลบรารีของไคลเอ็นต์ Google APIs สำหรับ JavaScript (หรือที่เรียกว่า gapi.client) เพื่อการเข้าถึง API ที่ซับซ้อนกว่าได้โดยง่าย

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

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

เราขอแนะนำให้คุณทำตามแนวทางที่ระบุไว้ในที่นี้แทนเทคนิคที่ระบุไว้ในคู่มือ OAuth 2.0 สำหรับเว็บแอปพลิเคชันฝั่งไคลเอ็นต์แบบเก่า

ตั้งค่า

ค้นหาหรือสร้างรหัสไคลเอ็นต์โดยทำตามขั้นตอนที่อธิบายไว้ในคู่มือรับรหัสไคลเอ็นต์ Google API ถัดไป ให้เพิ่มไลบรารีของไคลเอ็นต์ลงในหน้าในเว็บไซต์ที่จะเรียกใช้ Google APIs สุดท้าย ให้เริ่มต้นไคลเอ็นต์โทเค็น โดยทั่วไปจะดำเนินการภายในเครื่องจัดการ onload ของไลบรารีของไคลเอ็นต์

เริ่มต้นไคลเอ็นต์โทเค็น

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

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

ทริกเกอร์โฟลว์โทเค็น OAuth 2.0

ใช้เมธอด requestAccessToken() เพื่อทริกเกอร์โฟลว์ UX ของโทเค็นและรับโทเค็นเพื่อการเข้าถึง Google แจ้งให้ผู้ใช้ดำเนินการดังนี้

  • เลือกบัญชี
  • ลงชื่อเข้าใช้บัญชี Google หากยังไม่ได้ลงชื่อเข้าใช้
  • ยินยอมให้เว็บแอปเข้าถึงขอบเขตที่ขอแต่ละรายการ

ท่าทางสัมผัสของผู้ใช้จะทริกเกอร์โฟลว์โทเค็น: <button onclick="client.requestAccessToken();">Authorize me</button>

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

ผู้ใช้อาจปิดตัวเลือกบัญชีผู้ใช้หรือหน้าต่างลงชื่อเข้าใช้ ซึ่งในกรณีนี้ระบบจะไม่เรียกใช้ฟังก์ชันเรียกกลับ

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

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

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

การให้สิทธิ์ส่วนเพิ่ม

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

  • แอป Ajax แบบหน้าเดียว ซึ่งมักจะใช้ XMLHttpRequest พร้อมการเข้าถึงทรัพยากรแบบไดนามิก
  • หน้าเว็บหลายหน้าและทรัพยากรต่างๆ แยกกันและจัดการในแต่ละหน้า

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

อาแจ๊กซ์

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

แอป Ajax
เริ่มต้นไคลเอ็นต์โทเค็นเมื่อโหลดหน้าเว็บ
        const client = google.accounts.oauth2.initTokenClient({
          client_id: 'YOUR_GOOGLE_CLIENT_ID',
          callback: "onTokenResponse",
        });
      
ขอความยินยอมและรับโทเค็นเพื่อการเข้าถึงผ่านท่าทางสัมผัสของผู้ใช้ คลิก "+" เพื่อเปิด

เอกสารที่จะอ่าน

แสดงเอกสารล่าสุด

          client.requestAccessToken(
            overrideConfig = ({
               scope = 'https://www.googleapis.com/auth/documents.readonly'
             })
           );
        

กิจกรรมที่กำลังจะมาถึง

แสดงข้อมูลปฏิทิน

          client.requestAccessToken(
            overrideConfig = ({
               scope = 'https://www.googleapis.com/auth/calendar.readonly'
             })
           );
        

แสดงรูปภาพ

          client.requestAccessToken(
            overrideConfig = ({
               scope = 'https://www.googleapis.com/auth/photoslibrary.readonly'
             })
           );
        

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

หน้าเว็บหลายหน้า

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

แอปแบบหลายหน้า
หน้าเว็บ รหัส
หน้า 1. เอกสารที่จะอ่าน
  const client = google.accounts.oauth2.initTokenClient({
    client_id: 'YOUR_GOOGLE_CLIENT_ID',
    callback: "onTokenResponse",
    scope: 'https://www.googleapis.com/auth/documents.readonly',
  });
  client.requestAccessToken();
          
หน้า 2. กิจกรรมที่กำลังจะมีขึ้น
  const client = google.accounts.oauth2.initTokenClient({
    client_id: 'YOUR_GOOGLE_CLIENT_ID',
    callback: "onTokenResponse",
    scope: 'https://www.googleapis.com/auth/calendar.readonly',
  });
  client.requestAccessToken();
          
หน้า 3. ภาพสไลด์
  const client = google.accounts.oauth2.initTokenClient({
    client_id: 'YOUR_GOOGLE_CLIENT_ID',
    callback: "onTokenResponse",
    scope: 'https://www.googleapis.com/auth/photoslibrary.readonly',
  });
  client.requestAccessToken();
          

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

สิทธิ์แบบละเอียด

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

const client = google.accounts.oauth2.initTokenClient({
  client_id: 'YOUR_GOOGLE_CLIENT_ID',
  scope: 'https://www.googleapis.com/auth/calendar.readonly \
          https://www.googleapis.com/auth/documents.readonly \
          https://www.googleapis.com/auth/photoslibrary.readonly',
  callback: (tokenResponse) => {
    if (tokenResponse && tokenResponse.access_token) {
      if (google.accounts.oauth2.hasGrantedAnyScope(tokenResponse,
          'https://www.googleapis.com/auth/photoslibrary.readonly')) {
        // Look at pictures
        ...
      }
      if (google.accounts.oauth2.hasGrantedAllScopes(tokenResponse,
          'https://www.googleapis.com/auth/calendar.readonly',
          'https://www.googleapis.com/auth/documents.readonly')) {
        // Meeting planning and review documents
        ...
      }
    }
  },
});

การให้สิทธิ์ที่ยอมรับก่อนหน้าจากเซสชันหรือคำขอก่อนหน้าจะรวมอยู่ในคำตอบด้วย บันทึกความยินยอมของผู้ใช้จะเก็บรักษาไว้ต่อผู้ใช้และรหัสลูกค้า และยังคงอยู่ในการเรียก initTokenClient() หรือ requestAccessToken() หลายครั้ง โดยค่าเริ่มต้น ผู้ใช้จำเป็นต้องขอคำยินยอมเฉพาะในครั้งแรกที่ผู้ใช้เข้าชมเว็บไซต์และขอขอบเขตใหม่ แต่อาจมีการขอในการโหลดหน้าเว็บแต่ละครั้งโดยใช้ prompt=consent ในออบเจ็กต์การกำหนดค่าไคลเอ็นต์โทเค็น

การใช้งานโทเค็น

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

การใช้ REST และ CORS กับ Google API

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

ในตัวอย่างนี้ ให้ดูกิจกรรมในปฏิทินที่กำลังจะมีขึ้นของผู้ใช้ที่ลงชื่อเข้าใช้โดยใช้โทเค็นเพื่อการเข้าถึงที่ tokenRequest() แสดงผล

var xhr = new XMLHttpRequest();
xhr.open('GET', 'https://www.googleapis.com/calendar/v3/calendars/primary/events');
xhr.setRequestHeader('Authorization', 'Bearer ' + tokenResponse.access_token);
xhr.send();

โปรดดูข้อมูลเพิ่มเติมในวิธีใช้ CORS เพื่อเข้าถึง Google API

ในส่วนถัดไปจะอธิบายถึงวิธีการผสานรวมกับ API ที่ซับซ้อนมากขึ้นได้อย่างง่ายดาย

การทำงานกับไลบรารี JavaScript ของ Google APIs

ไคลเอ็นต์โทเค็นจะทำงานร่วมกับไลบรารีของไคลเอ็นต์ Google API สำหรับ JavaScript ดูข้อมูลโค้ดด้านล่าง

const client = google.accounts.oauth2.initTokenClient({
  client_id: 'YOUR_GOOGLE_CLIENT_ID',
  scope: 'https://www.googleapis.com/auth/calendar.readonly',
  callback: (tokenResponse) => {
    if (tokenResponse && tokenResponse.access_token) {
      gapi.client.setApiKey('YOUR_API_KEY');
      gapi.client.load('calendar', 'v3', listUpcomingEvents);
    }
  },
});

function listUpcomingEvents() {
  gapi.client.calendar.events.list(...);
}

การหมดอายุของโทเค็น

โทเค็นเพื่อการเข้าถึงมีอายุการใช้งานสั้น หากโทเค็นเพื่อการเข้าถึงหมดอายุก่อนสิ้นสุดเซสชันของผู้ใช้ ให้รับโทเค็นใหม่โดยเรียกใช้ requestAccessToken() จากเหตุการณ์ที่ผู้ใช้ขับเคลื่อน เช่น การกดปุ่ม

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

google.accounts.oauth2.revoke('414a76cb127a7ece7ee4bf287602ca2b56f8fcbf7fcecc2cd4e0509268120bd7', done => {
    console.log(done);
    console.log(done.successful);
    console.log(done.error);
    console.log(done.error_description);
  });