ย้ายข้อมูลไปยังบริการ Google Identity

ภาพรวม

หากต้องการรับโทเค็นการเข้าถึงต่อผู้ใช้เพื่อเรียกใช้ Google API ทาง Google มีไลบรารี JavaScript หลายรายการดังนี้

คู่มือนี้จะอธิบายวิธีย้ายข้อมูลจากไลบรารีเหล่านี้ไปยังไลบรารี Google Identity Services

เมื่อทำตามคู่มือนี้ คุณจะทำสิ่งต่อไปนี้ได้

  • แทนที่ไลบรารี Platform ที่เลิกใช้งานแล้วด้วยไลบรารีบริการข้อมูลประจำตัว และ
  • หากใช้ไลบรารีของไคลเอ็นต์ API ให้นําโมดูล gapi.auth2 ที่เลิกใช้งานออก รวมถึงเมธอดและออบเจ็กต์ของโมดูลนั้น แล้วแทนที่ด้วยรายการที่เทียบเท่าของ Identity Services

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

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

ระบุขั้นตอนการให้สิทธิ์

ขั้นตอนการให้สิทธิ์ผู้ใช้มี 2 รูปแบบ ได้แก่ Implicit และ Authorization Code

ตรวจสอบเว็บแอปเพื่อระบุประเภทของขั้นตอนการให้สิทธิ์ที่ใช้อยู่ในปัจจุบัน

สัญญาณที่บ่งบอกว่าเว็บแอปของคุณใช้ขั้นตอนที่นัยยะ

ตัวบ่งชี้ที่เว็บแอปใช้ขั้นตอนรหัสการให้สิทธิ์

  • การติดตั้งใช้งานจะอิงตามปัจจัยต่อไปนี้

  • แอปของคุณจะทำงานทั้งในเบราว์เซอร์ของผู้ใช้และในแพลตฟอร์มแบ็กเอนด์

  • แพลตฟอร์มแบ็กเอนด์โฮสต์ปลายทางของรหัสการให้สิทธิ์

  • แพลตฟอร์มแบ็กเอนด์จะเรียกใช้ Google API ในนามของผู้ใช้โดยไม่ต้องให้ผู้ใช้อยู่ด้วย หรือที่เรียกว่าโหมดออฟไลน์

  • แพลตฟอร์มแบ็กเอนด์จะจัดการและจัดเก็บโทเค็นรีเฟรช

ในบางกรณี โค้ดเบสของคุณอาจรองรับทั้ง 2 ขั้นตอน

เลือกขั้นตอนการให้สิทธิ์

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

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

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

เลือกขั้นตอนการให้สิทธิ์โดยใช้ตัวเลือกด้านล่าง

ขั้นตอนการให้สิทธิ์โดยนัย

รับโทเค็นการเข้าถึงเพื่อใช้ในเบราว์เซอร์ขณะที่ผู้ใช้อยู่

ตัวอย่างโฟลว์โดยนัยแสดงเว็บแอปก่อนและหลังการย้ายข้อมูลไปยังบริการระบุตัวตน

ขั้นตอนสำหรับรหัสการให้สิทธิ์

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

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

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

การเปลี่ยนแปลงในเว็บแอปในเบราว์เซอร์

ส่วนนี้จะตรวจสอบการเปลี่ยนแปลงที่คุณจะทำกับเว็บแอปในเบราว์เซอร์เมื่อย้ายข้อมูลไปยังไลบรารี JavaScript ของ Google Identity Services

การระบุโค้ดที่ได้รับผลกระทบและการทดสอบ

คุกกี้แก้ไขข้อบกพร่องจะช่วยค้นหาโค้ดที่ได้รับผลกระทบและทดสอบลักษณะการทํางานหลังการเลิกใช้งาน

ในแอปขนาดใหญ่หรือซับซ้อน คุณอาจหาโค้ดทั้งหมดที่ได้รับผลกระทบจากการเลิกใช้งานโมดูล gapi.auth2 ได้ยาก หากต้องการบันทึกการใช้งานที่มีอยู่ของฟังก์ชันการทำงานที่กำลังจะเลิกใช้งานลงในคอนโซล ให้ตั้งค่าคุกกี้ G_AUTH2_MIGRATION เป็น informational (ไม่บังคับ) เพิ่มโคลอนตามด้วยค่าคีย์เพื่อบันทึกลงในพื้นที่เก็บข้อมูลเซสชันด้วย หลังจากลงชื่อเข้าใช้และได้รับข้อมูลเข้าสู่ระบบแล้ว ให้ตรวจสอบหรือส่งบันทึกที่รวบรวมไปยังแบ็กเอนด์เพื่อการวิเคราะห์ในภายหลัง เช่น informational:showauth2use จะบันทึกต้นทางและ URL ลงในคีย์พื้นที่เก็บข้อมูลเซสชันชื่อ showauth2use

หากต้องการยืนยันลักษณะการทำงานของแอปเมื่อโมดูล gapi.auth2 ไม่โหลดอีกต่อไป ให้ตั้งค่าของคุกกี้ G_AUTH2_MIGRATION เป็น enforced ซึ่งจะช่วยให้ทดสอบลักษณะการทํางานหลังการเลิกใช้งานได้ก่อนถึงวันที่บังคับใช้

ค่าคุกกี้ G_AUTH2_MIGRATION ที่เป็นไปได้

  • enforced อย่าโหลดโมดูล gapi.auth2
  • informational บันทึกการใช้ฟังก์ชันการทำงานที่เลิกใช้งานแล้วลงในคอนโซล JS และบันทึกลงในพื้นที่เก็บข้อมูลเซสชันด้วยเมื่อตั้งค่าชื่อคีย์ที่ไม่บังคับ ดังนี้ informational:key-name

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

ไลบรารีและโมดูล

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

เพิ่มไลบรารีบริการระบุตัวตนลงในเว็บแอปโดยใส่ไว้ในเอกสาร

<script src="https://accounts.google.com/gsi/client" async defer></script>

นําอินสแตนซ์ของการโหลดโมดูล auth2 โดยใช้ gapi.load('auth2', function) ออก

ไลบรารี Google Identity Services จะแทนที่การใช้งานโมดูล gapi.auth2 คุณใช้โมดูล gapi.client จากไลบรารีของไคลเอ็นต์ Google API สำหรับ JavaScript ได้ต่อไปอย่างปลอดภัย และใช้ประโยชน์จากการสร้างเมธอด JS ที่เรียกใช้ได้โดยอัตโนมัติจากเอกสารการค้นพบ การเรียก API หลายรายการพร้อมกัน และฟังก์ชันการจัดการ CORS

คุกกี้

การให้สิทธิ์ผู้ใช้ไม่จำเป็นต้องใช้คุกกี้

