SiamCafe.net Blog
Technology

Web Components Identity Access Management

web components identity access management
Web Components Identity Access Management | SiamCafe Blog
2025-07-09· อ. บอม — SiamCafe.net· 9,959 คำ

Web Components IAM

Web Components Identity Access Management Custom Elements Shadow DOM OAuth RBAC Login Session Token JWT Permission Guard Security Production

ComponentPurposeAttributesEventsSecurity
login-formAuthentication UIauth-url redirect-urllogin-success login-errorCSRF Token
oauth-buttonSocial Loginprovider client-idoauth-callbackState param
permission-guardRBAC UIrequired-role fallbackaccess-deniedServer verify
session-timerSession Managementtimeout warn-beforesession-expiredhttpOnly cookie
user-profileUser Info Displayshow-role show-avatarprofile-updatedSanitize output
mfa-input2FA Code Inputdigits verify-urlmfa-verifiedRate limiting

Custom Element Implementation

# === Web Component — Login Form ===

# class LoginForm extends HTMLElement {
#   constructor() {
#     super();
#     this.attachShadow({ mode: 'open' });
#   }
#
#   static get observedAttributes() {
#     return ['auth-url', 'redirect-url'];
#   }
#
#   connectedCallback() {
#     this.shadowRoot.innerHTML = `
#       <style>
#         :host { display: block; max-width: 400px; margin: 0 auto; }
#         form { display: flex; flex-direction: column; gap: 16px; }
#         input { padding: 12px; border: 1px solid #ccc; border-radius: 8px; }
#         button { padding: 12px; background: #4f46e5; color: white; border: none;
#                  border-radius: 8px; cursor: pointer; font-size: 16px; }
#         button:hover { background: #4338ca; }
#         .error { color: #ef4444; display: none; }
#       </style>
#       <form>
#         <input type="text" name="username" placeholder="Username" required />
#         <input type="password" name="password" placeholder="Password" required />
#         <div class="error"></div>
#         <button type="submit">Login</button>
#       </form>
#     `;
#     this.shadowRoot.querySelector('form').addEventListener('submit', (e) => {
#       e.preventDefault();
#       this.handleLogin(e.target);
#     });
#   }
#
#   async handleLogin(form) {
#     const data = new FormData(form);
#     try {
#       const res = await fetch(this.getAttribute('auth-url'), {
#         method: 'POST',
#         headers: { 'Content-Type': 'application/json' },
#         body: JSON.stringify({
#           username: data.get('username'),
#           password: data.get('password'),
#         }),
#         credentials: 'include',
#       });
#       if (res.ok) {
#         const { token } = await res.json();
#         this.dispatchEvent(new CustomEvent('login-success', {
#           detail: { token }, bubbles: true, composed: true
#         }));
#       }
#     } catch (err) {
#       this.dispatchEvent(new CustomEvent('login-error', {
#         detail: { error: err.message }, bubbles: true, composed: true
#       }));
#     }
#   }
# }
# customElements.define('login-form', LoginForm);

from dataclasses import dataclass

@dataclass
class WebComponentAPI:
    lifecycle: str
    when_called: str
    use_case: str

apis = [
    WebComponentAPI("constructor()", "Element created", "Initialize state, attach Shadow DOM"),
    WebComponentAPI("connectedCallback()", "Added to DOM", "Render template, add event listeners"),
    WebComponentAPI("disconnectedCallback()", "Removed from DOM", "Cleanup listeners, cancel timers"),
    WebComponentAPI("attributeChangedCallback()", "Attribute changes", "React to attribute updates"),
    WebComponentAPI("adoptedCallback()", "Moved to new document", "Re-initialize if needed"),
    WebComponentAPI("observedAttributes", "Static getter", "List attributes to watch"),
]

print("=== Web Component Lifecycle ===")
for a in apis:
    print(f"  [{a.lifecycle}] When: {a.when_called}")
    print(f"    Use: {a.use_case}")

RBAC Permission Guard

# === Permission Guard Component ===

# class PermissionGuard extends HTMLElement {
#   constructor() {
#     super();
#     this.attachShadow({ mode: 'open' });
#   }
#
#   static get observedAttributes() {
#     return ['required-role', 'required-permission'];
#   }
#
#   connectedCallback() {
#     this.checkAccess();
#   }
#
#   async checkAccess() {
#     const requiredRole = this.getAttribute('required-role');
#     const userRoles = await this.getUserRoles();
#
#     if (userRoles.includes(requiredRole)) {
#       this.shadowRoot.innerHTML = '<slot></slot>';
#     } else {
#       this.shadowRoot.innerHTML = '<slot name="fallback"></slot>';
#       this.dispatchEvent(new CustomEvent('access-denied', {
#         detail: { requiredRole, userRoles },
#         bubbles: true, composed: true
#       }));
#     }
#   }
#
#   async getUserRoles() {
#     const token = document.cookie.match(/token=([^;]+)/)?.[1];
#     if (!token) return [];
#     const payload = JSON.parse(atob(token.split('.')[1]));
#     return payload.roles || [];
#   }
# }
# customElements.define('permission-guard', PermissionGuard);

