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

ภาพรวม

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

คู่มือนี้จะแสดงคำแนะนำในการย้ายข้อมูลจากไลบรารีเหล่านี้ไปยัง Identity Services Library

เมื่อทำตามคู่มือนี้ คุณจะ

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

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

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

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

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

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

ตัวบ่งชี้ที่เว็บแอปใช้ขั้นตอนโดยนัย ได้แก่

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

  • การติดตั้งใช้งานของคุณขึ้นอยู่กับปัจจัยต่อไปนี้

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

วัตถุ:

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

วิธีการ:

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

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

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

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

วัตถุ:

  • จำนวนเงิน 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 บริการข้อมูลประจำตัว:

วิธีการ:

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

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

อัปเดตฐานของโค้ดเป็น

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

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

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

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

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

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

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

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

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

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

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

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

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

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

วิธีการ:

  • จำนวนเงิน 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 บริการข้อมูลประจำตัว:

วัตถุ:

  • จำนวนเงิน 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 ไม่ซิงค์/รอ

ตัวอย่างนี้แสดงวิธีเพิ่มไลบรารีของบริการ Google Identity โดยใช้ โมเดลโทเค็น นำโมดูล 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>

Callback ของ GAPI

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

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

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

<!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 สามารถใช้การเปลี่ยนเส้นทาง URL ไปยัง แสดงรหัสการให้สิทธิ์ไปยังปลายทางของโทเค็นแบ็กเอนด์โดยตรง หรือ ตัวแฮนเดิล Callback ของ 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 โดยใช้รูปแบบรหัสการให้สิทธิ์ของกล่องโต้ตอบป๊อปอัปสำหรับความยินยอมของผู้ใช้ และ Callback Handler เพื่อรับรหัสการให้สิทธิ์จาก 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 Services ใหม่ และ โน้ตพร้อมข้อมูลเพิ่มเติมและการดำเนินการที่ต้องทำระหว่างการย้ายข้อมูล

เก่า ใหม่ หมายเหตุ
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 Services

ไลบรารี 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"
    }
  }