ดูการย้ายข้อมูลจาก Google Sign-In สำหรับรายละเอียดเกี่ยวกับวิธีที่การตรวจสอบสิทธิ์ผู้ใช้ใช้คุกกี้ และวิธีที่ Google ใช้คุกกี้สำหรับผลิตภัณฑ์และบริการอื่นๆ ของ Google เพื่อใช้คุกกี้

ข้อมูลเข้าสู่ระบบ

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

หากต้องการดูการเปลี่ยนแปลงเหล่านี้ โปรดดูตัวอย่างข้อมูลเข้าสู่ระบบ

ขั้นตอนการให้สิทธิ์โดยนัย

แยกการตรวจสอบสิทธิ์และการให้สิทธิ์ของผู้ใช้โดยนำการจัดการโปรไฟล์ผู้ใช้ออกจากขั้นตอนการให้สิทธิ์

นําการอ้างอิงไคลเอ็นต์ JavaScript ของ Google Sign-In เหล่านี้ออก

เมธอด

  • GoogleUser.getBasicProfile()
  • GoogleUser.getId()

ขั้นตอนสำหรับรหัสการให้สิทธิ์

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

สถานะเซสชัน

ก่อนหน้านี้ Google Sign-In ช่วยคุณจัดการสถานะการลงชื่อเข้าใช้ของผู้ใช้โดยใช้สิ่งต่อไปนี้

คุณมีหน้าที่รับผิดชอบในการจัดการสถานะการลงชื่อเข้าใช้และเซสชันของผู้ใช้เว็บแอป

นําการอ้างอิงไคลเอ็นต์ JavaScript ของ Google Sign-In เหล่านี้ออก

วัตถุ

  • gapi.auth2.SignInOptions

วิธีการ

  • GoogleAuth.attachClickHandler()
  • GoogleAuth.isSignedIn()
  • GoogleAuth.isSignedIn.get()
  • GoogleAuth.isSignedIn.listen()
  • GoogleAuth.signIn()
  • GoogleAuth.signOut()
  • GoogleAuth.currentUser.get()
  • GoogleAuth.currentUser.listen()
  • GoogleUser.isSignedIn()

การกำหนดค่าไคลเอ็นต์

อัปเดตเว็บแอปเพื่อเริ่มต้นไคลเอ็นต์โทเค็นสำหรับขั้นตอนการขอสิทธิ์แบบนัยหรือแบบรหัส

นําการอ้างอิงไคลเอ็นต์ JavaScript ของ Google Sign-In เหล่านี้ออก

วัตถุ

  • gapi.auth2.ClientConfig
  • gapi.auth2.OfflineAccessOptions

วิธีการ

  • gapi.auth2.getAuthInstance()
  • GoogleUser.grant()

ขั้นตอนการให้สิทธิ์โดยนัย

เพิ่มออบเจ็กต์ TokenClientConfig และเรียกใช้ initTokenClient() เพื่อกำหนดค่าเว็บแอปตามตัวอย่างในเริ่มต้นใช้งานไคลเอ็นต์โทเค็น

แทนที่ การอ้างอิงไคลเอ็นต์ JavaScript ของ Google Sign-In ด้วย Google Identity Services

วัตถุ:

  • จำนวนเงิน gapi.auth2.AuthorizeConfig ด้วยบัตร TokenClientConfig

วิธีการ:

  • จำนวนเงิน gapi.auth2.init() ด้วยบัตร google.accounts.oauth2.initTokenClient()

พารามิเตอร์ ได้แก่

  • gapi.auth2.AuthorizeConfig.login_hint ที่มี TokenClientConfig.login_hint
  • gapi.auth2.GoogleUser.getHostedDomain() ที่มี TokenClientConfig.hd

ขั้นตอนรหัสการให้สิทธิ์

เพิ่มออบเจ็กต์ CodeClientConfig และการเรียก initCodeClient() เพื่อกำหนดค่าเว็บแอป ตามตัวอย่างในเริ่มต้นไคลเอ็นต์โค้ด

เมื่อเปลี่ยนจากขั้นตอนแบบนัยเป็นขั้นตอนรหัสการให้สิทธิ์ ให้ทำดังนี้

นำ ข้อมูลอ้างอิงไคลเอ็นต์ JavaScript ของ Google Sign-In ออก

วัตถุ

  • gapi.auth2.AuthorizeConfig

วิธีการ

  • gapi.auth2.init()

พารามิเตอร์ ได้แก่

  • gapi.auth2.AuthorizeConfig.login_hint
  • gapi.auth2.GoogleUser.getHostedDomain()

คำขอโทเค็น

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

ขั้นตอนการให้สิทธิ์โดยนัย

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

แทนที่ การอ้างอิงไคลเอ็นต์ JavaScript ของ Google Sign-In ด้วย Google Identity Services

วิธีการ

  • จำนวนเงิน gapi.auth2.authorize() ด้วยบัตร TokenClient.requestAccessToken()
  • GoogleUser.reloadAuthResponse() ที่มี TokenClient.requestAccessToken()

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

อัปเดตโค้ดเบสเป็นเวอร์ชันต่อไปนี้

  • ทริกเกอร์ขั้นตอนโทเค็น OAuth 2.0 ด้วย requestAccessToken()
  • รองรับการให้สิทธิ์เพิ่มขึ้นโดยใช้ requestAccessToken และ OverridableTokenClientConfig ในการแยกคำขอ 1 รายการสำหรับหลายขอบเขตออกเป็นคำขอขนาดเล็กหลายคำขอ
  • ขอโทเค็นใหม่เมื่อโทเค็นที่มีอยู่หมดอายุหรือถูกเพิกถอน

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

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

ขั้นตอนรหัสการให้สิทธิ์

เพิ่มลิงก์หรือปุ่มเพื่อเรียกใช้ requestCode() เพื่อขอรหัสการให้สิทธิ์จาก Google ดูตัวอย่างได้ที่ทริกเกอร์โฟลว์รหัส OAuth 2.0

ดูข้อมูลเพิ่มเติมเกี่ยวกับวิธีจัดการโทเค็นที่หมดอายุหรือถูกเพิกถอนได้ที่ส่วนการจัดการโทเค็นด้านล่าง

การจัดการโทเค็น

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

Google APIs จะแสดงรหัสสถานะ HTTP 401 Unauthorized และข้อความแสดงข้อผิดพลาด invalid_token เมื่อใช้โทเค็นการเข้าถึงที่หมดอายุหรือถูกเพิกถอน ดูตัวอย่างได้ที่การตอบกลับโทเค็นไม่ถูกต้อง

โทเค็นที่หมดอายุ

โทเค็นเพื่อการเข้าถึงมีอายุสั้นและมักจะใช้งานได้ภายในไม่กี่นาที

การเพิกถอนโทเค็น

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

