ล็อกฟีเจอร์ตามแพ็กเกจด้วย Entitlements

อ่าน 7 นาที

ทำ feature flag ผูกกับ license: แยกแพ็กเกจ Basic/Pro ด้วย entitlements ที่ฝังอยู่ใน payload ที่เซ็นแล้ว ตรวจ offline ได้ พร้อมตัวอย่าง hasEntitlement ครบทั้ง 3 SDK (JS, Python, C#)

แทนที่จะ build แอปคนละไฟล์สำหรับแพ็กเกจ Basic กับ Pro คุณ ship แอปตัวเดียว แล้วปลดล็อกฟีเจอร์ตามสิทธิ์ที่ติดมากับคีย์ของลูกค้าแต่ละคนได้ — ด้วย entitlements ของ KeyThai มันคือ feature flag แบบหยาบ ๆ (เช่น export.pdf, premium, api.access) ที่ผูกกับ policy

ทำไมต้อง entitlements (ไม่เช็คชื่อแพ็กเกจเอง)

ถ้าโค้ดคุณ hardcode ว่า “ถ้า plan == pro ให้เปิด X” พอเพิ่มแพ็กเกจใหม่หรือทำโปร พิเศษ ต้องแก้โค้ดทุกที่ entitlements แยกแนวคิด “สิทธิ์” ออกจาก “ชื่อแพ็กเกจ” คุณปรับว่าแพ็กเกจไหนได้ฟีเจอร์อะไรจาก policy ฝั่ง dashboard โดยไม่ต้องแก้แอป

จุดเด่น: ฝังในลายเซ็น → ตรวจ offline ได้

entitlements ถูกฝัง ภายใน payload ที่เซ็นด้วย Ed25519 (รหัสถูกเรียงลำดับ ก่อนเซ็นเพื่อให้ canonical) เมื่อแอปตรวจลายเซ็นผ่าน ก็เชื่อรายการสิทธิ์ได้เลยโดยไม่ต้อง ต่อเน็ต และปลอมไม่ได้ — เพราะถ้าแก้ entitlements ลายเซ็นจะไม่ตรงทันที

เช็คด้วย hasEntitlement (ทั้ง 3 SDK)

ทุก SDK มีฟังก์ชัน hasEntitlement ที่ปลอดภัยต่อค่า null/ไม่มี entitlements (คืน false เสมอ) จึงเรียกได้โดยไม่ต้องเช็ค null เอง — คีย์ Basic ที่ไม่มีสิทธิ์ จะได้ผลลัพธ์ “ปิดฟีเจอร์” โดยอัตโนมัติ:

JavaScript (keythai-sdk)
import { verifyLicFile, hasEntitlement } from "keythai-sdk";

// payload เซ็นด้วย Ed25519 → entitlements ฝังข้างใน เชื่อถือได้แบบ offline
const lic = await verifyLicFile(jwk, licFileContents);
if (!lic.valid) throw new Error(lic.reason);

// แอปตัวเดียว แต่ปลดล็อกฟีเจอร์ตามชุดสิทธิ์ของคีย์แต่ละใบ
if (hasEntitlement(lic.payload, "export.pdf")) enablePdfExport();
if (hasEntitlement(lic.payload, "api.access")) enableApiTab();

// ค่าเริ่มต้นปลอดภัย: คีย์ Basic ไม่มี entitlement → คืน false เสมอ
if (!hasEntitlement(lic.payload, "premium")) showUpgradePrompt();
Python (keythai)
from keythai import verify_lic_file, has_entitlement

lic = verify_lic_file(jwk, lic_file_contents)
if not lic["valid"]:
    raise RuntimeError(lic["reason"])

# has_entitlement คืน False เมื่อ payload เป็น None หรือไม่มี entitlements
if has_entitlement(lic.get("payload"), "export.pdf"):
    enable_pdf_export()
if not has_entitlement(lic.get("payload"), "premium"):
    show_upgrade_prompt()   # ผู้ใช้แพ็กเกจ Basic
C# (KeyThai.Client)
using KeyThai;

LicFileResult lic = KeyThaiVerifier.VerifyLicFile(licFileContents, jwk);
if (!lic.Valid) throw new Exception(lic.Reason);

// SignedLicenseResponse.Entitlements เป็น IReadOnlyList<string>? (null เมื่อไม่มี)
if (KeyThaiVerifier.HasEntitlement(lic.Payload, "export.pdf"))
    EnablePdfExport();
if (!KeyThaiVerifier.HasEntitlement(lic.Payload, "premium"))
    ShowUpgradePrompt();   // Basic tier

ตัวอย่าง: Basic vs Pro ด้วยคีย์คนละชุดสิทธิ์

สร้าง 2 policy: Basic (ไม่มี entitlement) และ Pro (มี export.pdf, api.access, premium) ออกคีย์จาก policy ที่ลูกค้าซื้อ แอปตัวเดียวจะเปิด/ปิดเมนูตามสิทธิ์ของคีย์ พอลูกค้าอัปเกรด คุณแค่ออกคีย์ Pro หรือเปลี่ยน policy — ไม่ต้อง build/ship แอปใหม่ และเพราะ hasEntitlement คืน false เมื่อไม่มีสิทธิ์ ค่าเริ่มต้นจึงปลอดภัย (fail-closed)

อยากให้ผลลัพธ์เชื่อถือได้แม้ออฟไลน์ ควรตรวจลายเซ็นก่อนเสมอ — อ่าน ตรวจ license แบบ offline ด้วย Ed25519 ดูชนิดฟิลด์และฟังก์ชันทั้งหมดได้ที่ เอกสาร

พร้อมปกป้องซอฟต์แวร์ของคุณแล้วหรือยัง?

เริ่มต้นฟรี ไม่ต้องใช้บัตรเครดิต ออก license key แรกของคุณได้ในไม่กี่นาที