top of page
ค้นหา
รูปภาพนักเขียนSathit Jittanupat

Some sleepless nights with OAuth and Google Drive API scopes

อัปเดตเมื่อ 1 เม.ย. 2567


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


บังเอิญในจังหวะที่ชีวิตรอบตัวกำลังยุ่งเหยิง ก็มีอีเมลแจ้งเตือนเข้ามาอีกครั้งจาก Google Trust and Safety Team


[Day 30 Reminder] Changes to Restricted Scopes API Access

เรื่องที่ทดเอาไว้ว่าจะจัดการแล้วก็ผลัดจนล่วงเลยมานาน กลับมาอ่านคำแนะนำอีกครั้ง ก็ไม่ช่วยให้กระจ่างมากกว่าเดิมสักเท่าไหร่



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


กระบวนการทำงานเพื่อแนบไฟล์ ขึ้นอยู่กับความสะดวก และเครื่องมือที่แตกต่างกัน


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


มีคำแนะนำให้เปลี่ยนไปใช้ ขอบเขตใหม่ /auth/drive.file ที่ปลอดภัยกว่า


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



โยนหินลงในบ่อ

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


ปิดการขอใช้ /auth/drive แล้วเปลี่ยนเป็น /auth/drive.file แทน ลองทดสอบคร่าว ๆ ตามเคสเท่าที่จดรวบรวมไว้ก็น่าจะผ่าน


เช้าวันนั้นเอง เริ่มมีแจ้งปัญหาเข้ามา เริ่มจากน้องในทีมซัพพอร์ต แจ้งว่าไม่สามารถเข้าใช้โปรแกรมได้ หน้าจอมีข้อความฟ้องว่า "แอปนี้ถูกบล็อก"



"ซวยแล้ว" นึกในใจ


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


หากกิจการไม่สามารถเปิดบิลส่งของ เก็บเงินไม่ได้ เพราะความประมาทตั้งค่าผิดพลาด แล้วถอยกลับไปอย่างเดิมไม่ได้จะทำยังไง ผมไม่ทันได้คิดถึงแผนสำรอง หากเกิดความพังทะลายระดับนี้มาก่อน


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


นับว่าเป็นข่าวดีเล็ก ๆ พร้อมกับความสับสน ไม่เข้าใจว่าทำไมออกมาเป็นเช่นนั้น



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


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



ผู้ใช้ส่วนน้อยที่มีปัญหา เกิดจากเหตุบังเอิญ 2 ประการ 


เกิดจากตัวผู้ใช้เองสั่งถอนสิทธิที่เคยอนุญาตออก 


และเกิดจากโปรแกรมเองยังมีโค้ดหลุด ส่วนการทำงานที่ขอใช้ scope เดิมอยู่ ทำให้เกิดข้อความฟ้องว่า "แอปนี้ถูกบล็อก"


เมื่อแก้ไขโปรแกรมอีกครั้ง ก็ไม่มี "แอปนี้ถูกบล็อก" ขึ้นมาแล้ว แต่ยังมีปัญหาที่เกิดจากข้อจำกัดของ scope ใหม่ ที่ต้องหาทางแก้ไขต่อไป


"เฉพาะที่ใช้กับแอปนี้"

จากคำอธิบายของขอบเขตใหม่ /auth/drive.file

ดู แก้ไข สร้าง และลบไฟล์ Google ไดรฟ์เฉพาะที่ใช้กับแอปนี้
See, edit, create, and delete only the specific Google Drive files you use with this app

เทียบกับขอบเขตเดิม /auth/drive


ดู แก้ไข สร้าง และลบไฟล์ Google ไดรฟทั้งหมด
See, edit, create, and delete all of your Google Drive files

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

สุดท้ายจึงได้คำตอบจากการทดลองด้วยตัวเอง


  • หากคุณสั่ง export ข้อมูลในรายงาน เป็นไฟล์ Sheets ที่สร้างใหม่จากโปรแกรม หลังจากนั้นคุณสามารถสั่ง export รายงานจากโปรแกรม ไปแทนที่ข้อมูลเดิม โดยใช้ไฟล์ Sheets นั้นได้

  • หากคุณสร้างไฟล์ Sheets ขึ้นมาใหม่เอง จากหน้าจอ UI ของ Drive หลังจากนั้นคุณสามารถ "ไม่" สามารถสั่ง export รายงานจากโปรแกรม ไปแทนที่ข้อมูลเดิม โดยใช้ไฟล์ Sheets นั้น


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



การทำงานลักษณะนี้ จำเป็นต้องเพิ่ม scope /auth/spreadsheets เพื่อให้โปรแกรมสามารถ อ่านและเขียน ไฟล์ sheets ที่ผู้ใช้มีสิทธิเข้าถึง โดยไม่ต้องติดเงื่อนไข "เฉพาะที่ใช้กับแอปนี้"