แทนที่ การอ้างอิงไคลเอ็นต์ JavaScript ของ Google Sign-In: ด้วย Google Identity Services:

วิธีการ

  • จำนวนเงิน getAuthInstance().disconnect() ด้วยบัตร google.accounts.oauth2.revoke()
  • จำนวนเงิน GoogleUser.disconnect() ด้วยบัตร google.accounts.oauth2.revoke()

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

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

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

การลงชื่อเข้าใช้ของผู้ใช้

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

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

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

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

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

ขั้นตอนการให้สิทธิ์โดยนัย

แทนที่ การอ้างอิงไคลเอ็นต์ JavaScript ของ Google Sign-In ด้วย Google Identity Services

วัตถุ

  • จำนวนเงิน gapi.auth2.AuthorizeResponse ด้วยบัตร TokenClient.TokenResponse
  • จำนวนเงิน gapi.auth2.AuthResponse ด้วยบัตร TokenClient.TokenResponse

วิธีการ

  • GoogleUser.hasGrantedScopes() ที่มี google.accounts.oauth2.hasGrantedAllScopes()
  • GoogleUser.getGrantedScopes() ที่มี google.accounts.oauth2.hasGrantedAllScopes()

นํา การอ้างอิงไคลเอ็นต์ JavaScript ของ Google Sign-In ออก

วิธีการ

  • GoogleUser.getAuthResponse()

อัปเดตเว็บแอปด้วย hasGrantedAllScopes() และ hasGrantedAnyScope() โดยทําตามตัวอย่างสิทธิ์แบบละเอียดนี้

ขั้นตอนรหัสการให้สิทธิ์

อัปเดตหรือเพิ่มปลายทางของรหัสการให้สิทธิ์ลงในแพลตฟอร์มแบ็กเอนด์โดยทําตามวิธีการในการจัดการรหัสการให้สิทธิ์

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

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

ตัวอย่างโฟลว์แบบไม่เจาะจงปลายทาง

วิถีเดิม

ไลบรารีของไคลเอ็นต์ GAPI

ตัวอย่างไลบรารีของไคลเอ็นต์ Google API สําหรับ JavaScript ที่ทํางานในเบราว์เซอร์โดยใช้กล่องโต้ตอบแบบป๊อปอัปสําหรับความยินยอมของผู้ใช้

gapi.auth2จะโหลดและใช้งานโดย gapi.client.init() โดยอัตโนมัติ จึงซ่อนอยู่

<!DOCTYPE html>
  <html>
    <head>
      <script src="https://apis.google.com/js/api.js"></script>
      <script>
        function start() {
          gapi.client.init({
            'apiKey': 'YOUR_API_KEY',
            'clientId': 'YOUR_CLIENT_ID',
            'scope': 'https://www.googleapis.com/auth/cloud-translation',
            'discoveryDocs': ['https://www.googleapis.com/discovery/v1/apis/translate/v2/rest'],
          }).then(function() {
            // Execute an API request which is returned as a Promise.
            // The method name language.translations.list comes from the API discovery.
            return gapi.client.language.translations.list({
              q: 'hello world',
              source: 'en',
              target: 'de',
            });
          }).then(function(response) {
            console.log(response.result.data.translations[0].translatedText);
          }, function(reason) {
            console.log('Error: ' + reason.result.error.message);
          });
        };

        // Load the JavaScript client library and invoke start afterwards.
        gapi.load('client', start);
      </script>
    </head>
    <body>
      <div id="results"></div>
    </body>
  </html>

ไลบรารีของไคลเอ็นต์ JS

OAuth 2.0 สําหรับเว็บแอปพลิเคชันฝั่งไคลเอ็นต์ที่ทํางานในเบราว์เซอร์โดยใช้กล่องโต้ตอบแบบป๊อปอัปสําหรับความยินยอมของผู้ใช้

โหลดโมดูล gapi.auth2 ด้วยตนเอง

<!DOCTYPE html>
<html><head></head><body>
<script>
  var GoogleAuth;
  var SCOPE = 'https://www.googleapis.com/auth/drive.metadata.readonly';
  function handleClientLoad() {
    // Load the API's client and auth2 modules.
    // Call the initClient function after the modules load.
    gapi.load('client:auth2', initClient);
  }

  function initClient() {
    // In practice, your app can retrieve one or more discovery documents.
    var discoveryUrl = 'https://www.googleapis.com/discovery/v1/apis/drive/v3/rest';

    // Initialize the gapi.client object, which app uses to make API requests.
    // Get API key and client ID from API Console.
    // 'scope' field specifies space-delimited list of access scopes.
    gapi.client.init({
        'apiKey': 'YOUR_API_KEY',
        'clientId': 'YOUR_CLIENT_ID',
        'discoveryDocs': [discoveryUrl],
        'scope': SCOPE
    }).then(function () {
      GoogleAuth = gapi.auth2.getAuthInstance();

      // Listen for sign-in state changes.
      GoogleAuth.isSignedIn.listen(updateSigninStatus);

      // Handle initial sign-in state. (Determine if user is already signed in.)
      var user = GoogleAuth.currentUser.get();
      setSigninStatus();

      // Call handleAuthClick function when user clicks on
      //      "Sign In/Authorize" button.
      $('#sign-in-or-out-button').click(function() {
        handleAuthClick();
      });
      $('#revoke-access-button').click(function() {
        revokeAccess();
      });
    });
  }

  function handleAuthClick() {
    if (GoogleAuth.isSignedIn.get()) {
      // User is authorized and has clicked "Sign out" button.
      GoogleAuth.signOut();
    } else {
      // User is not signed in. Start Google auth flow.
      GoogleAuth.signIn();
    }
  }

  function revokeAccess() {
    GoogleAuth.disconnect();
  }

  function setSigninStatus() {
    var user = GoogleAuth.currentUser.get();
    var isAuthorized = user.hasGrantedScopes(SCOPE);
    if (isAuthorized) {
      $('#sign-in-or-out-button').html('Sign out');
      $('#revoke-access-button').css('display', 'inline-block');
      $('#auth-status').html('You are currently signed in and have granted ' +
          'access to this app.');
    } else {
      $('#sign-in-or-out-button').html('Sign In/Authorize');
      $('#revoke-access-button').css('display', 'none');
      $('#auth-status').html('You have not authorized this app or you are ' +
          'signed out.');
    }
  }

  function updateSigninStatus() {
    setSigninStatus();
  }
</script>

<button id="sign-in-or-out-button"
        style="margin-left: 25px">Sign In/Authorize</button>
<button id="revoke-access-button"
        style="display: none; margin-left: 25px">Revoke access</button>

<div id="auth-status" style="display: inline; padding-left: 25px"></div><hr>

