ทำไมไม่บล็อกเอเจนต์ออกจากการกระทำที่อ่อนไหวไปเลย?
การกระทำบางอย่างในแอปพลิเคชันของคุณมีความสำคัญมากกว่าการกระทำอื่น เช่น การเปลี่ยนรหัสผ่าน การเพิ่มสมาชิกทีม การส่งออกข้อมูล การลบโปรเจกต์ การอนุมัติคำสั่งซื้อ ถ้าสิ่งเหล่านี้เกิดขึ้นโดยไม่มีอำนาจที่ถูกต้อง ความเสียหายก็เป็นเรื่องจริง
ในเวลาเดียวกัน งานที่ชอบด้วยสิทธิ์จำนวนมากขึ้นเรื่อย ๆ ในแอปของคุณถูกทำโดยอัตโนมัติ ผู้ใช้ขอให้ผู้ช่วยอัปเดตการตั้งค่า พาร์ตเนอร์อินทิเกรชันสร้างข้อมูลตามกำหนด Internal agent ยื่นทิกเก็ตซัพพอร์ต การบล็อกไคลเอนต์อัตโนมัติทุกตัวจากเส้นทางที่อ่อนไหวจะทำให้การทำงานเหล่านี้เสียหาย และผลักผู้คนกลับไปสู่การทำงานด้วยมือหรือวิธีเลี่ยงที่ป้องกันได้ยากกว่า
คำตอบไม่ใช่ "บล็อกเอเจนต์" หรือ "เชื่อเอเจนต์" แต่คือโมเดลที่ให้ความเสี่ยงของการกระทำ อำนาจเบื้องหลังคำขอ และหลักฐานเกี่ยวกับ Actor ทำหน้าที่ต่างกันอย่างชัดเจน คู่มือนี้จะสร้างโมเดลดังกล่าวขึ้นมา สำหรับมุมมองที่กว้างกว่านี้ ดู การออกแบบนโยบายระดับแอปสำหรับมนุษย์และเอเจนต์ AI
ขั้นที่ 1: แบ่งระดับเส้นทางตามความเสี่ยง
เริ่มจากการจำแนกการกระทำ ไม่ใช่จำแนกไคลเอนต์ แผนแบ่งสามระดับแบบง่ายใช้ได้กับแอปพลิเคชันส่วนใหญ่:
| ระดับ | ตัวอย่าง | ข้อกำหนดเริ่มต้น |
|---|---|---|
| ต่ำ | อ่านข้อมูลสาธารณะ ค้นหา ดูแดชบอร์ดของตัวเอง | การยืนยันตัวตนตามปกติ หากมี |
| ปานกลาง | สร้างหรือแก้ไขเนื้อหาของตัวเอง เชิญผู้ดู | ยืนยันตัวตนแล้ว และได้รับอนุญาตสำหรับทรัพยากร |
| สูง | เปลี่ยนข้อมูลรับรอง เปลี่ยนเจ้าของ ส่งออกแบบจำนวนมาก ลบ อนุมัติ | ได้รับอนุญาต พร้อมการตรวจสอบแบบเพิ่มระดับหรือการทบทวน |
ใส่ระดับนี้ลงในคอนฟิกของ route เพื่อให้เห็นได้ในการ review โค้ด:
type Tier = "low" | "medium" | "high";
export const routeTier: Record<string, Tier> = {
"GET /projects": "low",
"POST /projects": "medium",
"POST /projects/:id/members": "medium",
"POST /account/password": "high",
"POST /exports": "high",
"DELETE /projects/:id": "high",
};ระดับจะเปลี่ยนช้าและเข้าใจได้ง่าย ทุกอย่างในคู่มือนี้ยึดตามระดับเหล่านี้
ขั้นที่ 2: ตัวตน ข้อมูลรับรอง และการอนุญาตต่างกันอย่างไร?
มักมีคำถามสามข้อที่ถูกปนกัน:
- ใครหรืออะไรเป็นผู้กระทำ? นี่คือหลักฐานของ Actor: คนที่โต้ตอบโดยตรง คนที่ใช้ AI ช่วย เอเจนต์ หรือ Unknown โดยมี basis เช่น Verified หรือ Declared
- มีการส่งข้อมูลรับรองใดมา? คุกกี้เซสชัน API key access token ของ OAuth
- ข้อมูลรับรองนี้ได้รับอนุญาตให้ทำการกระทำนี้กับทรัพยากรนี้หรือไม่? นี่คือการอนุญาต
ลายเซ็นของเอเจนต์ที่ยืนยันแล้ว (RFC 9421) ตอบข้อแรกได้ดี มันไม่ได้บอกอะไรเกี่ยวกับข้อที่สาม ซึ่งอธิบายไว้โดยละเอียดใน สิ่งที่คำขอที่เซ็นของเอเจนต์ AI บอกเราได้ และสิ่งที่บอกไม่ได้ OAuth token ที่มี scope ถูกต้องตอบข้อที่สามได้ แต่บอกเกี่ยวกับข้อแรกเพียงเล็กน้อย การตัดสินใจสำหรับการกระทำระดับสูงต้องมีคำตอบที่ดีต่อข้อที่สามเสมอ และใช้ข้อแรกเพื่อเลือกว่าต้องขอหลักประกันเพิ่มเติมมากแค่ไหน
interface Context {
actor: { actor: "human" | "human_ai" | "agent" | "unknown"; basis: "verified" | "declared" | "inferred" | "unknown" };
credential: { type: "session" | "oauth" | "api_key"; scopes: string[]; subject: string };
}
function authorized(ctx: Context, action: string, resourceOwner: string): boolean {
return ctx.credential.subject === resourceOwner && ctx.credential.scopes.includes(action);
}การอนุญาตไม่เคยถูกผ่อนคลายเพราะผลลัพธ์ของ Actor เป็นไปในทางที่ดี บริบทของ Actor ใช้เพื่อเพิ่มข้อกำหนดหรือเลือกเส้นทางที่ปลอดภัยพอ ๆ กันเท่านั้น
ขั้นที่ 3: ใช้อำนาจที่ได้รับมอบหมายเมื่อเอเจนต์ทำงานแทนคน
เมื่อเอเจนต์ทำงานแทนผู้ใช้ ให้มอบข้อมูลรับรองของตัวเองที่มีอำนาจจำกัด แทนที่จะปล่อยให้มันใช้เซสชันของผู้ใช้อีกครั้ง OAuth 2.0 คือเครื่องมือมาตรฐาน: ผู้ใช้อนุมัติ scopes เฉพาะสำหรับ client เฉพาะ และ token จะบันทึก client นั้น RFC 9700 ซึ่งเป็น OAuth 2.0 Security Best Current Practice อธิบายวิธีใช้งานอย่างปลอดภัย MCP servers ใช้รูปแบบเดียวกัน: ข้อกำหนดการอนุญาตของ MCP ถือว่า protected MCP server เป็น OAuth 2.1 resource server โพสต์ของเรา ใครกำลังเรียก MCP server ของคุณ? นำแนวทางนี้ไปใช้กับ tool calls
สิ่งนี้ให้สิ่งที่คุณต้องการสำหรับการกระทำที่อ่อนไหวอย่างตรงจุด:
- token บอกคุณได้ว่า client ใดเป็นผู้กระทำ และทำแทนใคร
- scopes จำกัดสิ่งที่มันทำได้ agent สำหรับการจัดตารางเวลาที่มี
calendar:writeจะเปลี่ยนรหัสผ่านไม่ได้ - ผู้ใช้สามารถเพิกถอน grant ได้โดยไม่ต้องเปลี่ยนข้อมูลรับรองของตนเอง และ OAuth 2.0 Token Revocation (RFC 7009) กำหนดวิธีที่ client แจ้ง authorization server ว่า token ควรหมดอายุใช้งาน
- บันทึก audit แสดงว่าเอเจนต์ ไม่ใช่ผู้ใช้ เป็นผู้ดำเนินการ
หากแอปของคุณยังไม่รองรับ delegated credentials ให้จัดลำดับความสำคัญของมันสำหรับการกระทำที่เอเจนต์ต้องใช้บ่อยที่สุด นี่คือการควบคุมที่มีประสิทธิภาพที่สุดเพียงอย่างเดียวสำหรับการเข้าถึงแบบอัตโนมัติ
ขั้นที่ 4: ควรขอการตรวจสอบแบบเพิ่มระดับเมื่อใด?
การตรวจสอบแบบเพิ่มระดับหมายถึงการขอหลักประกันเพิ่มเติมในขณะที่กำลังจะทำการกระทำที่อ่อนไหว สำหรับ API ที่ป้องกันด้วย OAuth RFC 9470 กำหนดวิธีที่ resource server บอก client ว่า authentication ของ token ปัจจุบันยังไม่แข็งแรงพอหรือไม่ใหม่พอ การตรวจสอบแบบเพิ่มระดับที่เหมาะสมขึ้นอยู่กับว่าใครเป็นผู้กระทำ:
- คนที่โต้ตอบโดยตรง (Human, Human + AI): ขอให้ยืนยันตัวตนอีกครั้ง ดูข้อกำหนดการยืนยันตัวตนซ้ำใน NIST SP 800-63B หรือใช้การแจ้ง passkey ที่สร้างบน WebAuthn หรือรหัสครั้งเดียว
- เอเจนต์ที่มี delegated credential: scope ที่กำหนดสำหรับการกระทำระดับสูง ซึ่งผู้ใช้อนุมัติอย่างชัดเจน หรือการยืนยันที่ส่งไปยังผู้ใช้นอกช่องทางหลัก
- Unknown: ใช้การตรวจสอบเข้มงวดที่มีอยู่เดิมของ route โดยไม่เปลี่ยนแปลง
type Requirement = "none" | "reauth" | "explicit_scope" | "user_confirmation" | "review";
function stepUp(tier: Tier, ctx: Context): Requirement {
if (tier !== "high") return "none";
const { actor } = ctx.actor;
if (actor === "human" || actor === "human_ai") return "reauth";
if (actor === "agent" && ctx.credential.type === "oauth") return "explicit_scope";
if (actor === "agent") return "user_confirmation";
return "reauth";
}สังเกตว่า ผลลัพธ์ Human ไม่ได้ข้ามการตรวจสอบแบบเพิ่มระดับ มันเป็นการเลือกขั้นตอนตรวจสอบที่เหมาะกับคนที่โต้ตอบโดยตรง Inferences อาจผิดได้ ดังนั้นควรเปลี่ยนรูปแบบของการตรวจสอบ ไม่ใช่เอาออกไป
ขั้นที่ 5: ส่งต่อให้มนุษย์ทบทวนเมื่อจำเป็นต้องใช้ดุลยพินิจ
การกระทำบางอย่างเกิดไม่บ่อย มีผลกระทบสูง และทำอัตโนมัติได้ยากอย่างปลอดภัย เช่น การส่งออกข้อมูลลูกค้าเป็นจำนวนมาก การกู้คืนบัญชีหลังจากข้อมูลรับรองสูญหาย หรือการลบองค์กร สำหรับกรณีเหล่านี้ คิวการทบทวนมักดีกว่ากฎอัตโนมัติใด ๆ
บริบทของ Actor ทำให้การทบทวนเร็วขึ้นและเป็นธรรมขึ้น เพราะให้หลักฐานแก่ผู้ทบทวน: class, basis, ข้อมูลรับรองที่ใช้, ประวัติของคำขอที่คล้ายกัน ผู้ทบทวนเป็นผู้ตัดสิน การจำแนกเป็นตัวช่วยให้ข้อมูล
function shouldReview(route: string, ctx: Context): boolean {
const reviewRoutes = new Set(["POST /exports", "POST /account/recover"]);
if (!reviewRoutes.has(route)) return false;
return !(ctx.credential.type === "oauth" && ctx.credential.scopes.includes("export:bulk"));
}ขั้นที่ 6: เลือกพฤติกรรมเมื่อเกิดความล้มเหลวแยกตามระดับ
การประเมิน Actor อาจหมดเวลา หรืออาจไม่มีหลักฐาน กำหนดล่วงหน้าว่าจะเกิดอะไรขึ้น
- ระดับต่ำ: fail open คำขอเดินหน้าตามปกติ
- ระดับปานกลาง: fail open โดยยังคงมีการอนุญาตตามปกติ
- ระดับสูง: fail closed ไปยังการตรวจสอบเข้มงวดที่มีอยู่เดิม หลักฐานของ Actor ที่ขาดหายไปจะไม่ทำให้การป้องกันอ่อนลง และจะไม่บล็อกคำขอที่มิฉะนั้นจะผ่านการตรวจสอบปกติของคุณ
คุณสมบัติสำคัญคือความสมมาตร ความล้มเหลวในการประเมิน Actor ควรทำให้การกระทำนั้นปลอดภัยเท่าเดิม และพร้อมใช้งานเท่าเดิม อย่างที่เป็นก่อนเพิ่มบริบทของ Actor
ขั้นที่ 7: อย่าตัดสินผลลัพธ์สำคัญเกี่ยวกับคนจาก Inferences
การจัดประเภทแบบ inferred เป็นหลักฐานเกี่ยวกับการโต้ตอบ ไม่ใช่ข้อเท็จจริงเกี่ยวกับบุคคล อย่าปฏิเสธใบสมัครงาน การตัดสินด้านเครดิต ผลสอบ ที่อยู่อาศัย หรือการเข้าถึงบริการที่จำเป็น เพียงเพราะเซสชันดูเหมือนเป็นอัตโนมัติหรือใช้ AI ช่วย ใน flow เหล่านั้น ให้ใช้บริบทของ Actor เพื่อเลือกกระบวนการ เช่น การทบทวนโดยมนุษย์หรือเส้นทางการยืนยันตัวตนทางเลือก และต้องแน่ใจว่าบุคคลนั้นดำเนินการให้เสร็จได้
นี่เป็นทั้งหลักความเป็นธรรมและหลักปฏิบัติ Inferences มี false positive และต้นทุนของ false positive ใน flow เหล่านี้จะตกกับคนที่ไม่ได้ทำอะไรผิด
ขั้นที่ 8: เปิดใช้งานโดยเริ่มจากการสังเกตก่อน
ก่อนที่สิ่งใดจะส่งผลต่อคำขอจริง ให้รันในโหมด observation และ preview:
- บันทึกระดับ class ของ Actor, basis, ประเภทข้อมูลรับรอง และ step-up ที่นโยบายของคุณจะต้องใช้
- ตรวจตัวอย่างคำขอระดับสูงตาม class เอเจนต์ที่ชอบด้วยสิทธิกำลังใช้ delegated credentials หรือกำลังใช้เซสชันของผู้ใช้อีกครั้ง?
- แก้ช่องว่างที่พบ มักจะแก้ได้ด้วยการเสนอ scoped credentials ก่อนที่คุณจะ enforce
- enforce กับส่วนเล็ก ๆ ของ route เดียว วัดอัตราการทำงานสำเร็จ แล้วค่อยขยาย
ขั้นที่ 9: เก็บร่องรอยการตรวจสอบที่ตอบคำถามว่า "ใคร และแทนใคร"
สำหรับการกระทำระดับสูงทุกครั้ง ให้บันทึกข้อมูลให้เพียงพอเพื่อประกอบเหตุการณ์ในภายหลังได้:
- class และ basis ของ Actor ณ เวลาที่มีคำขอ,
- ประเภทข้อมูลรับรอง client ที่ออกให้ และ subject ที่มันแทน (OAuth 2.0 Token Exchange, RFC 8693, กำหนด claim
actสำหรับบันทึกความสัมพันธ์แบบ "acting for" ประเภทนี้โดยเฉพาะ), - scopes ที่อนุญาตการกระทำ,
- ข้อกำหนด step-up หรือการทบทวนที่ใช้ และผลลัพธ์ของมัน
audit.write({
action: "project.export",
actor: ctx.actor,
client: ctx.credential.type === "oauth" ? clientIdFromToken(req) : undefined,
subject: ctx.credential.subject,
scopes: ctx.credential.scopes,
requirement,
outcome: "approved",
at: new Date().toISOString(),
});ด้วยร่องรอยนี้ คำถามอย่าง "คนหรือผู้ช่วยเป็นคนลบโปรเจกต์นี้ และใครเป็นผู้อนุมัติ" ก็จะมีคำตอบที่ชัดเจน สิ่งนี้ทำให้การตอบสนองต่อเหตุการณ์เร็วขึ้น และทำให้ผู้ใช้เชื่อมั่นว่า ความช่วยเหลือแบบอัตโนมัติในแอปของคุณมีความรับผิดชอบ
ตัวอย่างที่ใช้งานจริง
แอปจัดการโปรเจกต์แห่งหนึ่งเห็นผู้ช่วยอัปเดตกำหนดส่งของงานให้ผู้ใช้ และบางครั้งพยายามส่งออกโปรเจกต์ทั้งชุด
- การอัปเดตงานอยู่ในระดับปานกลาง ผู้ช่วยใช้ OAuth token ที่มี
tasks:writeได้รับอนุญาตแล้ว ไม่ต้อง step-up อนุญาต - การส่งออกโปรเจกต์อยู่ในระดับสูง token ของผู้ช่วยไม่มี
export:bulkแอปส่งคำขอยืนยันไปยังผู้ใช้ ผู้ใช้อนุมัติ และแอปให้ scope สำหรับ client นั้น - client ที่เป็น Unknown พยายามส่งออกแบบเดียวกันด้วย session cookie ที่นำกลับมาใช้ใหม่ ใช้ prompt ให้ยืนยันตัวตนอีกครั้งตามที่มีอยู่เดิมทุกประการ
ไม่มีใครถูกบล็อกเพียงเพราะเป็นเอเจนต์ ทุกการกระทำที่มีผลกระทบสูงมีอำนาจที่ชัดเจนกำกับอยู่
Proof of Actor เหมาะกับตรงไหน
Proof of Actor มอบด้าน Actor ของโมเดลนี้: ใครหรืออะไรเป็นผู้กระทำ และบนพื้นฐานใด แอปพลิเคชันของคุณยังคงดูแลการยืนยันตัวตน การอนุญาต และการตัดสินใจสุดท้ายไว้เอง Detect Actor, Understand ว่าแต่ละ class ใช้เส้นทางอ่อนไหวของคุณอย่างไร และ Route คำขอแต่ละรายการไปยังระดับหลักประกันที่เหมาะสม
หากต้องการออกแบบสิ่งนี้สำหรับแอปพลิเคชันของคุณร่วมกับทีมของเรา สมัครเข้าร่วมการเข้าถึงก่อนเปิดใช้ สำหรับกรณี SaaS ที่ลงรายละเอียดเพิ่มเติม ดู SaaS Apps & Websites
แหล่งอ้างอิง
- RFC 6749: The OAuth 2.0 Authorization Framework: ข้อมูลรับรองแบบ delegated ที่มี scope สำหรับ client
- RFC 9700: Best Current Practice for OAuth 2.0 Security: แนวทางความปลอดภัยปัจจุบันสำหรับการใช้งาน OAuth
- RFC 7009: OAuth 2.0 Token Revocation: การเพิกถอน grant โดยไม่ต้องเปลี่ยนข้อมูลรับรองของผู้ใช้
- RFC 9470: OAuth 2.0 Step Up Authentication Challenge Protocol: การส่งสัญญาณว่าต้องการการยืนยันตัวตนที่แข็งแรงขึ้นหรือใหม่ขึ้น
- RFC 8693: OAuth 2.0 Token Exchange: claim
act(actor) สำหรับ delegation - MCP specification 2026-07-28: Authorization: MCP servers ในบทบาท OAuth 2.1 resource servers
- NIST SP 800-63B: Authentication and Authenticator Management: แนวทางการยืนยันตัวตนซ้ำ
- W3C Web Authentication (WebAuthn) Level 3: มาตรฐานเบื้องหลังการแจ้ง passkey
- RFC 9421: HTTP Message Signatures: สิ่งที่ลายเซ็นของเอเจนต์ที่ยืนยันแล้วกำหนดได้