ภาพรวม
Google มีไลบรารี JavaScript หลายรายการเพื่อรับโทเค็นเพื่อการเข้าถึงต่อผู้ใช้เพื่อเรียกใช้ Google API
คู่มือนี้จะแสดงวิธีย้ายข้อมูลจากไลบรารีเหล่านี้ไปยังไลบรารี Google Identity Services
การปฏิบัติตามคู่มือนี้จะให้คุณ
- แทนที่ไลบรารีแพลตฟอร์มที่เลิกใช้ด้วยไลบรารี Identity Services และ
- หากใช้ไลบรารีของไคลเอ็นต์ API ให้นำโมดูล
gapi.auth2
ที่เลิกใช้งานแล้วออก รวมถึงเมธอดและออบเจ็กต์ของโมดูลนี้ออก แล้วแทนที่ด้วยรายการที่เทียบเท่าของบริการ Identity
สำหรับคำอธิบายสิ่งที่เปลี่ยนแปลงไปในไลบรารี JavaScript ของ Identity Services โปรดอ่านภาพรวมและวิธีการให้สิทธิ์ผู้ใช้เพื่อตรวจสอบคำสำคัญและแนวคิดต่างๆ
หากต้องการการตรวจสอบสิทธิ์สำหรับการลงชื่อสมัครใช้และลงชื่อเข้าใช้ของผู้ใช้ โปรดดูการย้ายข้อมูลจาก Google Sign-In แทน
ระบุขั้นตอนการให้สิทธิ์
ขั้นตอนการให้สิทธิ์ผู้ใช้ที่เป็นไปได้มี 2 ขั้นตอน ได้แก่ โดยนัยและรหัสการให้สิทธิ์
ตรวจสอบเว็บแอปเพื่อระบุประเภทของขั้นตอนการให้สิทธิ์ที่ใช้งานอยู่ในปัจจุบัน
การบ่งชี้ที่เว็บแอปใช้ขั้นตอนการดำเนินการโดยนัย ดังนี้
- เว็บแอปของคุณทำงานบนเบราว์เซอร์เพียงอย่างเดียว โดยไม่มีแพลตฟอร์มแบ็กเอนด์
- ผู้ใช้ต้องอยู่เพื่อเรียก Google API แอปของคุณใช้เฉพาะโทเค็นเพื่อการเข้าถึงเท่านั้นและไม่ต้องใช้โทเค็นการรีเฟรช
- เว็บแอปจะโหลด
apis.google.com/js/api.js
- การใช้งานของคุณอิงตาม OAuth 2.0 สำหรับเว็บแอปพลิเคชันฝั่งไคลเอ็นต์
- แอปของคุณใช้โมดูล
gapi.client
หรือgapi.auth2
ที่พบในไลบรารีของไคลเอ็นต์ Google API สำหรับ JavaScript
การระบุว่าเว็บแอปใช้ขั้นตอนรหัสการให้สิทธิ์ ดังนี้
การติดตั้งใช้งานขึ้นอยู่กับปัจจัยต่อไปนี้
แอปจะทำงานทั้งในเบราว์เซอร์ของผู้ใช้และในแพลตฟอร์มแบ็กเอนด์
แพลตฟอร์มแบ็กเอนด์โฮสต์ปลายทางของรหัสการให้สิทธิ์
แพลตฟอร์มแบ็กเอนด์จะเรียกใช้ Google API ในนามของผู้ใช้โดยที่ผู้ใช้ไม่จำเป็นต้องแสดง หรือที่เรียกว่าโหมดออฟไลน์
โทเค็นการรีเฟรชได้รับการจัดการและจัดเก็บโดยแพลตฟอร์มแบ็กเอนด์ของคุณ
ในบางกรณี ฐานของโค้ดอาจรองรับทั้ง 2 ขั้นตอน
เลือกขั้นตอนการให้สิทธิ์
ก่อนที่จะเริ่มย้ายข้อมูล คุณต้องพิจารณาว่าดำเนินการตามขั้นตอนที่มีอยู่ต่อไปหรือใช้ขั้นตอนอื่นที่ตรงตามความต้องการของคุณมากที่สุด
ตรวจสอบการเลือกขั้นตอนการให้สิทธิ์เพื่อทำความเข้าใจความแตกต่างสำคัญและข้อดีข้อเสียระหว่าง 2 ขั้นตอน
ในกรณีส่วนใหญ่ เราแนะนำให้ใช้ขั้นตอนของรหัสการให้สิทธิ์เนื่องจากจะให้ความปลอดภัยของผู้ใช้ในระดับสูงสุด การใช้ขั้นตอนนี้ยังช่วยให้แพลตฟอร์มของคุณเพิ่มฟังก์ชันการทำงานแบบออฟไลน์ใหม่ได้ง่ายขึ้น เช่น การดึงข้อมูลอัปเดตเพื่อแจ้งให้ผู้ใช้ทราบเกี่ยวกับการเปลี่ยนแปลงที่สำคัญในปฏิทิน รูปภาพ การสมัครใช้บริการ และอื่นๆ
เลือกขั้นตอนการให้สิทธิ์โดยใช้ตัวเลือกด้านล่าง
ขั้นตอนการให้สิทธิ์โดยนัย
รับโทเค็นเพื่อการเข้าถึงสำหรับการใช้งานในเบราว์เซอร์ขณะที่ผู้ใช้อยู่
ตัวอย่างโฟลว์แบบไม่เจาะจงปลายทางจะแสดงเว็บแอปก่อนและหลังการย้ายข้อมูลไปยัง Identity Services
ขั้นตอนรหัสการให้สิทธิ์
ระบบจะส่งรหัสการให้สิทธิ์ต่อผู้ใช้ที่ Google ออกไปยังแพลตฟอร์มแบ็กเอนด์ ซึ่งจะแลกเปลี่ยนเป็นโทเค็นเพื่อการเข้าถึงและโทเค็นการรีเฟรช
ตัวอย่างขั้นตอนรหัสการให้สิทธิ์จะแสดงเว็บแอปก่อนและหลังการย้ายข้อมูลไปยัง Identity Services
ในคู่มือนี้ ให้ทำตามวิธีการที่แสดงเป็นตัวหนาเพื่อเพิ่ม นำออก อัปเดต หรือแทนที่ฟังก์ชันการทำงานที่มีอยู่
การเปลี่ยนแปลงของเว็บแอปในเบราว์เซอร์
ส่วนนี้ตรวจสอบการเปลี่ยนแปลงที่คุณจะทำกับเว็บแอปในเบราว์เซอร์เมื่อย้ายข้อมูลไปยังไลบรารี 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 ลงในเว็บแอปโดยรวมไว้ในเอกสารของคุณ ดังนี้
<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 ใช้คุกกี้สำหรับการใช้คุกกี้โดยผลิตภัณฑ์และบริการอื่นๆ ของ Google ได้ที่การย้ายข้อมูลจาก Google Sign-In
ข้อมูลเข้าสู่ระบบ
บริการข้อมูลประจำตัวของ Google จะแยกการตรวจสอบสิทธิ์และการให้สิทธิ์ของผู้ใช้ออกเป็นการดำเนินการที่แตกต่างกัน 2 อย่าง และข้อมูลเข้าสู่ระบบของผู้ใช้จะแยกกัน นั่นคือ โทเค็นรหัสที่ใช้ระบุตัวตนผู้ใช้จะแสดงแยกจากโทเค็นเพื่อการเข้าถึงที่ใช้สำหรับการให้สิทธิ์
ดูการเปลี่ยนแปลงเหล่านี้ได้ที่ตัวอย่างข้อมูลเข้าสู่ระบบ
ขั้นตอนการให้สิทธิ์โดยนัย
แยกการตรวจสอบสิทธิ์และการให้สิทธิ์ผู้ใช้โดยนำการจัดการโปรไฟล์ผู้ใช้ออกจากขั้นตอนการให้สิทธิ์
ลบข้อมูลอ้างอิงไคลเอ็นต์ Google Sign-In JavaScript เหล่านี้
วิธีการ
GoogleUser.getBasicProfile()
GoogleUser.getId()
ขั้นตอนรหัสการให้สิทธิ์
Identity Services จะแยกข้อมูลเข้าสู่ระบบในเบราว์เซอร์ออกเป็นโทเค็นรหัสและโทเค็นเพื่อการเข้าถึง การเปลี่ยนแปลงนี้จะไม่มีผลกับข้อมูลเข้าสู่ระบบที่ได้รับผ่านการเรียกโดยตรงไปยังปลายทาง Google OAuth 2.0 จากแพลตฟอร์มแบ็กเอนด์หรือผ่านไลบรารีที่ทำงานบนเซิร์ฟเวอร์ที่ปลอดภัยในแพลตฟอร์มของคุณ เช่น ไคลเอ็นต์ Google API Node.js
สถานะเซสชัน
ก่อนหน้านี้ Google Sign-In ช่วยคุณจัดการสถานะการลงชื่อเข้าใช้ของผู้ใช้โดยใช้สิ่งต่อไปนี้
- ตัวแฮนเดิลการติดต่อกลับสำหรับการตรวจสอบสถานะเซสชันของผู้ใช้
- Listener สำหรับเหตุการณ์และการเปลี่ยนแปลงสถานะการลงชื่อเข้าใช้สำหรับบัญชี Google ของผู้ใช้
คุณมีหน้าที่รับผิดชอบในการจัดการสถานะการลงชื่อเข้าใช้และเซสชันของผู้ใช้ในเว็บแอป
ลบข้อมูลอ้างอิงไคลเอ็นต์ Google Sign-In JavaScript เหล่านี้
ออบเจ็กต์:
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()
การกำหนดค่าไคลเอ็นต์
อัปเดตเว็บแอปเพื่อเริ่มต้นไคลเอ็นต์โทเค็นสำหรับโฟลว์รหัสโดยนัยหรือการให้สิทธิ์
ลบข้อมูลอ้างอิงไคลเอ็นต์ Google Sign-In JavaScript เหล่านี้
ออบเจ็กต์:
gapi.auth2.ClientConfig
gapi.auth2.OfflineAccessOptions
วิธีการ:
gapi.auth2.getAuthInstance()
GoogleUser.grant()
ขั้นตอนการให้สิทธิ์โดยนัย
เพิ่มออบเจ็กต์ TokenClientConfig
และการเรียกใช้ initTokenClient()
เพื่อกำหนดค่าเว็บแอป ตามตัวอย่างในเริ่มต้นไคลเอ็นต์โทเค็น
แทนที่ การอ้างอิงไคลเอ็นต์ Google Sign-In JavaScript ด้วย Google Identity Services ดังนี้
ออบเจ็กต์:
gapi.auth2.AuthorizeConfig
ร่วมกับTokenClientConfig
วิธีการ:
gapi.auth2.init()
ร่วมกับgoogle.accounts.oauth2.initTokenClient()
พารามิเตอร์ ได้แก่
gapi.auth2.AuthorizeConfig.login_hint
ด้วยTokenClientConfig.login_hint
gapi.auth2.GoogleUser.getHostedDomain()
ด้วยTokenClientConfig.hd
ขั้นตอนรหัสการให้สิทธิ์
เพิ่มออบเจ็กต์ CodeClientConfig
และการเรียกใช้ initCodeClient()
เพื่อกำหนดค่าเว็บแอป ตามตัวอย่างในเริ่มต้นไคลเอ็นต์โค้ด
เมื่อเปลี่ยนจากการให้สิทธิ์โดยนัยเป็นขั้นตอนรหัสการให้สิทธิ์ สิ่งที่จะเกิดขึ้นมีดังนี้
ลบ ข้อมูลอ้างอิงไคลเอ็นต์ JavaScript ของ Google Sign-In
ออบเจ็กต์:
gapi.auth2.AuthorizeConfig
วิธีการ:
gapi.auth2.init()
พารามิเตอร์ ได้แก่
gapi.auth2.AuthorizeConfig.login_hint
gapi.auth2.GoogleUser.getHostedDomain()
คำขอโทเค็น
ท่าทางสัมผัสของผู้ใช้ เช่น การคลิกปุ่ม จะสร้างคำขอที่ส่งผลให้โทเค็นการเข้าถึงส่งกลับไปยังเบราว์เซอร์ของผู้ใช้โดยตรงด้วยโฟลว์โดยนัย หรือไปยังแพลตฟอร์มแบ็กเอนด์หลังจากแลกเปลี่ยนรหัสการให้สิทธิ์ต่อผู้ใช้เป็นโทเค็นเพื่อการเข้าถึงและโทเค็นการรีเฟรช
ขั้นตอนการให้สิทธิ์โดยนัย
โทเค็นเพื่อการเข้าถึงอาจได้รับและใช้ในเบราว์เซอร์ขณะที่ผู้ใช้ลงชื่อเข้าใช้และมีเซสชันที่ใช้งานอยู่กับ Google สำหรับโหมดโดยนัย ผู้ใช้ต้องใช้ท่าทางสัมผัสของผู้ใช้เพื่อขอโทเค็นเพื่อการเข้าถึง แม้ว่าจะมีคำขอมาก่อนก็ตาม
แทนที่ การอ้างอิงไคลเอ็นต์ Google Sign-In JavaScript: ด้วย 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 Services ไม่รองรับกระบวนการรีเฟรชโทเค็นอัตโนมัตินี้เพื่อความปลอดภัยของผู้ใช้ที่ดียิ่งขึ้น คุณต้องอัปเดตเว็บแอปเพื่อตรวจหาโทเค็นเพื่อการเข้าถึงที่หมดอายุและขอโทเค็นใหม่ โปรดดูข้อมูลเพิ่มเติมในส่วนการจัดการโทเค็นด้านล่าง
ขั้นตอนรหัสการให้สิทธิ์
เพิ่มลิงก์หรือปุ่มเพื่อโทรไปที่ requestCode()
เพื่อขอรหัสการให้สิทธิ์จาก Google ดูตัวอย่างได้ที่ทริกเกอร์โฟลว์โค้ด OAuth 2.0
ดูข้อมูลเพิ่มเติมเกี่ยวกับวิธีตอบกลับโทเค็นเพื่อการเข้าถึงที่หมดอายุหรือถูกเพิกถอนได้ที่ส่วนการจัดการโทเค็นด้านล่าง
การจัดการโทเค็น
เพิ่มการจัดการข้อผิดพลาดเพื่อตรวจหาการเรียก Google API ที่ล้มเหลวเมื่อมีการใช้โทเค็นเพื่อการเข้าถึงที่หมดอายุหรือยกเลิกไปแล้ว และเพื่อขอโทเค็นเพื่อการเข้าถึงที่ถูกต้องใหม่
Google API จะแสดงรหัสสถานะ HTTP ของ 401 Unauthorized
และข้อความแสดงข้อผิดพลาด invalid_token
เมื่อมีการใช้โทเค็นเพื่อการเข้าถึงที่หมดอายุหรือถูกเพิกถอน ดูตัวอย่างได้ที่การตอบกลับโทเค็นที่ไม่ถูกต้อง
โทเค็นหมดอายุ
โทเค็นเพื่อการเข้าถึงมีอายุสั้น และมักจะใช้งานได้ภายในเวลาไม่กี่นาที
การเพิกถอนโทเค็น
เจ้าของบัญชี Google อาจเพิกถอนความยินยอมที่ให้ไว้ก่อนหน้านี้เมื่อใดก็ได้ เพราะจะทำให้โทเค็นเพื่อการเข้าถึงที่มีอยู่ใช้งานไม่ได้และรีเฟรชโทเค็น ระบบอาจทริกเกอร์การเพิกถอนจากแพลตฟอร์มของคุณโดยใช้ revoke()
หรือผ่านบัญชี Google
แทนที่ การอ้างอิงไคลเอ็นต์ Google Sign-In JavaScript: ด้วย Google Identity Services ดังนี้
วิธีการ:
getAuthInstance().disconnect()
ร่วมกับgoogle.accounts.oauth2.revoke()
GoogleUser.disconnect()
ร่วมกับgoogle.accounts.oauth2.revoke()
โทรหา revoke
เมื่อผู้ใช้ลบบัญชีบนแพลตฟอร์มของคุณ หรือต้องการนําความยินยอมที่จะแชร์ข้อมูลกับแอปของคุณออก
ข้อความแจ้งความยินยอมของผู้ใช้
Google จะแสดงกล่องโต้ตอบความยินยอมแก่ผู้ใช้เมื่อเว็บแอปหรือแพลตฟอร์มแบ็กเอนด์ขอโทเค็นเพื่อการเข้าถึง ดูตัวอย่างกล่องโต้ตอบความยินยอมที่ Google แสดงแก่ผู้ใช้
ก่อนที่จะออกโทเค็นเพื่อการเข้าถึงแอป จะต้องมีเซสชัน Google ที่มีอยู่และใช้งานอยู่เพื่อแจ้งความยินยอมของผู้ใช้และบันทึกผลลัพธ์ ผู้ใช้อาจต้องลงชื่อเข้าใช้บัญชี Google ถ้าเซสชันที่มีอยู่นั้นยังไม่ได้เกิดขึ้น
การลงชื่อเข้าใช้ของผู้ใช้
ผู้ใช้อาจลงชื่อเข้าใช้บัญชี Google ในแท็บเบราว์เซอร์ที่แยกต่างหาก หรือลงชื่อเข้าใช้ผ่านเบราว์เซอร์หรือระบบปฏิบัติการ เราขอแนะนำให้เพิ่มลงชื่อเข้าใช้ด้วย Google ลงในเว็บไซต์เพื่อสร้างเซสชันที่ใช้งานอยู่ระหว่างบัญชี Google และเบราว์เซอร์เมื่อผู้ใช้เปิดแอปเป็นครั้งแรก การทำเช่นนี้จะให้ประโยชน์ดังต่อไปนี้
- ลดจำนวนครั้งที่ผู้ใช้ต้องลงชื่อเข้าใช้ โดยการขอโทเค็นเพื่อการเข้าถึงจะเป็นการเริ่มกระบวนการลงชื่อเข้าใช้บัญชี Google หากยังไม่มีเซสชันที่ใช้งานอยู่
- ใช้ช่องข้อมูลเข้าสู่ระบบ
email
ของโทเค็นรหัส JWT โดยตรงเป็นค่าของพารามิเตอร์login_hint
ในออบเจ็กต์CodeClientConfig
หรือTokenClientConfig
ซึ่งจะเป็นประโยชน์อย่างยิ่งหากแพลตฟอร์มของคุณไม่ได้ดูแลรักษาระบบการจัดการบัญชีผู้ใช้ - ค้นหาและเชื่อมโยงบัญชี Google กับบัญชีผู้ใช้ท้องถิ่นที่มีอยู่ในแพลตฟอร์มของคุณ ซึ่งจะช่วยลดบัญชีที่ซ้ำกันบนแพลตฟอร์ม
- เมื่อมีการสร้างบัญชีในเครื่องใหม่ กล่องโต้ตอบและขั้นตอนการลงชื่อสมัครใช้ของคุณจะแยกจากกล่องโต้ตอบและขั้นตอนการตรวจสอบสิทธิ์ผู้ใช้อย่างชัดเจน เป็นการลดจำนวนขั้นตอนที่ต้องทำและเพิ่มอัตราการออกจากไซต์
หลังจากลงชื่อเข้าใช้และก่อนออกโทเค็นเพื่อการเข้าถึง ผู้ใช้ต้องให้ความยินยอมสำหรับแอปพลิเคชันตามขอบเขตที่ขอ
การตอบกลับโทเค็นและความยินยอม
หลังจากได้รับความยินยอม ระบบจะส่งโทเค็นเพื่อการเข้าถึงพร้อมกับรายการขอบเขตที่ผู้ใช้อนุมัติหรือปฏิเสธ
สิทธิ์แบบละเอียดช่วยให้ผู้ใช้อนุมัติหรือปฏิเสธขอบเขตแต่ละรายการได้ เมื่อขอสิทธิ์เข้าถึงหลายขอบเขต ระบบจะให้สิทธิ์หรือปฏิเสธแต่ละขอบเขตโดยไม่ขึ้นอยู่กับขอบเขตอื่นๆ แอปจะเลือกเปิดใช้ฟีเจอร์และฟังก์ชันการทำงานซึ่งขึ้นอยู่กับขอบเขตแต่ละขอบเขต โดยขึ้นอยู่กับตัวเลือกของผู้ใช้
ขั้นตอนการให้สิทธิ์โดยนัย
แทนที่ การอ้างอิงไคลเอ็นต์ Google Sign-In JavaScript ด้วย Google Identity Services ดังนี้
ออบเจ็กต์:
gapi.auth2.AuthorizeResponse
ร่วมกับTokenClient.TokenResponse
gapi.auth2.AuthResponse
ร่วมกับTokenClient.TokenResponse
วิธีการ:
GoogleUser.hasGrantedScopes()
กับgoogle.accounts.oauth2.hasGrantedAllScopes()
GoogleUser.getGrantedScopes()
กับgoogle.accounts.oauth2.hasGrantedAllScopes()
นำ ข้อมูลอ้างอิงไคลเอ็นต์ JavaScript ของ Google Sign-In ออก ดังนี้
วิธีการ:
GoogleUser.getAuthResponse()
อัปเดตเว็บแอปด้วย hasGrantedAllScopes()
และ
hasGrantedAnyScope()
โดยทำตามตัวอย่างสิทธิ์แบบละเอียดนี้
ขั้นตอนรหัสการให้สิทธิ์
อัปเดตหรือเพิ่มปลายทางของรหัสการให้สิทธิ์ลงในแพลตฟอร์มแบ็กเอนด์โดยทำตามวิธีการในการจัดการรหัสการให้สิทธิ์
อัปเดตแพลตฟอร์มของคุณเพื่อทำตามขั้นตอนที่อธิบายไว้ในคู่มือใช้โมเดลโค้ดเพื่อตรวจสอบคำขอ รับโทเค็นเพื่อการเข้าถึง แล้วรีเฟรชโทเค็น
อัปเดตแพลตฟอร์มเพื่อเลือกเปิดหรือปิดใช้ฟีเจอร์และฟังก์ชันการทำงานตามขอบเขตแต่ละรายการที่ผู้ใช้อนุมัติโดยทำตามวิธีการสำหรับการให้สิทธิ์เพิ่มขึ้นและตรวจสอบขอบเขตการเข้าถึงที่ผู้ใช้อนุญาต
ตัวอย่างโฟลว์แบบไม่เจาะจงปลายทาง
วิธีเดิม
ไลบรารีของไคลเอ็นต์ GAPI
ตัวอย่างไลบรารีของไคลเอ็นต์ Google API สำหรับ JavaScript ที่ทำงานอยู่ในเบราว์เซอร์โดยใช้กล่องโต้ตอบป๊อปอัปสำหรับความยินยอมของผู้ใช้
โมดูล gapi.auth2
จะโหลดและใช้โดย
gapi.client.init()
โดยอัตโนมัติ และโมดูลดังกล่าวก็ซ่อนไป
<!DOCTYPE html>
<html>
<head>
<script src="https://apis.google.com/js/api.js"></script>
<script>
function start() {
gapi.client.init({
'apiKey': 'YOUR_API_KEY',
'clientId': 'YOUR_CLIENT_ID',
'scope': 'https://www.googleapis.com/auth/cloud-translation',
'discoveryDocs': ['https://www.googleapis.com/discovery/v1/apis/translate/v2/rest'],
}).then(function() {
// Execute an API request which is returned as a Promise.
// The method name language.translations.list comes from the API discovery.
return gapi.client.language.translations.list({
q: 'hello world',
source: 'en',
target: 'de',
});
}).then(function(response) {
console.log(response.result.data.translations[0].translatedText);
}, function(reason) {
console.log('Error: ' + reason.result.error.message);
});
};
// Load the JavaScript client library and invoke start afterwards.
gapi.load('client', start);
</script>
</head>
<body>
<div id="results"></div>
</body>
</html>
ไลบรารีของไคลเอ็นต์ JS
OAuth 2.0 สำหรับเว็บแอปพลิเคชันฝั่งไคลเอ็นต์ที่ทำงานในเบราว์เซอร์โดยใช้กล่องโต้ตอบป๊อปอัปเพื่อขอความยินยอมของผู้ใช้
โมดูล gapi.auth2
โหลดด้วยตนเอง
<!DOCTYPE html>
<html><head></head><body>
<script>
var GoogleAuth;
var SCOPE = 'https://www.googleapis.com/auth/drive.metadata.readonly';
function handleClientLoad() {
// Load the API's client and auth2 modules.
// Call the initClient function after the modules load.
gapi.load('client:auth2', initClient);
}
function initClient() {
// In practice, your app can retrieve one or more discovery documents.
var discoveryUrl = 'https://www.googleapis.com/discovery/v1/apis/drive/v3/rest';
// Initialize the gapi.client object, which app uses to make API requests.
// Get API key and client ID from API Console.
// 'scope' field specifies space-delimited list of access scopes.
gapi.client.init({
'apiKey': 'YOUR_API_KEY',
'clientId': 'YOUR_CLIENT_ID',
'discoveryDocs': [discoveryUrl],
'scope': SCOPE
}).then(function () {
GoogleAuth = gapi.auth2.getAuthInstance();
// Listen for sign-in state changes.
GoogleAuth.isSignedIn.listen(updateSigninStatus);
// Handle initial sign-in state. (Determine if user is already signed in.)
var user = GoogleAuth.currentUser.get();
setSigninStatus();
// Call handleAuthClick function when user clicks on
// "Sign In/Authorize" button.
$('#sign-in-or-out-button').click(function() {
handleAuthClick();
});
$('#revoke-access-button').click(function() {
revokeAccess();
});
});
}
function handleAuthClick() {
if (GoogleAuth.isSignedIn.get()) {
// User is authorized and has clicked "Sign out" button.
GoogleAuth.signOut();
} else {
// User is not signed in. Start Google auth flow.
GoogleAuth.signIn();
}
}
function revokeAccess() {
GoogleAuth.disconnect();
}
function setSigninStatus() {
var user = GoogleAuth.currentUser.get();
var isAuthorized = user.hasGrantedScopes(SCOPE);
if (isAuthorized) {
$('#sign-in-or-out-button').html('Sign out');
$('#revoke-access-button').css('display', 'inline-block');
$('#auth-status').html('You are currently signed in and have granted ' +
'access to this app.');
} else {
$('#sign-in-or-out-button').html('Sign In/Authorize');
$('#revoke-access-button').css('display', 'none');
$('#auth-status').html('You have not authorized this app or you are ' +
'signed out.');
}
}
function updateSigninStatus() {
setSigninStatus();
}
</script>
<button id="sign-in-or-out-button"
style="margin-left: 25px">Sign In/Authorize</button>
<button id="revoke-access-button"
style="display: none; margin-left: 25px">Revoke access</button>
<div id="auth-status" style="display: inline; padding-left: 25px"></div><hr>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
<script async defer src="https://apis.google.com/js/api.js"
onload="this.onload=function(){};handleClientLoad()"
onreadystatechange="if (this.readyState === 'complete') this.onload()">
</script>
</body></html>
ปลายทาง OAuth 2.0
OAuth 2.0 สำหรับเว็บแอปพลิเคชันฝั่งไคลเอ็นต์ที่ทำงานในเบราว์เซอร์โดยใช้การเปลี่ยนเส้นทางไปที่ Google สำหรับความยินยอมของผู้ใช้
ตัวอย่างนี้แสดงการเรียกโดยตรงไปยังปลายทาง OAuth 2.0 ของ Google จากเบราว์เซอร์ของผู้ใช้ และไม่ได้ใช้โมดูล gapi.auth2
หรือไลบรารี JavaScript
<!DOCTYPE html>
<html><head></head><body>
<script>
var YOUR_CLIENT_ID = 'REPLACE_THIS_VALUE';
var YOUR_REDIRECT_URI = 'REPLACE_THIS_VALUE';
var fragmentString = location.hash.substring(1);
// Parse query string to see if page request is coming from OAuth 2.0 server.
var params = {};
var regex = /([^&=]+)=([^&]*)/g, m;
while (m = regex.exec(fragmentString)) {
params[decodeURIComponent(m[1])] = decodeURIComponent(m[2]);
}
if (Object.keys(params).length > 0) {
localStorage.setItem('oauth2-test-params', JSON.stringify(params) );
if (params['state'] && params['state'] == 'try_sample_request') {
trySampleRequest();
}
}
// If there's an access token, try an API request.
// Otherwise, start OAuth 2.0 flow.
function trySampleRequest() {
var params = JSON.parse(localStorage.getItem('oauth2-test-params'));
if (params && params['access_token']) {
var xhr = new XMLHttpRequest();
xhr.open('GET',
'https://www.googleapis.com/drive/v3/about?fields=user&' +
'access_token=' + params['access_token']);
xhr.onreadystatechange = function (e) {
if (xhr.readyState === 4 && xhr.status === 200) {
console.log(xhr.response);
} else if (xhr.readyState === 4 && xhr.status === 401) {
// Token invalid, so prompt for user permission.
oauth2SignIn();
}
};
xhr.send(null);
} else {
oauth2SignIn();
}
}
/*
* Create form to request access token from Google's OAuth 2.0 server.
*/
function oauth2SignIn() {
// Google's OAuth 2.0 endpoint for requesting an access token
var oauth2Endpoint = 'https://accounts.google.com/o/oauth2/v2/auth';
// Create element to open OAuth 2.0 endpoint in new window.
var form = document.createElement('form');
form.setAttribute('method', 'GET'); // Send as a GET request.
form.setAttribute('action', oauth2Endpoint);
// Parameters to pass to OAuth 2.0 endpoint.
var params = {'client_id': YOUR_CLIENT_ID,
'redirect_uri': YOUR_REDIRECT_URI,
'scope': 'https://www.googleapis.com/auth/drive.metadata.readonly',
'state': 'try_sample_request',
'include_granted_scopes': 'true',
'response_type': 'token'};
// Add form parameters as hidden input values.
for (var p in params) {
var input = document.createElement('input');
input.setAttribute('type', 'hidden');
input.setAttribute('name', p);
input.setAttribute('value', params[p]);
form.appendChild(input);
}
// Add form to page and submit it to open the OAuth 2.0 endpoint.
document.body.appendChild(form);
form.submit();
}
</script>
<button onclick="trySampleRequest();">Try sample request</button>
</body></html>
รูปแบบใหม่
GIS เท่านั้น
ตัวอย่างนี้แสดงเฉพาะไลบรารี JavaScript ของ Google Identity Service ที่ใช้โมเดลโทเค็นและกล่องโต้ตอบป๊อปอัปสำหรับความยินยอมของผู้ใช้ ข้อมูลนี้มีไว้เพื่อแสดงตัวอย่างจำนวนขั้นตอนขั้นต่ำที่จำเป็นในการกำหนดค่าไคลเอ็นต์ คำขอ และรับโทเค็นเพื่อการเข้าถึง รวมถึงการเรียกใช้ Google API
<!DOCTYPE html>
<html>
<head>
<script src="https://accounts.google.com/gsi/client" onload="initClient()" async defer></script>
</head>
<body>
<script>
var client;
var access_token;
function initClient() {
client = google.accounts.oauth2.initTokenClient({
client_id: 'YOUR_CLIENT_ID',
scope: 'https://www.googleapis.com/auth/calendar.readonly \
https://www.googleapis.com/auth/contacts.readonly',
callback: (tokenResponse) => {
access_token = tokenResponse.access_token;
},
});
}
function getToken() {
client.requestAccessToken();
}
function revokeToken() {
google.accounts.oauth2.revoke(access_token, () => {console.log('access token revoked')});
}
function loadCalendar() {
var xhr = new XMLHttpRequest();
xhr.open('GET', 'https://www.googleapis.com/calendar/v3/calendars/primary/events');
xhr.setRequestHeader('Authorization', 'Bearer ' + access_token);
xhr.send();
}
</script>
<h1>Google Identity Services Authorization Token model</h1>
<button onclick="getToken();">Get access token</button><br><br>
<button onclick="loadCalendar();">Load Calendar</button><br><br>
<button onclick="revokeToken();">Revoke token</button>
</body>
</html>
GAPI async/await
ตัวอย่างนี้แสดงวิธีเพิ่มไลบรารี Google 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 ที่ทำงานอยู่ในเบราว์เซอร์ของผู้ใช้ ซึ่งจะพร็อกซีการตอบสนองไปยังแพลตฟอร์มของคุณ ในทั้งสองกรณี แพลตฟอร์มแบ็กเอนด์จะดำเนินการขั้นตอน 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 <form> element to submit parameters to OAuth 2.0 endpoint.
var form = document.createElement('form');
form.setAttribute('method', 'GET'); // Send as a GET request.
form.setAttribute('action', oauth2Endpoint);
// Parameters to pass to OAuth 2.0 endpoint.
var params = {'client\_id': 'YOUR_CLIENT_ID',
'redirect\_uri': 'YOUR_AUTHORIZATION_CODE_ENDPOINT_URL',
'response\_type': 'token',
'scope': 'https://www.googleapis.com/auth/drive.metadata.readonly',
'include\_granted\_scopes': 'true',
'state': 'pass-through value'};
// Add form parameters as hidden input values.
for (var p in params) {
var input = document.createElement('input');
input.setAttribute('type', 'hidden');
input.setAttribute('name', p);
input.setAttribute('value', params[p]);
form.appendChild(input);
}
// Add form to page and submit it to open the OAuth 2.0 endpoint.
document.body.appendChild(form);
form.submit();
}
รูปแบบใหม่
UX ป๊อปอัป GIS
ตัวอย่างนี้แสดงเฉพาะไลบรารี JavaScript ของ Google Identity Service โดยใช้โมเดลรหัสการให้สิทธิ์ กล่องโต้ตอบป๊อปอัปสำหรับความยินยอมของผู้ใช้และตัวแฮนเดิลเรียกกลับเพื่อรับรหัสการให้สิทธิ์จาก Google ข้อมูลนี้มีไว้เพื่อแสดงให้เห็นจำนวนขั้นตอนขั้นต่ำที่จำเป็นในการกำหนดค่าไคลเอ็นต์ ขอคำยินยอม และส่งรหัสการให้สิทธิ์ไปยังแพลตฟอร์มแบ็กเอนด์
<!DOCTYPE html>
<html>
<head>
<script src="https://accounts.google.com/gsi/client" onload="initClient()" async defer></script>
</head>
<body>
<script>
var client;
function initClient() {
client = google.accounts.oauth2.initCodeClient({
client_id: 'YOUR_CLIENT_ID',
scope: 'https://www.googleapis.com/auth/calendar.readonly',
ux_mode: 'popup',
callback: (response) => {
var code_receiver_uri = 'YOUR_AUTHORIZATION_CODE_ENDPOINT_URI',
// Send auth code to your backend platform
const xhr = new XMLHttpRequest();
xhr.open('POST', code_receiver_uri, true);
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
xhr.onload = function() {
console.log('Signed in as: ' + xhr.responseText);
};
xhr.send('code=' + response.code);
// After receipt, the code is exchanged for an access token and
// refresh token, and the platform then updates this web app
// running in user's browser with the requested calendar info.
},
});
}
function getAuthCode() {
// Request authorization code and obtain user consent
client.requestCode();
}
</script>
<button onclick="getAuthCode();">Load Your Calendar</button>
</body>
</html>
UX การเปลี่ยนเส้นทาง GIS
โมเดลรหัสการให้สิทธิ์รองรับป๊อปอัปและเปลี่ยนเส้นทางโหมด UX เพื่อส่งรหัสการให้สิทธิ์ต่อผู้ใช้ไปยังปลายทางที่แพลตฟอร์มโฮสต์ โหมด UX การเปลี่ยนเส้นทางจะแสดงที่นี่
<!DOCTYPE html>
<html>
<head>
<script src="https://accounts.google.com/gsi/client" onload="initClient()" async defer></script>
</head>
<body>
<script>
var client;
function initClient() {
client = google.accounts.oauth2.initCodeClient({
client_id: 'YOUR_CLIENT_ID',
scope: 'https://www.googleapis.com/auth/calendar.readonly \
https://www.googleapis.com/auth/photoslibrary.readonly',
ux_mode: 'redirect',
redirect_uri: 'YOUR_AUTHORIZATION_CODE_ENDPOINT_URI'
});
}
// Request an access token
function getAuthCode() {
// Request authorization code and obtain user consent
client.requestCode();
}
</script>
<button onclick="getAuthCode();">Load Your Calendar</button>
</body>
</html>
ไลบรารี JavaScript
บริการข้อมูลประจำตัวของ Google คือไลบรารี JavaScript แบบเดียวที่ใช้สำหรับการตรวจสอบสิทธิ์และการให้สิทธิ์ผู้ใช้ ซึ่งรวมและแทนที่ฟีเจอร์และฟังก์ชันการทำงานที่พบในไลบรารีและโมดูลต่างๆ ดังนี้
สิ่งที่ต้องทําเมื่อย้ายข้อมูลไปยัง Identity Services
ไลบรารี JS ที่มีอยู่ | ไลบรารี JS ใหม่ | Notes |
---|---|---|
apis.google.com/js/api.js |
accounts.google.com/gsi/client |
เพิ่มไลบรารีใหม่และทำตามขั้นตอนโดยนัย |
apis.google.com/js/client.js |
accounts.google.com/gsi/client |
เพิ่มไลบรารีใหม่และขั้นตอนรหัสการให้สิทธิ์ |
ข้อมูลอ้างอิงด่วนของคลังเพลง
การเปรียบเทียบออบเจ็กต์และวิธีการระหว่างไลบรารี ไคลเอ็นต์ Google Sign-In JavaScript เก่า กับไลบรารี Google Identity Services ใหม่ และหมายเหตุที่มีข้อมูลและการดำเนินการเพิ่มเติมที่ต้องทำระหว่างการย้ายข้อมูล
เก่า | ใหม่ | Notes |
---|---|---|
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 และโทเค็นรหัส Connect ID ในการตอบสนองเดียว
ตัวอย่างการตอบกลับที่มีทั้ง 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"
}
}