<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
<script async defer src="https://apis.google.com/js/api.js"
        onload="this.onload=function(){};handleClientLoad()"
        onreadystatechange="if (this.readyState === 'complete') this.onload()">
</script>
</body></html>

ปลายทาง OAuth 2.0

OAuth 2.0 สำหรับเว็บแอปพลิเคชันฝั่งไคลเอ็นต์ที่ทำงานในเบราว์เซอร์โดยใช้การเปลี่ยนเส้นทางไปยัง Google สำหรับความยินยอมของผู้ใช้

ตัวอย่างนี้แสดงการเรียกใช้ปลายทาง OAuth 2.0 ของ Google โดยตรงจากเบราว์เซอร์ของผู้ใช้ และไม่ได้ใช้โมดูล gapi.auth2 หรือไลบรารี JavaScript

<!DOCTYPE html>
<html><head></head><body>
<script>
  var YOUR_CLIENT_ID = 'REPLACE_THIS_VALUE';
  var YOUR_REDIRECT_URI = 'REPLACE_THIS_VALUE';
  var fragmentString = location.hash.substring(1);

  // Parse query string to see if page request is coming from OAuth 2.0 server.
  var params = {};
  var regex = /([^&=]+)=([^&]*)/g, m;
  while (m = regex.exec(fragmentString)) {
    params[decodeURIComponent(m[1])] = decodeURIComponent(m[2]);
  }
  if (Object.keys(params).length > 0) {
    localStorage.setItem('oauth2-test-params', JSON.stringify(params) );
    if (params['state'] && params['state'] == 'try_sample_request') {
      trySampleRequest();
    }
  }

  // If there's an access token, try an API request.
  // Otherwise, start OAuth 2.0 flow.
  function trySampleRequest() {
    var params = JSON.parse(localStorage.getItem('oauth2-test-params'));
    if (params && params['access_token']) {
      var xhr = new XMLHttpRequest();
      xhr.open('GET',
          'https://www.googleapis.com/drive/v3/about?fields=user&' +
          'access_token=' + params['access_token']);
      xhr.onreadystatechange = function (e) {
        if (xhr.readyState === 4 && xhr.status === 200) {
          console.log(xhr.response);
        } else if (xhr.readyState === 4 && xhr.status === 401) {
          // Token invalid, so prompt for user permission.
          oauth2SignIn();
        }
      };
      xhr.send(null);
    } else {
      oauth2SignIn();
    }
  }

  /*

    *   Create form to request access token from Google's OAuth 2.0 server.
 */
function oauth2SignIn() {
  // Google's OAuth 2.0 endpoint for requesting an access token
  var oauth2Endpoint = 'https://accounts.google.com/o/oauth2/v2/auth';

    // Create element to open OAuth 2.0 endpoint in new window.
    var form = document.createElement('form');
    form.setAttribute('method', 'GET'); // Send as a GET request.
    form.setAttribute('action', oauth2Endpoint);

    // Parameters to pass to OAuth 2.0 endpoint.
    var params = {'client_id': YOUR_CLIENT_ID,
                  'redirect_uri': YOUR_REDIRECT_URI,
                  'scope': 'https://www.googleapis.com/auth/drive.metadata.readonly',
                  'state': 'try_sample_request',
                  'include_granted_scopes': 'true',
                  'response_type': 'token'};

    // Add form parameters as hidden input values.
    for (var p in params) {
      var input = document.createElement('input');
      input.setAttribute('type', 'hidden');
      input.setAttribute('name', p);
      input.setAttribute('value', params[p]);
      form.appendChild(input);
    }

    // Add form to page and submit it to open the OAuth 2.0 endpoint.
    document.body.appendChild(form);
    form.submit();
  }
</script>

<button onclick="trySampleRequest();">Try sample request</button>
</body></html>

วิธีใหม่

GIS เท่านั้น

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

<!DOCTYPE html>
<html>
  <head>
    <script src="https://accounts.google.com/gsi/client" onload="initClient()" async defer></script>
  </head>
  <body>
    <script>
      var client;
      var access_token;

      function initClient() {
        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: (tokenResponse) => {
            access_token = tokenResponse.access_token;
          },
        });
      }
      function getToken() {
        client.requestAccessToken();
      }
      function revokeToken() {
        google.accounts.oauth2.revoke(access_token, () => {console.log('access token revoked')});
      }
      function loadCalendar() {
        var xhr = new XMLHttpRequest();
        xhr.open('GET', 'https://www.googleapis.com/calendar/v3/calendars/primary/events');
        xhr.setRequestHeader('Authorization', 'Bearer ' + access_token);
        xhr.send();
      }
    </script>
    <h1>Google Identity Services Authorization Token model</h1>
    <button onclick="getToken();">Get access token</button><br><br>
    <button onclick="loadCalendar();">Load Calendar</button><br><br>
    <button onclick="revokeToken();">Revoke token</button>
  </body>
</html>

GAPI async/await

ตัวอย่างนี้แสดงวิธีเพิ่มไลบรารีบริการระบุตัวตนของ Google โดยใช้รูปแบบโทเค็น นำโมดูล gapi.auth2 ออก และเรียกใช้ API โดยใช้ไลบรารีของไคลเอ็นต์ Google API สําหรับ JavaScript

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

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

