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

ภาพรวม

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

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

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

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

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

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

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

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

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

การบ่งชี้ว่าเว็บแอปของคุณใช้ขั้นตอนโดยนัยดังต่อไปนี้

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

  • การใช้งานของคุณขึ้นอยู่กับ:

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

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

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

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

ในบางกรณี Codebase อาจรองรับทั้งสองโฟลว์

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

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

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

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

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

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

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

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

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

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

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

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

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

ส่วนนี้จะตรวจสอบการเปลี่ยนแปลงที่คุณจะทํากับเว็บแอปในเบราว์เซอร์เมื่อย้ายข้อมูลไปยังไลบรารี 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 จัดการการตรวจสอบสิทธิ์ของผู้ใช้สําหรับการลงชื่อเข้าใช้และขั้นตอนการให้สิทธิ์โดยปริยาย ให้แทนที่โมดูลที่เลิกใช้งานนี้ รวมถึงออบเจ็กต์และเมธอดของไลบรารีดังกล่าวด้วยไลบรารี Google Identity Services

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

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

ลบอินสแตนซ์ใดๆ ที่โหลดโมดูล auth2 โดยใช้ gapi.load('auth2', function)

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

คุกกี้

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

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

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

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

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

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

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

นําออก ข้อมูลอ้างอิงของไคลเอ็นต์ JavaScript สําหรับ Google Sign-In ดังต่อไปนี้

วิธีการ

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

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

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

สถานะเซสชัน

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

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

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

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

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

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

Google API จะส่งรหัสสถานะ 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 หากไม่มีเซสชันที่ใช้งานอยู่อยู่แล้ว
  • ใช้ช่องโทเค็นข้อมูลรับรอง JWT โดยตรง email เป็นค่าของพารามิเตอร์ 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 เท่านั้นโดยใช้โมเดลโทเค็นและกล่องโต้ตอบป๊อปอัปสําหรับคํายินยอมของผู้ใช้ รหัสนี้จะแสดงให้เห็นจํานวนขั้นตอนขั้นต่ําที่จําเป็นในการกําหนดค่าไคลเอ็นต์ ขอและรับโทเค็นเพื่อการเข้าถึง และเพื่อเรียกใช้ 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 Service โดยใช้โมเดลโทเค็น นําโมดูล gapi.auth2 ออก และเรียก API โดยใช้ไลบรารีของไคลเอ็นต์ Google API สําหรับ JavaScript

การสัญญา การซิงค์แบบไม่พร้อมกัน และรอการดําเนินการเพื่อบังคับใช้ลําดับการโหลดไลบรารี รวมถึงเพื่อตรวจจับและแก้ไขข้อผิดพลาดในการให้สิทธิ์ การเรียก 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 Identity Service โดยใช้โมเดลโทเค็น นําโมดูล 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 Service แบบป๊อปอัปสามารถใช้การเปลี่ยนเส้นทาง URL เพื่อส่งกลับรหัสการให้สิทธิ์ไปยังปลายทางโทเค็นแบ็กเอนด์ของคุณโดยตรง หรือเครื่องจัดการการเรียก JavaScript ที่ทํางานในเบราว์เซอร์ของผู้ใช้ ซึ่งส่งการตอบกลับไปยังแพลตฟอร์มของคุณ ทั้ง 2 กรณี แพลตฟอร์มแบ็กเอนด์จะทําขั้นตอน 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();
}

รูปแบบใหม่

GIS ป๊อปอัป UX

ตัวอย่างนี้แสดงเฉพาะไลบรารี 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 เป็นไลบรารี JavaScript เดียวที่ใช้สําหรับการตรวจสอบสิทธิ์ของผู้ใช้และการให้สิทธิ์ ซึ่งรวมและแทนที่คุณลักษณะและฟังก์ชันการทํางานในไลบรารีและโมดูลต่างๆ มากมาย

สิ่งที่ต้องทําเมื่อย้ายข้อมูลไปยังบริการ Identity

ไลบรารี 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 และไลบรารีใหม่ บริการข้อมูลประจําตัวของ Google และโน้ตที่มีข้อมูลและการดําเนินการเพิ่มเติมระหว่างการย้ายข้อมูล

เก่า ใหม่ หมายเหตุ
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() หรือ 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() หรือ requestAccessToken() แทนที่รายการเก่าด้วยรายการใหม่
gapi.auth2.ClientConfig() TokenClientConfig หรือ CodeClientConfig แทนที่รายการเก่าด้วยรายการใหม่
gapi.auth2.getAuthInstance() นำออก
gapi.auth2.init() initTokenClient() หรือ 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

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