DEV Community

Cover image for OAuth สำหรับ AI Agent: ทำงานแทนผู้ใช้อย่างปลอดภัย
Thanawat Wongchai
Thanawat Wongchai

Posted on Originally published at apidog.com

OAuth สำหรับ AI Agent: ทำงานแทนผู้ใช้อย่างปลอดภัย

OAuth 2.0 สำหรับ AI Agent: ให้สิทธิ์แทนผู้ใช้อย่างปลอดภัย

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

ลองใช้ Apidog วันนี้

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

หากกำลังเลือกระหว่างคีย์กับ OAuth โปรดเริ่มจากบทความ คีย์ API และ OAuth และใช้ Apidog เพื่อทดสอบโฟลว์โทเค็น รวมถึงกรณีหมดอายุและเพิกถอนก่อนขึ้น production

เลือกระหว่างบัญชีบริการกับ delegated access

ใช้บัญชีบริการเมื่อทรัพยากรเป็นของคุณ

Service account คือตัวตนของเอเจนต์เอง เหมาะกับงาน เช่น:

  • อ่านฐานข้อมูลของคุณ
  • เรียกบริการภายใน
  • รันงานตามกำหนดเวลาบนโครงสร้างพื้นฐานของคุณ

กำหนดสิทธิ์ให้แคบที่สุด หมุนเวียนข้อมูลรับรองสม่ำเสมอ และปฏิบัติตามหลัก API key แบบ least privilege สำหรับเอเจนต์

ใช้ delegated access เมื่อข้อมูลเป็นของผู้ใช้

Delegated access หมายถึงเอเจนต์ทำงานในฐานะผู้ใช้เฉพาะคน และได้รับสิทธิ์ไม่เกินที่ผู้ใช้นั้นอนุญาต ผู้ใช้สามารถ:

  • ตรวจสอบสิทธิ์ที่มอบให้
  • เพิกถอนสิทธิ์ได้
  • ตรวจสอบบันทึกการกระทำที่ระบุตัวตนได้

อย่าใช้ service account ที่เข้าถึงทั้งองค์กรเพื่อปลอมบทบาทเป็นผู้ใช้ เพราะคุณจะสูญเสียการเพิกถอนรายผู้ใช้และ audit trail ที่น่าเชื่อถือ

OAuth flow ที่เหมาะกับเอเจนต์

OAuth 2.0 มีหลาย grant type แต่สำหรับเอเจนต์ให้เลือกตามกรณีใช้งานดังนี้

Authorization Code with PKCE

ใช้เมื่อเอเจนต์ต้องดำเนินการแทนผู้ใช้:

  1. ผู้ใช้เปิดหน้าเชื่อมต่อในเบราว์เซอร์
  2. ผู้ใช้อนุมัติ scope
  3. บริการของคุณแลก authorization code เป็น token
  4. ระบบจัดเก็บ refresh token อย่างปลอดภัย
  5. เอเจนต์ใช้ token ในการทำงานภายหลัง

PKCE ปกป้องขั้นตอนแลก code และเป็นคำแนะนำมาตรฐานตาม OAuth 2.0 Security Best Current Practice ดูรายละเอียดกลไกได้จาก Authorization Code Grant

ประเด็นสำคัญคือแยก เวลาที่เชื่อมต่อ ออกจาก เวลาที่เอเจนต์ทำงาน: มนุษย์อนุญาตเพียงครั้งเดียวตอนเชื่อมต่อ จากนั้นเอเจนต์ใช้ refresh token ในการทำงานเบื้องหลัง

Client Credentials

ใช้สำหรับ machine-to-machine และ service account เท่านั้น ไม่มีผู้ใช้เข้ามาเกี่ยวข้อง จึงไม่ควรใช้เพื่อทำหน้าที่แทนผู้ใช้

Device Authorization Grant

เหมาะกับเอเจนต์ CLI หรือ headless environment ที่ไม่มีเบราว์เซอร์บนเครื่อง เอเจนต์แสดงโค้ด แล้วผู้ใช้ไปอนุมัติผ่านโทรศัพท์หรืออุปกรณ์อื่น

Token Exchange

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

จำกัด scope ตามเอเจนต์