<!DOCTYPE html>
<html>
<head></head>
<body>
  <h1>GAPI with GIS async/await</h1>
  <button id="showEventsBtn" onclick="showEvents();">Show Calendar</button><br><br>
  <button id="revokeBtn" onclick="revokeToken();">Revoke access token</button>

  <script>

    const gapiLoadPromise = new Promise((resolve, reject) => {
      gapiLoadOkay = resolve;
      gapiLoadFail = reject;
    });
    const gisLoadPromise = new Promise((resolve, reject) => {
      gisLoadOkay = resolve;
      gisLoadFail = reject;
    });

    var tokenClient;

    (async () => {
      document.getElementById("showEventsBtn").style.visibility="hidden";
      document.getElementById("revokeBtn").style.visibility="hidden";

      // First, load and initialize the gapi.client
      await gapiLoadPromise;
      await new Promise((resolve, reject) => {
        // NOTE: the 'auth2' module is no longer loaded.
        gapi.load('client', {callback: resolve, onerror: reject});
      });
      await gapi.client.init({
        // NOTE: OAuth2 'scope' and 'client_id' parameters have moved to initTokenClient().
      })
      .then(function() {  // Load the Calendar API discovery document.
        gapi.client.load('https://www.googleapis.com/discovery/v1/apis/calendar/v3/rest');
      });

      // Now load the GIS client
      await gisLoadPromise;
      await new Promise((resolve, reject) => {
        try {
          tokenClient = google.accounts.oauth2.initTokenClient({
              client_id: 'YOUR_CLIENT_ID',
              scope: 'https://www.googleapis.com/auth/calendar.readonly',
              prompt: 'consent',
              callback: '',  // defined at request time in await/promise scope.
          });
          resolve();
        } catch (err) {
          reject(err);
        }
      });

      document.getElementById("showEventsBtn").style.visibility="visible";
      document.getElementById("revokeBtn").style.visibility="visible";
    })();

    async function getToken(err) {

      if (err.result.error.code == 401 || (err.result.error.code == 403) &&
          (err.result.error.status == "PERMISSION_DENIED")) {

        // The access token is missing, invalid, or expired, prompt for user consent to obtain one.
        await new Promise((resolve, reject) => {
          try {
            // Settle this promise in the response callback for requestAccessToken()
            tokenClient.callback = (resp) => {
              if (resp.error !== undefined) {
                reject(resp);
              }
              // GIS has automatically updated gapi.client with the newly issued access token.
              console.log('gapi.client access token: ' + JSON.stringify(gapi.client.getToken()));
              resolve(resp);
            };
            tokenClient.requestAccessToken();
          } catch (err) {
            console.log(err)
          }
        });
      } else {
        // Errors unrelated to authorization: server errors, exceeding quota, bad requests, and so on.
        throw new Error(err);
      }
    }

    function showEvents() {

      // Try to fetch a list of Calendar events. If a valid access token is needed,
      // prompt to obtain one and then retry the original request.
      gapi.client.calendar.events.list({ 'calendarId': 'primary' })
      .then(calendarAPIResponse => console.log(JSON.stringify(calendarAPIResponse)))
      .catch(err  => getToken(err))  // for authorization errors obtain an access token
      .then(retry => gapi.client.calendar.events.list({ 'calendarId': 'primary' }))
      .then(calendarAPIResponse => console.log(JSON.stringify(calendarAPIResponse)))
      .catch(err  => console.log(err)); // cancelled by user, timeout, etc.
    }

    function revokeToken() {
      let cred = gapi.client.getToken();
      if (cred !== null) {
        google.accounts.oauth2.revoke(cred.access_token, () => {console.log('Revoked: ' + cred.access_token)});
        gapi.client.setToken('');
      }
    }

  </script>

  <script async defer src="https://apis.google.com/js/api.js" onload="gapiLoadOkay()" onerror="gapiLoadFail(event)"></script>
  <script async defer src="https://accounts.google.com/gsi/client" onload="gisLoadOkay()" onerror="gisLoadFail(event)"></script>

</body>
</html>

การติดต่อกลับของ GAPI

ตัวอย่างนี้แสดงวิธีเพิ่มไลบรารีบริการระบุตัวตนของ Google โดยใช้รูปแบบโทเค็น นำโมดูล gapi.auth2 ออก และเรียกใช้ API โดยใช้ไลบรารีของไคลเอ็นต์ Google API สําหรับ JavaScript

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

ผู้ใช้ควรกดปุ่ม "แสดงปฏิทิน" เมื่อโหลดหน้าเว็บเป็นครั้งแรก และกดอีกครั้งเมื่อต้องการรีเฟรชข้อมูลปฏิทิน

<!DOCTYPE html>
<html>
<head>
  <script async defer src="https://apis.google.com/js/api.js" onload="gapiLoad()"></script>
  <script async defer src="https://accounts.google.com/gsi/client" onload="gisInit()"></script>
</head>
<body>
  <h1>GAPI with GIS callbacks</h1>
  <button id="showEventsBtn" onclick="showEvents();">Show Calendar</button><br><br>
  <button id="revokeBtn" onclick="revokeToken();">Revoke access token</button>
  <script>
    let tokenClient;
    let gapiInited;
    let gisInited;

    document.getElementById("showEventsBtn").style.visibility="hidden";
    document.getElementById("revokeBtn").style.visibility="hidden";

    function checkBeforeStart() {
       if (gapiInited && gisInited){
          // Start only when both gapi and gis are initialized.
          document.getElementById("showEventsBtn").style.visibility="visible";
          document.getElementById("revokeBtn").style.visibility="visible";
       }
    }

    function gapiInit() {
      gapi.client.init({
        // NOTE: OAuth2 'scope' and 'client_id' parameters have moved to initTokenClient().
      })
      .then(function() {  // Load the Calendar API discovery document.
        gapi.client.load('https://www.googleapis.com/discovery/v1/apis/calendar/v3/rest');
        gapiInited = true;
        checkBeforeStart();
      });
    }

    function gapiLoad() {
        gapi.load('client', gapiInit)
    }

    function gisInit() {
     tokenClient = google.accounts.oauth2.initTokenClient({
                client_id: 'YOUR_CLIENT_ID',
                scope: 'https://www.googleapis.com/auth/calendar.readonly',
                callback: '',  // defined at request time
            });
      gisInited = true;
      checkBeforeStart();
    }

    function showEvents() {

      tokenClient.callback = (resp) => {
        if (resp.error !== undefined) {
          throw(resp);
        }
        // GIS has automatically updated gapi.client with the newly issued access token.
        console.log('gapi.client access token: ' + JSON.stringify(gapi.client.getToken()));

        gapi.client.calendar.events.list({ 'calendarId': 'primary' })
        .then(calendarAPIResponse => console.log(JSON.stringify(calendarAPIResponse)))
        .catch(err => console.log(err));

        document.getElementById("showEventsBtn").innerText = "Refresh Calendar";
      }

      // Conditionally ask users to select the Google Account they'd like to use,
      // and explicitly obtain their consent to fetch their Calendar.
      // NOTE: To request an access token a user gesture is necessary.
      if (gapi.client.getToken() === null) {
        // Prompt the user to select a Google Account and asked for consent to share their data
        // when establishing a new session.
        tokenClient.requestAccessToken({prompt: 'consent'});
      } else {
        // Skip display of account chooser and consent dialog for an existing session.
        tokenClient.requestAccessToken({prompt: ''});
      }
    }

    function revokeToken() {
      let cred = gapi.client.getToken();
      if (cred !== null) {
        google.accounts.oauth2.revoke(cred.access_token, () => {console.log('Revoked: ' + cred.access_token)});
        gapi.client.setToken('');
        document.getElementById("showEventsBtn").innerText = "Show Calendar";
      }
    }
  </script>
</body>
</html>

ตัวอย่างขั้นตอนรหัสการให้สิทธิ์

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

วิธีเดิม

เว็บแอปฝั่งเซิร์ฟเวอร์

Google Sign-In สําหรับแอปฝั่งเซิร์ฟเวอร์ที่ทํางานในแพลตฟอร์มแบ็กเอนด์ ใช้การเปลี่ยนเส้นทางไปยัง Google เพื่อขอความยินยอมจากผู้ใช้