Thumbnail ใน Picker

โปรแกรมใช้ Picker API สำหรับการทำงานเลือกรูปภาพจาก Drive เพื่อแนบเข้ากับข้อมูลในโปรแกรม เช่น การบันทึกข้อมูล sales order ก็จะแนบหลักฐานไฟล์ PDF หรือภาพถ่ายของใบสั่งซื้อจากลูกค้า



ปรากฏว่าเมื่อเปลี่ยนไปใช้ scope ใหม่ ภาพตัวอย่างของไฟล์ส่วนใหญ่ที่เคยแสดงให้เห็นตอนเลือก ไม่สามารถแสดงได้ ทำให้การเลือกไฟล์ยากลำบาก ไม่เหมือนเดิม


สันนิษฐานว่า ไฟล์ที่ไม่เข้าเงื่อนไข "เฉพาะที่ใช้กับแอปนี้" ไม่สามารถแสดงภาพตัวอย่าง แต่ที่ย้อนแย้งอยู่ตรงที่ ทำไม Picker ยังแสดงไฟล์เหล่านั้นมาให้เลือก แถมยังสามารถเลือกมาได้ด้วย เมื่อเลือกมาแล้วโปรแกรมก็ไม่สามารถเข้าถึง metadata ใด ๆ เช่น thumbnailLink เพื่อใช้แสดงภาพตัวอย่าง


เพื่อให้ Picker แสดงภาพตัวอย่างของไฟล์ทั้งหมด โดยไม่ติดเงื่อนไข "เฉพาะที่ใช้กับแอปนี้" จำเป็นต้องเพิ่ม scope /auth/docs ซึ่งจำกัดขอบเขตให้สามารถเข้าถึงเฉพาะไฟล์ที่เห็นใน Drive app

100 users limit

ประเด็นความซับซ้อนสำหรับโปรแกรมที่มีผู้ใช้เกิน 100 ราย เมื่อมีการขอใช้ scope ใหม่ ในกลุ่ม sensitive scopes เช่น /auth/spreadsheets , /auth/docs ) หรือ restricted scopes เช่น /auth/drive จะต้องแจ้งขอตรวจสอบก่อน และอาจใช้เวลานานถึง 4–6 สัปดาห์



ระหว่างที่รอตรวจสอบ โปรแกรมมีสถานะเป็น unverified app หากมีการขอใช้ scope เหล่านั้นจะโดนฟ้องว่า "แอปนี้ถูกบล็อก"


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


ยกเว้นโปรแกรมที่ยังมีผู้ใช้ไม่ถึง 100 ราย จะไม่ฟ้อง "แอปนี้ถูกบล็อก" แต่แสดงเป็นข้อความเตือนว่า "hasn't verified this app" สามารถใช้ scope ใหม่ได้ทันที โดยเลือก "advanced" เพื่อเข้าไปสั่งอนุญาต

Workaround

การแก้ปัญหาชั่วคราว กรณีติดข้อจำกัด scope /auth/drive.file ทำให้ไม่สามารถเข้าถึง metadata ของบางไฟล์ และยังไม่สามารถขออนุมัติเพื่อใช้ sensitive scopes เพิ่มเติมได้


1. thumbnailLink 

ไฟล์ใน Drive สามารถเลือกโดยใช้ Picker API ซึ่งอาจเป็นไฟล์ของฉันหรือไฟล์ที่ผู้อื่นแชร์ให้ฉัน


ผู้ใช้มีสามารถเห็นและเรียกดูไฟล์เหล่านั้นผ่าน Drive app ได้ แต่โปรแกรมกลับไม่สามารถเข้าถึงไฟล์เหล่านั้น หากผู้ใช้อนุญาตตามขอบเขตใหม่


โปรแกรมไม่สามารถอ่านค่า thumbnailLink เพื่อแสดงภาพตัวอย่าง แต่มีวิธีใช้ id ของ file มาสร้างเป็น URL เองได้


https://lh3.googleusercontent.com/XXXX 

เงื่อนไขสำคัญของการนำ url นี้มาใช้แสดง จะต้องระบุ referrerpolicy="no-referrer" ไว้ใน tag <img> ด้วย มิฉะนั้นจะเกิด HTTP error 403


<img 
  src="https://lh3.googleusercontent.com/XXXX"
  referrerpolicy="no-referrer"
/>

คำสั่งเพิ่มเติมสำหรับกำหนดเงื่อนไขรูปภาพที่ต้องการดูจาก Gist คำแนะนำ referrerpolicy จาก Stack Overflow

2. webViewLink (alternateLink)

เช่นเดียวกับกรณีของ thumbnail ไฟล์ที่เลือกจาก Picker ได้ แต่โปรแกรมไม่สามารถเข้าถึง ทำให้ไม่สามารถอ่านค่า webViewLink (alternateLink สำหรับ Drive API v2) เพื่อชี้กลับไปหาไฟล์ต้นฉบับใน Drive