Scope คือหัวใจของ delegated authorization อย่าขอทุกสิทธิ์ที่แอปอาจต้องใช้

  • ขอเฉพาะสิ่งที่เอเจนต์นั้นทำ — เอเจนต์จัดตารางต้องมีสิทธิ์เขียนปฏิทิน ไม่ใช่อีเมล ผู้ติดต่อ และไฟล์
  • ขอเพิ่มแบบค่อยเป็นค่อยไป — เริ่มจาก scope ขั้นต่ำ แล้วขอเพิ่มเมื่อผู้ใช้เปิดใช้ฟีเจอร์ที่จำเป็น
  • แยกโทเค็นต่อเอเจนต์ — เอเจนต์วิจัยและเอเจนต์เรียกเก็บเงินควรมีโทเค็นคนละชุด แม้ทำงานแทนผู้ใช้เดียวกัน
  • ให้ read-only เป็นค่าเริ่มต้น — การเขียนต้องเป็นการยกระดับสิทธิ์อย่างชัดเจน
  • เพิ่ม approval gate สำหรับงานเสี่ยง — โทเค็นตอบได้เพียงว่า “ทำได้หรือไม่”; approval gate ตอบว่า “ควรทำหรือไม่”

อ่านรายละเอียดการออกแบบ scope ได้จาก OAuth 2 scopes และแนวทาง AI agent guardrails

จัดเก็บ รีเฟรช และเพิกถอนโทเค็น

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

การจัดเก็บ

  • เข้ารหัส refresh token ขณะจัดเก็บ
  • ใช้คีย์เข้ารหัสแยกต่อผู้ใช้
  • ห้ามบันทึก token ลง log
  • ห้ามใส่ token ใน prompt
  • ห้ามให้โมเดลเห็น token

การปกปิดควรเกิดที่ขอบเขตของระบบ ไม่ใช่รอปกปิดตอนอ่าน log ดูแนวทางได้จาก การติดตาม tool call ของเอเจนต์

การรีเฟรช

Access token ควรมีอายุสั้น และเอเจนต์ไม่ควรจัดการการรีเฟรชด้วยตัวเอง ให้มี token manager อยู่หน้า HTTP client

class TokenManager:
    def __init__(self, store, provider):
        self.store, self.provider = store, provider

    def access_token(self, user_id, agent_scope):
        rec = self.store.get(user_id, agent_scope)
        if rec.expires_in() > 60:
            return rec.access_token
        fresh = self.provider.refresh(rec.refresh_token, scope=agent_scope)
        self.store.save(user_id, agent_scope, fresh)   # rotation: store the new refresh token
        return fresh.access_token
Enter fullscreen mode Exit fullscreen mode

ข้อควรระวัง:

  1. ผู้ให้บริการจำนวนมากทำ refresh token rotation: ทุกครั้งที่ refresh จะได้ refresh token ใหม่ และตัวเก่าถูกยกเลิก ต้องบันทึกตัวใหม่ทันที
  2. จัดลำดับการ refresh ต่อผู้ใช้ เพื่อป้องกัน worker สองตัว refresh พร้อมกันแล้วตัวใดตัวหนึ่งใช้ token เก่าที่ถูกยกเลิก

การเพิกถอนและสิทธิ์หมดอายุ

ผู้ใช้อาจเพิกถอนสิทธิ์ ผู้ดูแลอาจลบบัญชี หรือสิทธิ์อาจหมดอายุตามนโยบาย

ให้ปฏิบัติต่อ 401 และ 403 เป็นข้อผิดพลาดสุดท้าย:

  • หยุดงาน
  • ห้าม retry วนซ้ำ
  • แจ้งชื่อผู้ใช้และ scope ที่มีปัญหา
  • ขอให้ผู้ใช้เชื่อมต่อใหม่หรืออนุญาต scope เพิ่ม

แนวทางการออกแบบข้อความผิดพลาดดูได้จาก API error messages สำหรับ AI agent

ความยินยอมต้องเกิดก่อนเวลาทำงาน

OAuth ไม่ได้ทำให้เอเจนต์ข้ามการยินยอมของมนุษย์ได้

ให้แยกเป็นสองช่วง:

  • เวลาเชื่อมต่อ: ผู้ใช้เปิดเบราว์เซอร์และอนุญาตสิทธิ์
  • เวลาทำงาน: เอเจนต์ใช้สิทธิ์ที่ได้รับผ่าน refresh token โดยไม่ต้องมีผู้ใช้อยู่หน้าจอ

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

ทดสอบ OAuth flow ด้วย mocks ก่อนขึ้น production

หน้าจอทดสอบ API ใน Apidog