<!DOCTYPE html>
<html>
  <head>
    <script src="//ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js"></script>
    <script src="https://apis.google.com/js/client:platform.js?onload=start" async defer></script>
    <script>
      function start() {
        gapi.load('auth2', function() {
          auth2 = gapi.auth2.init({
            client_id: 'YOUR_CLIENT_ID',
            api_key: 'YOUR_API_KEY',
            discovery_docs: ['https://www.googleapis.com/discovery/v1/apis/translate/v2/rest'],
            // Scopes to request in addition to 'profile' and 'email'
            scope: 'https://www.googleapis.com/auth/cloud-translation',
          });
        });
      }
      function signInCallback(authResult) {
        if (authResult['code']) {
          console.log("sending AJAX request");
          // Send authorization code obtained from Google to backend platform
          $.ajax({
            type: 'POST',
            url: 'YOUR_AUTHORIZATION_CODE_ENDPOINT_URL',
            // Always include an X-Requested-With header to protect against CSRF attacks.
            headers: {
              'X-Requested-With': 'XMLHttpRequest'
            },
            contentType: 'application/octet-stream; charset=utf-8',
            success: function(result) {
              console.log(result);
            },
            processData: false,
            data: authResult['code']
          });
        } else {
          console.log('error: failed to obtain authorization code')
        }
      }
    </script>
  </head>
  <body>
    <button id="signinButton">Sign In With Google</button>
    <script>
      $('#signinButton').click(function() {
        // Obtain an authorization code from Google
        auth2.grantOfflineAccess().then(signInCallback);
      });
    </script>
  </body>
</html>

HTTP/REST โดยใช้การเปลี่ยนเส้นทาง

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

/\*
 \* Create form to request access token from Google's OAuth 2.0 server.
 \*/
function oauthSignIn() {
  // Google's OAuth 2.0 endpoint for requesting an access token
  var oauth2Endpoint = 'https://accounts.google.com/o/oauth2/v2/auth';
  // Create &lt;form> element to submit parameters to OAuth 2.0 endpoint.
  var form = document.createElement('form');
  form.setAttribute('method', 'GET'); // Send as a GET request.
  form.setAttribute('action', oauth2Endpoint);
  // Parameters to pass to OAuth 2.0 endpoint.
  var params = {'client\_id': 'YOUR_CLIENT_ID',
                'redirect\_uri': 'YOUR_AUTHORIZATION_CODE_ENDPOINT_URL',
                'response\_type': 'token',
                'scope': 'https://www.googleapis.com/auth/drive.metadata.readonly',
                'include\_granted\_scopes': 'true',
                'state': 'pass-through value'};
  // Add form parameters as hidden input values.
  for (var p in params) {
    var input = document.createElement('input');
    input.setAttribute('type', 'hidden');
    input.setAttribute('name', p);
    input.setAttribute('value', params[p]);
    form.appendChild(input);
  }

  // Add form to page and submit it to open the OAuth 2.0 endpoint.
  document.body.appendChild(form);
  form.submit();
}

วิธีใหม่

UX ของป๊อปอัป GIS

ตัวอย่างนี้แสดงเฉพาะไลบรารี JavaScript ของ Google Identity Service ที่ใช้รูปแบบรหัสการให้สิทธิ์ กล่องโต้ตอบแบบป๊อปอัปสําหรับความยินยอมของผู้ใช้ และตัวแฮนเดิลการเรียกกลับเพื่อรับรหัสการให้สิทธิ์จาก Google มีไว้เพื่อแสดงขั้นตอนขั้นต่ำที่จำเป็นในการกำหนดค่าไคลเอ็นต์ ขอความยินยอม และส่งรหัสการให้สิทธิ์ไปยังแพลตฟอร์มแบ็กเอนด์

<!DOCTYPE html>
<html>
  <head>
    <script src="https://accounts.google.com/gsi/client" onload="initClient()" async defer></script>
  </head>
  <body>
    <script>
      var client;
      function initClient() {
        client = google.accounts.oauth2.initCodeClient({
          client_id: 'YOUR_CLIENT_ID',
          scope: 'https://www.googleapis.com/auth/calendar.readonly',
          ux_mode: 'popup',
          callback: (response) => {
            var code_receiver_uri = 'YOUR_AUTHORIZATION_CODE_ENDPOINT_URI',
            // Send auth code to your backend platform
            const xhr = new XMLHttpRequest();
            xhr.open('POST', code_receiver_uri, true);
            xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
            xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
            xhr.onload = function() {
              console.log('Signed in as: ' + xhr.responseText);
            };
            xhr.send('code=' + response.code);
            // After receipt, the code is exchanged for an access token and
            // refresh token, and the platform then updates this web app
            // running in user's browser with the requested calendar info.
          },
        });
      }
      function getAuthCode() {
        // Request authorization code and obtain user consent
        client.requestCode();
      }
    </script>
    <button onclick="getAuthCode();">Load Your Calendar</button>
  </body>
</html>

UX การเปลี่ยนเส้นทาง GIS

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

<!DOCTYPE html>
<html>
  <head>
    <script src="https://accounts.google.com/gsi/client" onload="initClient()" async defer></script>
  </head>
  <body>
    <script>
      var client;
      function initClient() {
        client = google.accounts.oauth2.initCodeClient({
          client_id: 'YOUR_CLIENT_ID',
          scope: 'https://www.googleapis.com/auth/calendar.readonly \
                  https://www.googleapis.com/auth/photoslibrary.readonly',
          ux_mode: 'redirect',
          redirect_uri: 'YOUR_AUTHORIZATION_CODE_ENDPOINT_URI'
        });
      }
      // Request an access token
      function getAuthCode() {
        // Request authorization code and obtain user consent
        client.requestCode();
      }
    </script>
    <button onclick="getAuthCode();">Load Your Calendar</button>
  </body>
</html>

ไลบรารี JavaScript

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

สิ่งที่ควรทำเมื่อย้ายข้อมูลไปยังบริการข้อมูลประจำตัวมีดังนี้

ไลบรารี JS ที่มีอยู่ ไลบรารี JS ใหม่ หมายเหตุ
apis.google.com/js/api.js accounts.google.com/gsi/client เพิ่มคลังใหม่และทำตามขั้นตอนแบบไม่แสดง
apis.google.com/js/client.js accounts.google.com/gsi/client เพิ่มคลังใหม่และขั้นตอนรหัสการให้สิทธิ์

ข้อมูลอ้างอิงโดยย่อเกี่ยวกับคลัง

การเปรียบเทียบออบเจ็กต์และเมธอดระหว่างไลบรารีไคลเอ็นต์ JavaScript ของ Google Sign-In เก่ากับไลบรารีบริการ Google Identity ใหม่และหมายเหตุ พร้อมด้วยข้อมูลเพิ่มเติมและการดำเนินการที่ต้องทำระหว่างการย้ายข้อมูล

