ภาพรวม
Google มีไลบรารี JavaScript หลายรายการเพื่อรับโทเค็นเพื่อการเข้าถึงต่อผู้ใช้เพื่อเรียกใช้ Google API ดังนี้
คู่มือนี้มีวิธีการย้ายข้อมูลจากไลบรารีเหล่านี้ไปยังไลบรารี Google Identity Services
การทำตามคำแนะนำนี้จะช่วยให้คุณทำสิ่งต่อไปนี้ได้
- แทนที่ Platform Library ที่เลิกใช้งานแล้วด้วย Identity Services Library และ
- หากใช้ไลบรารีของไคลเอ็นต์ API ให้นำโมดูล
gapi.auth2
ที่เลิกใช้แล้ว เมธอดและออบเจ็กต์ของโมดูลออก แล้วแทนที่ด้วยรายการที่เทียบเท่ากับ Identity Services
โปรดอ่านภาพรวมและวิธีที่การให้สิทธิ์ของผู้ใช้ทำงานเพื่อดูคำอธิบายเกี่ยวกับสิ่งที่เปลี่ยนแปลงในไลบรารี JavaScript ของบริการระบุตัวตน และตรวจสอบคำศัพท์และแนวคิดสำคัญ
หากคุณกำลังมองหาการตรวจสอบสิทธิ์สำหรับการลงชื่อสมัครใช้และลงชื่อเข้าใช้ของผู้ใช้ โปรดดูการย้ายข้อมูลจาก 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
ในกรณีส่วนใหญ่ เราขอแนะนำให้ใช้ขั้นตอนรหัสการให้สิทธิ์เนื่องจากมี การรักษาความปลอดภัยของผู้ใช้ในระดับสูงสุด การใช้ขั้นตอนการทำงานนี้ยังช่วยให้แพลตฟอร์มของคุณเพิ่มฟังก์ชันการทำงานแบบออฟไลน์ใหม่ๆ ได้ด้วย เช่น การดึงข้อมูลอัปเดตเพื่อแจ้งให้ผู้ใช้ทราบถึงการเปลี่ยนแปลงที่สำคัญในปฏิทิน รูปภาพ และการติดตาม
เลือกโฟลว์การให้สิทธิ์โดยใช้ตัวเลือก
ขั้นตอนการให้สิทธิ์โดยนัย
รับโทเค็นเพื่อการเข้าถึงสำหรับการใช้งานในเบราว์เซอร์ขณะที่ผู้ใช้อยู่
ตัวอย่างโฟลว์โดยนัยแสดงเว็บแอปก่อนและหลังการย้ายข้อมูลไปยัง บริการระบุตัวตน
ขั้นตอนรหัสการให้สิทธิ์
ระบบจะส่งรหัสการให้สิทธิ์ต่อผู้ใช้ที่ Google ออกให้ไปยังแพลตฟอร์มแบ็กเอนด์ของคุณ จากนั้นจะแลกรหัสดังกล่าวเป็นโทเค็นเพื่อการเข้าถึงและโทเค็นการรีเฟรช
ตัวอย่างโฟลว์รหัสการให้สิทธิ์แสดงเว็บแอปก่อนและหลัง การย้ายข้อมูลไปยังบริการระบุตัวตน
ตลอดทั้งคู่มือนี้ ให้ทำตามวิธีการที่แสดงเป็นตัวหนาเพื่อเพิ่ม นำออก อัปเดต หรือแทนที่ฟังก์ชันการทำงานที่มีอยู่
การเปลี่ยนแปลงในเว็บแอปในเบราว์เซอร์
ส่วนนี้จะตรวจสอบการเปลี่ยนแปลงที่คุณจะทำกับเว็บแอปในเบราว์เซอร์เมื่อย้ายข้อมูลไปยังไลบรารี JavaScript ของ Google Identity Services
ระบุโค้ดที่ได้รับผลกระทบและทดสอบ
คุกกี้แก้ไขข้อบกพร่องจะช่วยค้นหาโค้ดที่ได้รับผลกระทบและทดสอบลักษณะการทำงานหลังการเลิกใช้งานได้
ในแอปขนาดใหญ่หรือซับซ้อน คุณอาจค้นหาโค้ดทั้งหมดที่ได้รับผลกระทบจากการ
เลิกใช้งานโมดูล gapi.auth2
ได้ยาก หากต้องการบันทึกการใช้งานฟังก์ชันที่จะเลิกใช้งานในเร็วๆ นี้ลงในคอนโซล ให้ตั้งค่าG_AUTH2_MIGRATION
คุกกี้เป็น informational
ไม่บังคับ: เพิ่มโคลอนตามด้วยค่าคีย์เพื่อบันทึกลงในที่เก็บข้อมูลเซสชันด้วย หลังจากลงชื่อเข้าใช้
และได้รับการตรวจสอบข้อมูลเข้าสู่ระบบ หรือส่งบันทึกที่รวบรวมไปยังแบ็กเอนด์เพื่อวิเคราะห์ในภายหลัง
เช่น informational:showauth2use
จะบันทึกต้นทางและ URL ไปยังคีย์พื้นที่เก็บข้อมูลเซสชันชื่อ showauth2use
หากต้องการยืนยันลักษณะการทำงานของแอปเมื่อระบบไม่โหลดโมดูล gapi.auth2
อีกต่อไป ให้ตั้งค่า
คุกกี้ G_AUTH2_MIGRATION
เป็น enforced
ซึ่งจะช่วยให้ทดสอบ
ลักษณะการทำงานหลังการเลิกใช้งานได้ก่อนวันที่บังคับใช้
ค่าคุกกี้ที่เป็นไปได้ของ G_AUTH2_MIGRATION
enforced
อย่าโหลดโมดูลgapi.auth2
informational
บันทึกการใช้ฟังก์ชันที่เลิกใช้งานแล้วไปยังคอนโซล JS และบันทึกลงในที่เก็บข้อมูลเซสชันเมื่อตั้งชื่อคีย์ที่ไม่บังคับ ดังนี้informational:key-name
เราขอแนะนำให้คุณตั้งค่าคุกกี้นี้ในเครื่องก่อน ระหว่างการพัฒนาและการทดสอบ ก่อนที่จะนำไปใช้ในสภาพแวดล้อมการใช้งานจริง เพื่อลดผลกระทบต่อผู้ใช้
ไลบรารีและโมดูล
โมดูล gapi.auth2
จัดการการตรวจสอบสิทธิ์ของผู้ใช้สำหรับการลงชื่อเข้าใช้และโฟลว์โดยนัย
สำหรับการให้สิทธิ์ ให้แทนที่โมดูลที่เลิกใช้งานแล้วนี้ รวมถึงออบเจ็กต์และ
เมธอดของโมดูลด้วยไลบรารี Google Identity Services
เพิ่มไลบรารีบริการข้อมูลประจำตัวลงในเว็บแอปโดยใส่ไว้ในเอกสาร
<script src="https://accounts.google.com/gsi/client" async defer></script>
นำอินสแตนซ์ทั้งหมดของการโหลดโมดูล auth2
โดยใช้ gapi.load('auth2',
function)
ออก
ไลบรารีบริการระบุตัวตนของ Google จะแทนที่การใช้โมดูล 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 APIs Node.js Client
สถานะเซสชัน
ก่อนหน้านี้ การลงชื่อเข้าใช้ด้วย Google ช่วยให้คุณจัดการสถานะการลงชื่อเข้าใช้ของผู้ใช้ได้โดยใช้สิ่งต่อไปนี้
- ตัวแฮนเดิลการเรียกกลับสำหรับการตรวจสอบสถานะเซสชันของผู้ใช้
- Listeners สำหรับเหตุการณ์และการเปลี่ยนแปลงสถานะการลงชื่อเข้าใช้สำหรับบัญชี Google ของผู้ใช้
คุณมีหน้าที่รับผิดชอบในการจัดการสถานะการลงชื่อเข้าใช้และเซสชันของผู้ใช้ในเว็บแอป
นำการอ้างอิงไคลเอ็นต์ JavaScript ของ Google Sign-In เหล่านี้ออก
ออบเจ็กต์
gapi.auth2.SignInOptions
วิธีการ
GoogleAuth.attachClickHandler()
GoogleAuth.isSignedIn()
GoogleAuth.isSignedIn.get()
GoogleAuth.isSignedIn.listen()
GoogleAuth.signIn()
GoogleAuth.signOut()
GoogleAuth.currentUser.get()
GoogleAuth.currentUser.listen()
GoogleUser.isSignedIn()
การกำหนดค่าไคลเอ็นต์
อัปเดตเว็บแอปเพื่อเริ่มต้นไคลเอ็นต์โทเค็นสำหรับโฟลว์รหัสการให้สิทธิ์โดยนัยหรือ
นำการอ้างอิงไคลเอ็นต์ JavaScript ของ Google Sign-In เหล่านี้ออก
ออบเจ็กต์
gapi.auth2.ClientConfig
gapi.auth2.OfflineAccessOptions
วิธีการ
gapi.auth2.getAuthInstance()
GoogleUser.grant()
ขั้นตอนการให้สิทธิ์โดยนัย
เพิ่มTokenClientConfig
ออบเจ็กต์และinitTokenClient()
เรียกใช้
เพื่อกำหนดค่าเว็บแอปตามตัวอย่างในเริ่มต้นไคลเอ็นต์
โทเค็น
แทนที่ การอ้างอิงไคลเอ็นต์ JavaScript ของ Google Sign-In ด้วย Google Identity Services:
ออบเจ็กต์
- จำนวนเงิน
gapi.auth2.AuthorizeConfig
ด้วยบัตรTokenClientConfig
วิธีการ
- จำนวนเงิน
gapi.auth2.init()
ด้วยบัตรgoogle.accounts.oauth2.initTokenClient()
พารามิเตอร์ ได้แก่
gapi.auth2.AuthorizeConfig.login_hint
ด้วยTokenClientConfig.login_hint
gapi.auth2.GoogleUser.getHostedDomain()
ด้วยTokenClientConfig.hd
ขั้นตอนรหัสการให้สิทธิ์
เพิ่มออบเจ็กต์ CodeClientConfig
และเรียกใช้ initCodeClient()
เพื่อกำหนดค่า
เว็บแอปตามตัวอย่างในเริ่มต้นไคลเอ็นต์โค้ด
เมื่อเปลี่ยนจากขั้นตอนโดยนัยเป็นขั้นตอนรหัสการให้สิทธิ์ ให้ทำดังนี้
นำ การอ้างอิงไคลเอ็นต์ JavaScript ของการลงชื่อเข้าใช้ด้วย Google ออก
ออบเจ็กต์
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
เพื่อแยกคำขอเดียวสำหรับขอบเขตหลายรายการ ออกเป็นคำขอที่เล็กลงหลายรายการ - ขอโทเค็นใหม่เมื่อโทเค็นที่มีอยู่หมดอายุหรือถูกเพิกถอน
การทำงานกับขอบเขตหลายรายการอาจต้องมีการเปลี่ยนแปลงโครงสร้างในโค้ดเบส เพื่อขอสิทธิ์เข้าถึงขอบเขตเฉพาะเมื่อจำเป็นเท่านั้น แทนที่จะขอทั้งหมดในครั้งเดียว ซึ่งเรียกว่าการให้สิทธิ์แบบเพิ่มทีละรายการ คำขอแต่ละรายการควรมีขอบเขตน้อยที่สุดเท่าที่จะเป็นไปได้ และควรมีขอบเขตเดียว ดูข้อมูลเพิ่มเติมเกี่ยวกับวิธีอัปเดตแอปเพื่อการให้สิทธิ์แบบค่อยเป็นค่อยไปได้ที่วิธีจัดการความยินยอมของผู้ใช้
เมื่อโทเค็นเพื่อการเข้าถึงหมดอายุ gapi.auth2
โมดูลจะรับโทเค็นเพื่อการเข้าถึงใหม่ที่ใช้งานได้สำหรับเว็บแอปของคุณโดยอัตโนมัติ
เพื่อปรับปรุงความปลอดภัยของผู้ใช้ ไลบรารีบริการระบุตัวตนของ Google ไม่รองรับกระบวนการรีเฟรชโทเค็นอัตโนมัตินี้
คุณต้องอัปเดตเว็บแอปเพื่อตรวจหาโทเค็นเพื่อการเข้าถึงที่หมดอายุและขอโทเค็นใหม่ ดูข้อมูลเพิ่มเติมได้ที่ส่วนการจัดการโทเค็น
ขั้นตอนรหัสการให้สิทธิ์
เพิ่มลิงก์หรือปุ่มเพื่อเรียกใช้ requestCode()
เพื่อขอรหัสการให้สิทธิ์
จาก Google ดูตัวอย่างได้ที่ทริกเกอร์ขั้นตอนรหัส OAuth 2.0
ดูข้อมูลเพิ่มเติมเกี่ยวกับวิธีตอบสนองต่อโทเค็นเพื่อการเข้าถึงที่หมดอายุหรือถูกเพิกถอนได้ที่ส่วนการจัดการโทเค็น
การจัดการโทเค็น
เพิ่มการจัดการข้อผิดพลาดเพื่อตรวจหาการเรียก Google API ที่ล้มเหลวเมื่อใช้โทเค็นเพื่อการเข้าถึงที่หมดอายุหรือ ถูกเพิกถอน และเพื่อขอโทเค็นเพื่อการเข้าถึงใหม่ที่ถูกต้อง
Google APIs จะแสดงรหัสสถานะ HTTP 401 Unauthorized
และข้อความแสดงข้อผิดพลาด invalid_token
เมื่อมีการใช้โทเค็นการเข้าถึงที่หมดอายุหรือถูกเพิกถอน ดูตัวอย่างได้ที่การตอบกลับโทเค็นไม่ถูกต้อง
โทเค็นที่หมดอายุ
โทเค็นเพื่อการเข้าถึงมีอายุสั้นและมักจะใช้ได้เพียงไม่กี่นาที
การเพิกถอนโทเค็น
เจ้าของบัญชี Google สามารถเพิกถอนความยินยอมที่ให้ไว้ก่อนหน้านี้ได้ทุกเมื่อ การดำเนินการนี้จะทำให้โทเค็นเพื่อการเข้าถึงและโทเค็นการรีเฟรชที่มีอยู่ไม่ถูกต้อง การเพิกถอนอาจเกิดขึ้นจากแพลตฟอร์มของคุณโดยใช้ revoke()
หรือผ่านบัญชี
Google
แทนที่ การอ้างอิงไคลเอ็นต์ JavaScript ของ Google Sign-In ด้วย Google Identity Services
วิธีการ
- จำนวนเงิน
getAuthInstance().disconnect()
ด้วยบัตรgoogle.accounts.oauth2.revoke()
- จำนวนเงิน
GoogleUser.disconnect()
ด้วยบัตรgoogle.accounts.oauth2.revoke()
เรียกใช้ revoke
เมื่อผู้ใช้ลบบัญชีในแพลตฟอร์มของคุณ หรือ
ต้องการเพิกถอนความยินยอมในการแชร์ข้อมูลกับแอปของคุณ
ข้อความแจ้งความยินยอมของผู้ใช้
Google จะแสดงกล่องโต้ตอบความยินยอมต่อผู้ใช้เมื่อเว็บแอปหรือแพลตฟอร์มแบ็กเอนด์ ของคุณขอโทเค็นเพื่อการเข้าถึง ดูตัวอย่างกล่องโต้ตอบความยินยอมที่ Google แสดงต่อผู้ใช้
ก่อนที่จะออกโทเค็นเพื่อการเข้าถึงให้กับแอปของคุณ คุณต้องมีเซสชัน Google ที่ใช้งานอยู่เพื่อแจ้งให้ขอความยินยอมจากผู้ใช้และบันทึกผลลัพธ์ ระบบอาจกำหนดให้ผู้ใช้ลงชื่อเข้าใช้บัญชี Google หากยังไม่ได้สร้างเซสชันที่มีอยู่
การลงชื่อเข้าใช้ของผู้ใช้
ผู้ใช้อาจลงชื่อเข้าใช้บัญชี Google ในแท็บเบราว์เซอร์แยกต่างหาก หรือโดยตรงผ่านเบราว์เซอร์หรือระบบปฏิบัติการ เราขอแนะนําให้เพิ่มลงชื่อเข้าใช้ด้วย Google ลงในเว็บไซต์เพื่อสร้างเซสชันที่ใช้งานอยู่ระหว่างบัญชี Google กับเบราว์เซอร์เมื่อผู้ใช้เปิดแอปเป็นครั้งแรก การทําเช่นนี้จะมอบประโยชน์ต่อไปนี้
- ลดจำนวนครั้งที่ผู้ใช้ต้องลงชื่อเข้าใช้ โดยการขอโทเค็นการเข้าถึงจะเริ่มกระบวนการลงชื่อเข้าใช้บัญชี Google หากไม่มีเซสชันที่ใช้งานอยู่
- ใช้ฟิลด์ credential
email
ของโทเค็นรหัส JWT โดยตรงเป็นค่าของ พารามิเตอร์login_hint
ในออบเจ็กต์CodeClientConfig
หรือTokenClientConfig
ซึ่งจะเป็นประโยชน์อย่างยิ่งหากแพลตฟอร์มของคุณไม่มี ระบบการจัดการบัญชีผู้ใช้ - ค้นหาและเชื่อมโยงบัญชี Google กับบัญชีผู้ใช้ในเครื่องที่มีอยู่บนแพลตฟอร์มของคุณ เพื่อช่วยลดบัญชีที่ซ้ำกันบนแพลตฟอร์ม
- เมื่อสร้างบัญชีใหม่ในเครื่อง ไดอะล็อกและขั้นตอนการลงชื่อสมัครใช้จะแยกออกจากไดอะล็อกและขั้นตอนการตรวจสอบสิทธิ์ผู้ใช้อย่างชัดเจน ซึ่งจะช่วยลดจำนวนขั้นตอนที่จำเป็นและปรับปรุงอัตราการเลิกกลางคัน
หลังจากลงชื่อเข้าใช้และก่อนที่จะมีการออกโทเค็นเพื่อการเข้าถึง ผู้ใช้ต้องให้ความยินยอม สำหรับแอปพลิเคชันของคุณสำหรับขอบเขตที่ขอ
การตอบกลับของโทเค็นและความยินยอม
หลังจากได้รับความยินยอมแล้ว ระบบจะแสดงโทเค็นเพื่อเข้าถึงพร้อมกับรายการขอบเขตที่ผู้ใช้ อนุมัติหรือปฏิเสธ
สิทธิ์แบบละเอียดช่วยให้ผู้ใช้สามารถอนุมัติหรือปฏิเสธขอบเขตแต่ละรายการได้ เมื่อ ขอสิทธิ์เข้าถึงหลายขอบเขต ระบบจะให้สิทธิ์หรือปฏิเสธแต่ละขอบเขต โดยไม่ขึ้นอยู่กับขอบเขตอื่นๆ แอปของคุณจะเปิดใช้ฟีเจอร์และฟังก์ชันการทำงานที่ขึ้นอยู่กับขอบเขตแต่ละรายการโดยเลือกตามที่ผู้ใช้เลือก
ขั้นตอนการให้สิทธิ์โดยนัย
แทนที่ การอ้างอิงไคลเอ็นต์ JavaScript ของ Google Sign-In ด้วย Google Identity Services:
ออบเจ็กต์
- จำนวนเงิน
gapi.auth2.AuthorizeResponse
ด้วยบัตรTokenClient.TokenResponse
- จำนวนเงิน
gapi.auth2.AuthResponse
ด้วยบัตรTokenClient.TokenResponse
วิธีการ
GoogleUser.hasGrantedScopes()
ที่มีgoogle.accounts.oauth2.hasGrantedAllScopes()
GoogleUser.getGrantedScopes()
ที่มีgoogle.accounts.oauth2.hasGrantedAllScopes()
นำ การอ้างอิงไคลเอ็นต์ JavaScript ของการลงชื่อเข้าใช้ด้วย Google ออกโดยทำดังนี้
วิธีการ
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 Google Cloud 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 ที่ใช้รูปแบบโทเค็นและกล่องโต้ตอบป๊อปอัปสำหรับความยินยอมของผู้ใช้ โดยมีไว้เพื่อแสดงจำนวนขั้นตอนขั้นต่ำที่ต้องใช้ในการกำหนดค่าไคลเอ็นต์ ส่งคำขอและรับโทเค็นการเข้าถึง รวมถึงเรียกใช้ 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>
async/await ของ GAPI
ตัวอย่างนี้แสดงวิธีเพิ่มไลบรารีบริการข้อมูลประจำตัวของ Google โดยใช้
รูปแบบโทเค็น นำโมดูล gapi.auth2
ออก และเรียกใช้ API โดยใช้ไลบรารีของไคลเอ็นต์ Google API สำหรับ JavaScript
ใช้ Promise, async และ await เพื่อบังคับลำดับการโหลดไลบรารี รวมถึงเพื่อ ตรวจหาและลองอีกครั้งสำหรับข้อผิดพลาดในการให้สิทธิ์ ระบบจะเรียก API หลังจากที่โทเค็นเพื่อการเข้าถึงที่ถูกต้องพร้อมใช้งานแล้วเท่านั้น
ผู้ใช้ควรจะกดปุ่ม "แสดงปฏิทิน" เมื่อไม่มีโทเค็นเพื่อการเข้าถึง เมื่อโหลดหน้าเว็บเป็นครั้งแรก หรือหลังจากโทเค็นเพื่อการเข้าถึง หมดอายุแล้ว
<!DOCTYPE html>
<html>
<head>
<title>GAPI and GIS Example</title>
<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="gisLoad()"></script>
</head>
<body>
<h1>GAPI Client with GIS Authorization</h1>
<button id="authorizeBtn" style="visibility:hidden;">Authorize and Load Events</button>
<button id="revokeBtn" style="visibility:hidden;">Revoke Access</button>
<div id="content"></div>
<script>
const YOUR_CLIENT_ID = "YOUR_CLIENT_ID";
const YOUR_API_KEY = 'YOUR_API_KEY';
const CALENDAR_SCOPE = 'https://www.googleapis.com/auth/calendar.readonly';
let tokenClient;
let libsLoaded = 0;
function gapiLoad() {
gapi.load('client', initGapiClient);
}
async function initGapiClient() {
try {
await gapi.client.init({ apiKey: YOUR_API_KEY });
await gapi.client.load('https://www.googleapis.com/discovery/v1/apis/calendar/v3/rest');
console.log('GAPI client initialized.');
checkAllLoaded();
} catch (err) {
handleError('GAPI initialization failed:', err);
}
}
function gisLoad() {
try {
tokenClient = google.accounts.oauth2.initTokenClient({
client_id: YOUR_CLIENT_ID,
scope: CALENDAR_SCOPE,
callback: '', // Will be set dynamically
error_callback: handleGisError,
});
console.log('GIS TokenClient initialized.');
checkAllLoaded();
} catch (err) {
handleError('GIS initialization failed:', err);
}
}
function checkAllLoaded() {
libsLoaded++;
if (libsLoaded === 2) {
document.getElementById('authorizeBtn').style.visibility = 'visible';
document.getElementById('revokeBtn').style.visibility = 'visible';
document.getElementById('authorizeBtn').onclick = makeApiCall;
document.getElementById('revokeBtn').onclick = revokeAccess;
console.log('Ready to authorize.');
}
}
function handleGisError(err) {
console.error('GIS Error:', err);
let message = 'An error occurred during authorization.';
if (err && err.type === 'popup_failed_to_open') {
message = 'Failed to open popup. Please disable popup blockers.';
} else if (err && err.type === 'popup_closed') {
message = 'Authorization popup was closed.';
}
document.getElementById('content').textContent = message;
}
function handleError(message, error) {
console.error(message, error);
document.getElementById('content').textContent = `${message} ${error.message || JSON.stringify(error)}`;
}
async function makeApiCall() {
document.getElementById('content').textContent = 'Processing...';
try {
let token = gapi.client.getToken();
if (!token || !token.access_token) {
console.log('No token, fetching one...');
await getToken();
}
console.log('Calling Calendar API...');
const response = await gapi.client.calendar.events.list({ 'calendarId': 'primary' });
displayEvents(response.result);
} catch (err) {
console.error('API call failed:', err);
const errorInfo = err.result && err.result.error;
if (errorInfo && (errorInfo.code === 401 || (errorInfo.code === 403 && errorInfo.status === "PERMISSION_DENIED"))) {
console.log('Auth error on API call, refreshing token...');
try {
await getToken({ prompt: 'consent' }); // Force refresh
const retryResponse = await gapi.client.calendar.events.list({ 'calendarId': 'primary' });
displayEvents(retryResponse.result);
} catch (refreshErr) {
handleError('Failed to refresh token or retry API call:', refreshErr);
}
} else {
handleError('Error loading events:', err.result ? err.result.error : err);
}
}
}
async function getToken(options = { prompt: '' }) {
return new Promise((resolve, reject) => {
if (!tokenClient) return reject(new Error("GIS TokenClient not initialized."));
tokenClient.callback = (tokenResponse) => {
if (tokenResponse.error) {
reject(new Error(`Token Error: ${tokenResponse.error} - ${tokenResponse.error_description}`));
} else {
console.log('Token acquired.');
resolve(tokenResponse);
}
};
tokenClient.requestAccessToken(options);
});
}
function displayEvents(result) {
const events = result.items;
if (events && events.length > 0) {
let eventList = '<h3>Upcoming Events:</h3><ul>' + events.map(event =>
`<li>${event.summary} (${event.start.dateTime || event.start.date})</li>`
).join('') + '</ul>';
document.getElementById('content').innerHTML = eventList;
} else {
document.getElementById('content').textContent = 'No upcoming events found.';
}
}
function revokeAccess() {
const token = gapi.client.getToken();
if (token && token.access_token) {
google.accounts.oauth2.revoke(token.access_token, () => {
console.log('Access revoked.');
document.getElementById('content').textContent = 'Access has been revoked.';
gapi.client.setToken(null);
});
} else {
document.getElementById('content').textContent = 'No token to revoke.';
}
}
</script>
</body>
</html>
การเรียกกลับของ GAPI
ตัวอย่างนี้แสดงวิธีเพิ่มไลบรารีบริการข้อมูลประจำตัวของ Google โดยใช้
รูปแบบโทเค็น นำโมดูล gapi.auth2
ออก และเรียกใช้ API โดยใช้ไลบรารีของไคลเอ็นต์ Google API สำหรับ JavaScript
ตัวแปรใช้เพื่อบังคับลำดับการโหลดไลบรารี การเรียกใช้ GAPI จะดำเนินการ จากภายในฟังก์ชันเรียกกลับหลังจากที่ระบบส่งคืนโทเค็นเพื่อการเข้าถึงที่ถูกต้อง
ผู้ใช้ควรจะกดปุ่ม "แสดงปฏิทิน" เมื่อหน้าเว็บโหลดเป็นครั้งแรก และอีกครั้งเมื่อต้องการรีเฟรชข้อมูลปฏิทิน
<!DOCTYPE html>
<html>
<head>
<script async defer src="https://apis.google.com/js/api.js" onload="gapiLoad()"></script>
<script async defer src="https://accounts.google.com/gsi/client" onload="gisInit()"></script>
</head>
<body>
<h1>GAPI with GIS callbacks</h1>
<button id="showEventsBtn" onclick="showEvents();">Show Calendar</button><br><br>
<button id="revokeBtn" onclick="revokeToken();">Revoke access token</button>
<script>
let tokenClient;
let gapiInited;
let gisInited;
document.getElementById("showEventsBtn").style.visibility="hidden";
document.getElementById("revokeBtn").style.visibility="hidden";
function checkBeforeStart() {
if (gapiInited && gisInited){
// Start only when both gapi and gis are initialized.
document.getElementById("showEventsBtn").style.visibility="visible";
document.getElementById("revokeBtn").style.visibility="visible";
}
}
function gapiInit() {
gapi.client.init({
// NOTE: OAuth2 'scope' and 'client_id' parameters have moved to initTokenClient().
})
.then(function() { // Load the Calendar API discovery document.
gapi.client.load('https://www.googleapis.com/discovery/v1/apis/calendar/v3/rest');
gapiInited = true;
checkBeforeStart();
});
}
function gapiLoad() {
gapi.load('client', gapiInit)
}
function gisInit() {
tokenClient = google.accounts.oauth2.initTokenClient({
client_id: 'YOUR_CLIENT_ID',
scope: 'https://www.googleapis.com/auth/calendar.readonly',
callback: '', // defined at request time
});
gisInited = true;
checkBeforeStart();
}
function showEvents() {
tokenClient.callback = (resp) => {
if (resp.error !== undefined) {
throw(resp);
}
// GIS has automatically updated gapi.client with the newly issued access token.
console.log('gapi.client access token: ' + JSON.stringify(gapi.client.getToken()));
gapi.client.calendar.events.list({ 'calendarId': 'primary' })
.then(calendarAPIResponse => console.log(JSON.stringify(calendarAPIResponse)))
.catch(err => console.log(err));
document.getElementById("showEventsBtn").innerText = "Refresh Calendar";
}
// Conditionally ask users to select the Google Account they'd like to use,
// and explicitly obtain their consent to fetch their Calendar.
// NOTE: To request an access token a user gesture is necessary.
if (gapi.client.getToken() === null) {
// Prompt the user to select a Google Account and asked for consent to share their data
// when establishing a new session.
tokenClient.requestAccessToken({prompt: 'consent'});
} else {
// Skip display of account chooser and consent dialog for an existing session.
tokenClient.requestAccessToken({prompt: ''});
}
}
function revokeToken() {
let cred = gapi.client.getToken();
if (cred !== null) {
google.accounts.oauth2.revoke(cred.access_token, () => {console.log('Revoked: ' + cred.access_token)});
gapi.client.setToken('');
document.getElementById("showEventsBtn").innerText = "Show Calendar";
}
}
</script>
</body>
</html>
ตัวอย่างขั้นตอนรหัสการให้สิทธิ์
UX ป๊อปอัปของไลบรารี Google Identity 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 ที่ใช้รูปแบบรหัสการให้สิทธิ์ กล่องโต้ตอบป๊อปอัปสำหรับความยินยอมของผู้ใช้ และ ตัวแฮนเดิลการเรียกกลับเพื่อรับรหัสการให้สิทธิ์จาก 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 เดียวที่ใช้สำหรับการตรวจสอบสิทธิ์และการให้สิทธิ์ผู้ใช้ ซึ่งรวมและแทนที่ฟีเจอร์และฟังก์ชันที่พบในไลบรารีและโมดูลต่างๆ ดังนี้
- ไคลเอ็นต์ JavaScript ของการลงชื่อเข้าใช้ด้วย Google และ
- ไลบรารีของไคลเอ็นต์ Google API สำหรับ 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 |
เพิ่มไลบรารีใหม่และโฟลว์รหัสการให้สิทธิ์ |
ข้อมูลอ้างอิงฉบับย่อของไลบรารี
การเปรียบเทียบออบเจ็กต์และเมธอดระหว่างไลบรารี เก่า Google Sign-In JavaScript client กับไลบรารี ใหม่ 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 | |
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 OAuth 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 จะแสดงผลดังนี้
โทเค็นเพื่อการเข้าถึงเมื่อใช้เพื่อการให้สิทธิ์
{ "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"
}
}