Authentication เป็นส่วนที่มักถูกทดสอบน้อยที่สุด เพราะการทดสอบด้วยระบบจริงต้องคลิกผ่านหน้าจอของผู้ให้บริการ ให้จำลอง token endpoint และ protected endpoint แล้วทดสอบอย่างน้อยห้ากรณีนี้ใน CI:

  1. Happy path — access token ใช้งานได้และ API สำเร็จ
  2. Access token หมดอายุ — ได้ 401, token manager refresh, retry หนึ่งครั้ง และสำเร็จ
  3. Refresh token ถูกเพิกถอน — refresh ได้ invalid_grant, เอเจนต์หยุดและรายงาน
  4. Scope ไม่พอ — ได้ 403, เอเจนต์ไม่ retry และระบุ scope ที่ขาด
  5. Refresh พร้อมกัน — มีสองคำขอสำหรับผู้ใช้คนเดียวกัน แต่ต้องเกิด refresh เพียงครั้งเดียว

ใช้ Apidog เพื่อ mock การตอบกลับและกรณีผิดพลาดทั้งหมด โดยไม่ต้องแตะบัญชีจริง อ่านเพิ่มเติมได้จาก การรันเอเจนต์กับ mocks แทน production และ คู่มือทดสอบ OAuth 2 API

ตัวอย่างการเลือกโมเดลสิทธิ์

ผู้ช่วยปฏิทิน

อ่านเวลาว่างและจองประชุมให้ผู้ใช้หนึ่งคน

  • ใช้ delegated access
  • ขอ scope อ่านและเขียนปฏิทินเท่านั้น
  • ขอความยินยอมผ่านเบราว์เซอร์ตอนเชื่อมต่อ
  • ตรวจจับการเพิกถอนและหยุดงานกลางคืนทันที

เอเจนต์สนับสนุนสำหรับกล่องจดหมายร่วม

หากทรัพยากรเป็นของทีมจริง การใช้บัญชีร่วมอาจยอมรับได้ แต่ audit log จะดูเหมือนทุกการตอบกลับมาจากตัวตนเดียวกัน ทางเลือกที่ดีกว่าคือ bot identity ที่มี scope ของตัวเอง พร้อมบันทึกว่ามนุษย์คนใดเริ่มงานนั้น

เอเจนต์ปฏิบัติการภายใน

รีสตาร์ตบริการและอ่านแดชบอร์ดในโครงสร้างพื้นฐานของคุณเอง

  • ไม่มีข้อมูลผู้ใช้
  • ไม่ต้องใช้ delegated access
  • ใช้ service account ที่มี scope แคบ
  • เน้น rotation และการจำกัด blast radius

เส้นแบ่งง่าย ๆ คือ ความเป็นเจ้าของข้อมูล: ถ้าข้อมูลเป็นของบุคคลที่ควรเพิกถอนการเข้าถึงได้ ให้ใช้ delegated authorization ถ้าเป็นทรัพยากรของคุณเอง ให้ใช้ service account

เก็บตัวตนของผู้ร้องขอไว้ด้วย

Delegated authorization ตอบคำถามว่า “เอเจนต์ทำงานในนามของใคร” แต่ไม่ได้ตอบว่า “ใครขอให้เอเจนต์ทำงานนี้”

ภาพประกอบการมอบหมายงานให้เอเจนต์และทีมพร้อมผู้รับผิดชอบ

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

สำหรับทุกการเรียก ควรบันทึก:

  • user ID ที่เอเจนต์ทำงานแทน
  • ชื่อหรือ ID ของเอเจนต์
  • scope ที่ใช้
  • token identifier หรือ key ID
  • ผู้ใช้หรือระบบที่ร้องขอการทำงาน

ห้ามบันทึก token จริง

อย่าให้โมเดลเห็นข้อมูลรับรอง

กฎสำคัญที่สุดสำหรับระบบเอเจนต์คือ:

โมเดลต้องไม่เห็น token

ออกแบบให้ executor ฉีด Authorization header ที่ชั้น HTTP หลังจากโมเดลเลือก tool และสร้าง arguments แล้ว ดังนั้น:

  • tool schema ต้องไม่มีพารามิเตอร์ token
  • prompt ต้องไม่มีข้อมูลรับรอง
  • response ที่ส่งกลับให้โมเดลต้องลบ Authorization header
  • executor เป็นผู้เลือกโทเค็นตาม user ID และ agent scope