เก่า ใหม่ หมายเหตุ
ออบเจ็กต์ GoogleAuth และเมธอดที่เกี่ยวข้อง
GoogleAuth.attachClickHandler() นำออก
GoogleAuth.currentUser.get() นำออก
GoogleAuth.currentUser.listen() นำออก
GoogleAuth.disconnect() google.accounts.oauth2.revoke แทนที่รายการเก่าด้วยรายการใหม่ การเพิกถอนอาจเกิดขึ้นจาก https://myaccount.google.com/permissions เช่นกัน
GoogleAuth.grantOfflineAccess() นำออก แล้วทำตามขั้นตอนรหัสการให้สิทธิ์
GoogleAuth.isSignedIn.get() นำออก
GoogleAuth.isSignedIn.listen() นำออก
GoogleAuth.signIn() นำออก
GoogleAuth.signOut() นำออก
GoogleAuth.then() นำออก
ออบเจ็กต์ GoogleUser และเมธอดที่เกี่ยวข้อง
GoogleUser.disconnect() google.accounts.id.revoke แทนที่รายการเก่าด้วยรายการใหม่ นอกจากนี้ คุณยังเพิกถอนสิทธิ์ได้จาก https://myaccount.google.com/permissions
GoogleUser.getAuthResponse() requestCode() or requestAccessToken() แทนที่รายการเก่าด้วยรายการใหม่
GoogleUser.getBasicProfile() นำออก โปรดใช้โทเค็นรหัสแทน โปรดดูการย้ายข้อมูลจาก Google Sign-In
GoogleUser.getGrantedScopes() hasGrantedAnyScope() แทนที่รายการเก่าด้วยรายการใหม่
GoogleUser.getHostedDomain() นำออก
GoogleUser.getId() นำออก
GoogleUser.grantOfflineAccess() โปรดนำออก แล้วทำตามขั้นตอนรหัสการให้สิทธิ์
GoogleUser.grant() นำออก
GoogleUser.hasGrantedScopes() hasGrantedAnyScope() แทนที่รายการเก่าด้วยรายการใหม่
GoogleUser.isSignedIn() นำออก
GoogleUser.reloadAuthResponse() requestAccessToken() นำโทเค็นเก่าออก แล้วเรียกใช้โทเค็นใหม่เพื่อแทนที่โทเค็นการเข้าถึงที่หมดอายุหรือถูกเพิกถอน
ออบเจ็กต์ gapi.auth2 และเมธอดที่เกี่ยวข้อง
ออบเจ็กต์ gapi.auth2.AuthorizeConfig TokenClientConfig หรือ CodeClientConfig แทนที่รายการเก่าด้วยรายการใหม่
ออบเจ็กต์ gapi.auth2.AuthorizeResponse นำออก
ออบเจ็กต์ gapi.auth2.AuthResponse นำออก
gapi.auth2.authorize() requestCode() or requestAccessToken() แทนที่รายการเก่าด้วยใหม่
gapi.auth2.ClientConfig() TokenClientConfig หรือ CodeClientConfig แทนที่รายการเก่าด้วยใหม่
gapi.auth2.getAuthInstance() นำออก
gapi.auth2.init() initTokenClient() or initCodeClient() แทนที่รายการเก่าด้วยรายการใหม่
ออบเจ็กต์ gapi.auth2.OfflineAccessOptions นำออก
ออบเจ็กต์ gapi.auth2.SignInOptions นำออก
gapi.signin2 และวิธีการที่เกี่ยวข้อง:
gapi.signin2.render() นำออก การโหลด HTML DOM ขององค์ประกอบ g_id_signin หรือ JS ที่เรียกใช้ google.accounts.id.renderButton จะทริกเกอร์การลงชื่อเข้าใช้บัญชี Google ของผู้ใช้

ตัวอย่างข้อมูลเข้าสู่ระบบ

ข้อมูลเข้าสู่ระบบที่มีอยู่

ไลบรารีแพลตฟอร์ม Google Sign-In, ไลบรารีไคลเอ็นต์ Google API สำหรับ JavaScript หรือการเรียกใช้ปลายทาง Google Auth 2.0 โดยตรงจะแสดงทั้งโทเค็นการเข้าถึง OAuth 2.0 และโทเค็นระบุตัวตน OpenID Connect ในการตอบกลับครั้งเดียว

ตัวอย่างคำตอบที่มีทั้ง access_token และ id_token

  {
    "token_type": "Bearer",
    "access_token": "ya29.A0ARrdaM-SmArZaCIh68qXsZSzyeU-8mxhQERHrP2EXtxpUuZ-3oW8IW7a6D2J6lRnZrRj8S6-ZcIl5XVEqnqxq5fuMeDDH_6MZgQ5dgP7moY-yTiKR5kdPm-LkuPM-mOtUsylWPd1wpRmvw_AGOZ1UUCa6UD5Hg",
    "scope": "https://www.googleapis.com/auth/calendar.readonly",
    "login_hint": "AJDLj6I2d1RH77cgpe__DdEree1zxHjZJr4Q7yOisoumTZUmo5W2ZmVFHyAomUYzLkrluG-hqt4RnNxrPhArd5y6p8kzO0t8xIfMAe6yhztt6v2E-_Bb4Ec3GLFKikHSXNh5bI-gPrsI",
    "expires_in": 3599,
    "id_token": "eyJhbGciOiJSUzI1NiIsImtpZCI6IjkzNDFhYmM0MDkyYjZmYzAzOGU0MDNjOTEwMjJkZDNlNDQ1MzliNTYiLCJ0eXAiOiJKV1QifQ.eyJpc3MiOiJhY2NvdW50cy5nb29nbGUuY29tIiwiYXpwIjoiNTM4MzQ0NjUzMjU1LTc1OGM1aDVpc2M0NXZnazI3ZDhoOGRlYWJvdnBnNnRvLmFwcHMuZ29vZ2xldXNlcmNvbnRlbnQuY29tIiwiYXVkIjoiNTM4MzQ0NjUzMjU1LTc1OGM1aDVpc2M0NXZnazI3ZDhoOGRlYWJvdnBnNnRvLmFwcHMuZ29vZ2xldXNlcmNvbnRlbnQuY29tIiwic3ViIjoiMTE3NzI2NDMxNjUxOTQzNjk4NjAwIiwiaGQiOiJnb29nbGUuY29tIiwiZW1haWwiOiJkYWJyaWFuQGdvb2dsZS5jb20iLCJlbWFpbF92ZXJpZmllZCI6dHJ1ZSwiYXRfaGFzaCI6IkJBSW55TjN2MS1ZejNLQnJUMVo0ckEiLCJuYW1lIjoiQnJpYW4gRGF1Z2hlcnR5IiwicGljdHVyZSI6Imh0dHBzOi8vbGgzLmdvb2dsZXVzZXJjb250ZW50LmNvbS9hLS9BT2gxNEdnenAyTXNGRGZvbVdMX3VDemRYUWNzeVM3ZGtxTE5ybk90S0QzVXNRPXM5Ni1jIiwiZ2l2ZW5fbmFtZSI6IkJyaWFuIiwiZmFtaWx5X25hbWUiOiJEYXVnaGVydHkiLCJsb2NhbGUiOiJlbiIsImlhdCI6MTYzODk5MTYzOCwiZXhwIjoxNjM4OTk1MjM4LCJqdGkiOiI5YmRkZjE1YWFiNzE2ZDhjYmJmNDYwMmM1YWM3YzViN2VhMDQ5OTA5In0.K3EA-3Adw5HA7O8nJVCsX1HmGWxWzYk3P7ViVBb4H4BoT2-HIgxKlx1mi6jSxIUJGEekjw9MC-nL1B9Asgv1vXTMgoGaNna0UoEHYitySI23E5jaMkExkTSLtxI-ih2tJrA2ggfA9Ekj-JFiMc6MuJnwcfBTlsYWRcZOYVw3QpdTZ_VYfhUu-yERAElZCjaAyEXLtVQegRe-ymScra3r9S92TA33ylMb3WDTlfmDpWL0CDdDzby2asXYpl6GQ7SdSj64s49Yw6mdGELZn5WoJqG7Zr2KwIGXJuSxEo-wGbzxNK-mKAiABcFpYP4KHPEUgYyz3n9Vqn2Tfrgp-g65BQ",
    "session_state": {
      "extraQueryParams": {
        "authuser": "0"
      }
    },
    "first_issued_at": 1638991637982,
    "expires_at": 1638995236982,
    "idpId": "google"
  }