ปกติแล้ว Picker จะตอบ embedUrl และ url ซึ่งใช้แทนได้ หรือหากต้องการสร้าง url ขึ้นมาเองจาก id ของ file สามารถทำได้ดังนี้


https://drive.google.com/file/d/XXXX/view?usp=drivesdk

ความหมายของการกำหนดค่า usp ดูได้จาก Stack Overflow



สรุป

เหนื่อย!! อดนอนหลายคืน กว่าจะเรียบเรียงสถานการณ์ออกมาได้ จนวางใจว่ายังพอรับมืออยู่


แอปที่ติดเงื่อนไข 100 users limit ไปแล้ว ไม่มีวิธีง่ายเพื่อทดสอบโปรแกรมตัวเอง เมื่อต้องเปลี่ยนแปลง scopes

  1. เดิมโปรแกรมใช้ Google Drive API scope แบบไม่มีข้อจำกัดมาหลายปี

  2. Google Safety Team แจ้งให้ทบทวน แนะนำให้ตรวจสอบและหากเป็นไปได้ควรเปลี่ยนไปใช้ scope ใหม่ ที่จำกัดขอบเขตเท่าที่จำเป็น

  3. ทดลองเปลี่ยนไปใช้ scope ใหม่ตามคำแนะนำ การใช้งานทั่วไปไม่มีปัญหา

  4. ตัดสินใจเปลี่ยน scope กับโปรแกรมชุดเต็ม แล้วก็เจอปัญหาเคสใช้งานจริงของผู้ใช้บางไซต์ (แชร์ไฟล์และซิงก์ข้อมูลเข้า Sheets)

  5. ผู้ใช้เดิมที่ยังไม่ถอนการอนุญาต scope เดิม ยังคงใช้งานได้เหมือนเดิม 

  6. ผู้ใช้ใหม่หรือผู้ที่ถอนการอนุญาต scope เดิมออก โปรแกรมไม่สามารถถอยกลับไปขออีก จึงต้องใช้ scope ใหม่ที่จำกัดขอบเขต

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

  8. เพื่อให้ทำงานได้เท่า scope เดิม จำเป็นต้องขอใช้ scope เพิ่มเติม แต่ยังไม่สามารถทำได้ทันที จนกว่าจะมีสถานะเป็น verified app

  9. ระหว่างที่รอ reverify app โปรแกรมยังไม่สามารถขอใช้สิทธิเพิ่มเติม เพราะจะติด "แอปนี้ถูกบล็อก" เนื่องจากมีผู้ใช้รวมเกิน 100 ราย จึงต้องปรับโปรแกรมให้ทำงานได้จำกัดเท่าที่ scope ใหม่ยินยอม

  10. รอจนกว่าได้ verified app แล้ว ตอนนั้นจึงค่อยปรับโปรแกรมอีกรอบให้ทำงานกับ scope เพิ่มเติม


โชคที่ยังพอมีอยู่บ้าง บังเอิญออกแบบโปรแกรมให้รองรับการเปลี่ยนผ่านแบบเงียบ ๆ ตรวจว่าหากผู้ใช้เคยอนุญาต scope เดิมอยู่แล้ว ก็ให้โปรแกรมใช้ต่อไป ยังไม่ต้องเปลี่ยนไปขอใช้ scope ใหม่


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


ผู้ที่ได้รับผลกระทบจึงเหลือเฉพาะผู้ใช้ใหม่ หรือผู้ที่ถอนการอนุญาต scope เดิมเท่านั้น


ระหว่างที่ค้นคว้าเรื่องนี้ เจอเรื่องที่ไม่สบายใจซ้อนเข้ามา พบว่าตอนนี้โปรแกรมใช้ Drive API v2 ยังไม่ได้ปรับปรุงให้เป็น v3 ซึ่งการอ้างอิงชื่อข้อมูลสำคัญบางส่วนแตกต่างกันค่อนข้างมาก การค้นคว้าข้อมูลรวมทั้งศึกษาโค้ดตัวอย่าง จะต้องเช็คให้ดีว่าเป็นของ version อะไรกันแน่ และตัวอย่างนั้นล้าสมัยหรือยัง มีงานต้องสะสางโค้ดเกี่ยวกับ Drive API รออยู่


อ้างอิง

Google OAuth and verification status


googleusercontent image URL parameters


googleusercontent HTTP 403


Google Drive URL usp parameter


Drive API v2 to v3 reference


OAuth2 API hasGrantAnyScope


Google Drive API browser samples



ดู 5 ครั้ง0 ความคิดเห็น

โพสต์ล่าสุด

ดูทั้งหมด

Comments


Post: Blog2_Post
bottom of page