ทุกสิ่งที่โมเดลเห็นอาจไปอยู่ใน trace, summary, error message หรือคำตอบกลับผู้ใช้ได้ การให้โมเดลเลือก user ID หรือถือ token จึงเปลี่ยนการอนุญาตให้กลายเป็นความเสี่ยงโดยไม่จำเป็น

Checklist

  • [ ] ใช้ delegated access ทุกครั้งที่ข้อมูลเป็นของผู้ใช้
  • [ ] ใช้ service account เฉพาะทรัพยากรของคุณเอง
  • [ ] ใช้ Authorization Code with PKCE ตอนเชื่อมต่อ
  • [ ] ใช้ Device Authorization Grant สำหรับเครื่อง headless
  • [ ] ขอ scope ขั้นต่ำและแยกโทเค็นต่อเอเจนต์
  • [ ] ให้ซับเอเจนต์ใช้ token exchange แทนการคัดลอกสิทธิ์หลัก
  • [ ] เข้ารหัส refresh token และห้ามใส่ใน prompt, log หรือ trace
  • [ ] ให้ token manager refresh พร้อมจัดลำดับต่อผู้ใช้
  • [ ] ปฏิบัติต่อ 401 และ 403 เป็นข้อผิดพลาดสุดท้าย
  • [ ] แจ้งผู้ใช้เมื่อสิทธิ์หมดอายุหรือถูกเพิกถอน
  • [ ] ใช้ approval gate เพิ่มเติมกับงานที่มีความเสี่ยงสูง
  • [ ] ทดสอบทั้งห้าสถานการณ์ authentication ด้วย mocks ใน CI

Delegated authorization ใช้ความพยายามมากกว่าคีย์ที่ใช้ร่วมกัน แต่ให้สิ่งจำเป็นสองอย่างสำหรับเอเจนต์ที่ทำงานแทนผู้อื่น: ผู้ใช้เพิกถอนสิทธิ์ได้ และบันทึกระบุได้ว่าใครทำอะไร สร้างและทดสอบ token flow รวมถึง failure case ด้วย Apidog ก่อนปล่อยให้เอเจนต์ทำงานโดยไม่มีผู้ดูแล

คำถามที่พบบ่อย

เอเจนต์ทำขั้นตอน OAuth consent เองได้หรือไม่?

ไม่ได้ และไม่ควรทำ การยินยอมต้องเป็นการตัดสินใจของมนุษย์ ให้ผู้ใช้ออกสิทธิ์หนึ่งครั้งผ่าน browser flow แล้วเอเจนต์จึงใช้สิทธิ์นั้นภายหลัง

เอเจนต์แต่ละตัวควรมี OAuth client ของตัวเองหรือไม่?

แยก OAuth client ตาม product integration และแยก token ตามเอเจนต์ภายใน integration นั้น โดยทั่วไปผ่าน token exchange ใช้ client แยกเมื่อผู้ให้บริการจำกัด rate limit ต่อ client หรือต้องการเพิกถอนแบบอิสระ

ถ้าพลาด refresh token ตัวใหม่หลัง rotation จะเกิดอะไรขึ้น?

ผู้ใช้จะถูกล็อกออกและต้องเชื่อมต่อใหม่ ให้บันทึก refresh token ใหม่ในธุรกรรมเดียวกับการใช้ตัวเก่า และจัดลำดับการ refresh ต่อผู้ใช้เพื่อป้องกันการแข่งขันระหว่าง worker

ปลอดภัยหรือไม่หากให้โมเดลเห็น access token?

ไม่ปลอดภัย โทเค็นต้องอยู่ที่ชั้น HTTP ซึ่ง executor เป็นผู้ฉีดให้ สิ่งที่โมเดลเห็นอาจรั่วไปยัง trace, summary หรือคำตอบได้

ตรวจสอบได้อย่างไรว่าเอเจนต์ใดทำอะไร?

บันทึก user ID, ชื่อเอเจนต์, scope, token identifier และผู้ร้องขอในทุกการเรียก ห้ามบันทึก token จริง

ถ้าผู้ให้บริการไม่รองรับ token exchange ล่ะ?

หากผู้ให้บริการอนุญาต ให้เก็บสิทธิ์แยกต่อเอเจนต์ หรือบังคับใช้ scope restriction ใน gateway ของคุณเอง เพื่อกรองให้เอเจนต์เรียกได้เฉพาะการดำเนินการที่ได้รับอนุญาตก่อนคำขอออกจากเครือข่ายของคุณ

Top comments (0)