# Usage:
# <permission-guard required-role="admin">
#   <admin-dashboard></admin-dashboard>
#   <div slot="fallback">Access Denied</div>
# </permission-guard>

@dataclass
class RBACRule:
    role: str
    permissions: str
    ui_access: str
    api_access: str

rules = [
    RBACRule("admin", "all", "Full dashboard, user management, settings", "All endpoints"),
    RBACRule("editor", "read write publish", "Content editor, media library, preview", "CRUD content, media"),
    RBACRule("viewer", "read", "View content, reports, analytics", "GET endpoints only"),
    RBACRule("moderator", "read write delete-content", "Content moderation, user reports", "Content CRUD, reports"),
    RBACRule("guest", "read-public", "Public pages only", "Public API only"),
]

print("\n=== RBAC Configuration ===")
for r in rules:
    print(f"  [{r.role}] Permissions: {r.permissions}")
    print(f"    UI: {r.ui_access}")
    print(f"    API: {r.api_access}")

Security Best Practices

# === IAM Security Checklist ===

@dataclass
class SecurityCheck:
    category: str
    check: str
    implementation: str
    risk_if_missing: str

checks = [
    SecurityCheck("Authentication", "Use httpOnly Secure cookies for tokens",
        "Set-Cookie: token=xxx; HttpOnly; Secure; SameSite=Strict",
        "XSS can steal tokens from localStorage"),
    SecurityCheck("CSRF", "Include CSRF token in forms",
        "Generate token server-side, validate on POST",
        "Cross-site form submission attacks"),
    SecurityCheck("XSS", "Shadow DOM encapsulation + sanitize",
        "Shadow DOM isolates styles, sanitize user input",
        "Script injection, session hijacking"),
    SecurityCheck("Session", "Server-side session validation",
        "Verify token on every request, not just client-side",
        "Client-side checks can be bypassed"),
    SecurityCheck("RBAC", "Server-side permission check",
        "Never rely on UI hiding alone, verify on API",
        "Users can inspect/modify DOM to bypass UI guards"),
    SecurityCheck("Rate Limit", "Login attempt limiting",
        "Max 5 attempts per minute, lockout after 10",
        "Brute force password attacks"),
    SecurityCheck("MFA", "Two-factor authentication",
        "TOTP (Google Authenticator) or SMS backup",
        "Single-factor compromise = full access"),
    SecurityCheck("Audit", "Log all auth events",
        "Log login, logout, failed attempts, permission changes",
        "No visibility into security incidents"),
]

print("Security Checklist:")
for c in checks:
    print(f"  [{c.category}] {c.check}")
    print(f"    How: {c.implementation}")
    print(f"    Risk: {c.risk_if_missing}")

เคล็ดลับ

Web Components สำหรับ IAM คืออะไร

Web Standard Reusable Custom Elements Shadow DOM Login OAuth RBAC Permission Guard Session ใช้ทุก Framework React Vue Angular Vanilla

สร้าง Login Component อย่างไร

Custom Element HTMLElement Shadow DOM Template Form API Request Token httpOnly Cookie Custom Event login-success login-error Attribute Configurable

RBAC UI ทำอย่างไร

Permission Guard Component required-role Attribute JWT Token Role Slot Content Fallback Role Badge Permission Matrix CSS Custom Properties Server Verify

จัดการ Session อย่างไร

Session Manager Token Expiry Countdown Refresh Token Modal เตือน Redirect Login Activity Mouse Keyboard BroadcastChannel Tab Shadow DOM XSS

สรุป

Web Components IAM Custom Elements Shadow DOM OAuth RBAC Login Permission Guard Session Token JWT Security httpOnly CSRF XSS Production

📖 บทความที่เกี่ยวข้อง

Delta Lake Identity Access Managementอ่านบทความ → Elixir Ecto Identity Access Managementอ่านบทความ → Rust Actix Web Identity Access Managementอ่านบทความ → Go Wire DI Identity Access Managementอ่านบทความ → Svelte Stores Identity Access Managementอ่านบทความ →

📚 ดูบทความทั้งหมด →