ข้อมูลเข้าสู่ระบบบริการ Google Identity

ไลบรารี Google Identity Services จะแสดงผลดังนี้

  • โทเค็นการเข้าถึงเมื่อใช้สำหรับการให้สิทธิ์

    {
      "access_token": "ya29.A0ARrdaM_LWSO-uckLj7IJVNSfnUityT0Xj-UCCrGxFQdxmLiWuAosnAKMVQ2Z0LLqeZdeJii3TgULp6hR_PJxnInBOl8UoUwWoqsrGQ7-swxgy97E8_hnzfhrOWyQBmH6zs0_sUCzwzhEr_FAVqf92sZZHphr0g",
      "token_type": "Bearer",
      "expires_in": 3599,
      "scope": "https://www.googleapis.com/auth/calendar.readonly"
    }
    
  • หรือโทเค็นระบุตัวตนเมื่อใช้สำหรับการตรวจสอบสิทธิ์

    {
      "clientId": "538344653255-758c5h5isc45vgk27d8h8deabovpg6to.apps.googleusercontent.com",
      "credential": "eyJhbGciOiJSUzI1NiIsImtpZCI6ImMxODkyZWI0OWQ3ZWY5YWRmOGIyZTE0YzA1Y2EwZDAzMjcxNGEyMzciLCJ0eXAiOiJKV1QifQ.eyJpc3MiOiJodHRwczovL2FjY291bnRzLmdvb2dsZS5jb20iLCJuYmYiOjE2MzkxNTcyNjQsImF1ZCI6IjUzODM0NDY1MzI1NS03NThjNWg1aXNjNDV2Z2syN2Q4aDhkZWFib3ZwZzZ0by5hcHBzLmdvb2dsZXVzZXJjb250ZW50LmNvbSIsInN1YiI6IjExNzcyNjQzMTY1MTk0MzY5ODYwMCIsIm5vbmNlIjoiZm9vYmFyIiwiaGQiOiJnb29nbGUuY29tIiwiZW1haWwiOiJkYWJyaWFuQGdvb2dsZS5jb20iLCJlbWFpbF92ZXJpZmllZCI6dHJ1ZSwiYXpwIjoiNTM4MzQ0NjUzMjU1LTc1OGM1aDVpc2M0NXZnazI3ZDhoOGRlYWJvdnBnNnRvLmFwcHMuZ29vZ2xldXNlcmNvbnRlbnQuY29tIiwibmFtZSI6IkJyaWFuIERhdWdoZXJ0eSIsInBpY3R1cmUiOiJodHRwczovL2xoMy5nb29nbGV1c2VyY29udGVudC5jb20vYS0vQU9oMTRHZ3pwMk1zRkRmb21XTF91Q3pkWFFjc3lTN2RrcUxOcm5PdEtEM1VzUT1zOTYtYyIsImdpdmVuX25hbWUiOiJCcmlhbiIsImZhbWlseV9uYW1lIjoiRGF1Z2hlcnR5IiwiaWF0IjoxNjM5MTU3NTY0LCJleHAiOjE2MzkxNjExNjQsImp0aSI6IjRiOTVkYjAyZjU4NDczMmUxZGJkOTY2NWJiMWYzY2VhYzgyMmI0NjUifQ.Cr-AgMsLFeLurnqyGpw0hSomjOCU4S3cU669Hyi4VsbqnAV11zc_z73o6ahe9Nqc26kPVCNRGSqYrDZPfRyTnV6g1PIgc4Zvl-JBuy6O9HhClAK1HhMwh1FpgeYwXqrng1tifmuotuLQnZAiQJM73Gl-J_6s86Buo_1AIx5YAKCucYDUYYdXBIHLxrbALsA5W6pZCqqkMbqpTWteix-G5Q5T8LNsfqIu_uMBUGceqZWFJALhS9ieaDqoxhIqpx_89QAr1YlGu_UO6R6FYl0wDT-nzjyeF5tonSs3FHN0iNIiR3AMOHZu7KUwZaUdHg4eYkU-sQ01QNY_11keHROCRQ",
      "select_by": "user"
    }
    

การตอบสนองของโทเค็นไม่ถูกต้อง

ตัวอย่างการตอบกลับจาก Google เมื่อพยายามส่งคําขอ API โดยใช้โทเค็นการเข้าถึงที่หมดอายุ เพิกถอน หรือใช้งานไม่ได้

ส่วนหัวการตอบกลับ HTTP

  www-authenticate: Bearer realm="https://accounts.google.com/", error="invalid_token"

เนื้อหาการตอบกลับ

  {
    "error": {
      "code": 401,
      "message": "Request had invalid authentication credentials. Expected OAuth 2 access token, login cookie or other valid authentication credential. See https://developers.google.com/identity/sign-in/web/devconsole-project.",
      "errors": [
        {
          "message": "Invalid Credentials",
          "domain": "global",
          "reason": "authError",
          "location": "Authorization",
          "locationType": "header"
        }
      ],
      "status": "UNAUTHENTICATED"
    }
  }