Chuyển đến nội dung chính

Bài 16: Authentication & Authorization — SSO cho Micro Frontend

SSO architecture cho Micro Frontend. Keycloak integration. OAuth2/OIDC flow. Token management. RBAC. Token sharing giữa Shell và MFEs.

🏗️ Kiến trúc — Bài 16 Bài 16: Authentication & Authorization — SSO cho Micro Frontend

Thiết kế hệ thống Microservices & Micro Frontend — Từ cơ bản đến Production

Phần 5: Xây dựng Micro Frontend thực tế

xdev.asia

Giới thiệu

Authentication trong Micro Frontend phức tạp hơn SPA thông thường: Shell App handle login, nhưng tất cả MFEs cần access token. Bài này thiết kế SSO architecture với Keycloak.


1. SSO Architecture

┌──────────┐   1. Login    ┌──────────┐
│  Shell   │──────────────►│ Keycloak │
│  App     │◄──────────────│  (OIDC)  │
│          │   2. Tokens   └──────────┘
│          │
│ 3. Store tokens (memory)
│ 4. Broadcast auth state
│          │
│  ┌───────┴───────┐
│  ▼               ▼
│ MFE A          MFE B
│ (useAuth)      (useAuth)
│  │               │
│  ▼               ▼
│ API calls with Bearer token
└─────────────────────────

OIDC Authorization Code Flow + PKCE

1. User clicks Login → Shell redirects to Keycloak
2. User authenticates → Keycloak redirects back with auth code
3. Shell exchanges auth code for tokens (PKCE)
4. Tokens: Access (5 min), Refresh (30 min), ID Token
5. Shell stores in memory (NOT localStorage!)
6. Shell broadcasts auth state to MFEs

2. Token Management

2.1 Storage Security

❌ localStorage / sessionStorage: XSS vulnerable
✅ Memory (JS variable): Cleared on refresh + silent renew
✅ HTTP-only Cookie: For BFF pattern (server-side)

2.2 Token Sharing

// Option 1: React Context (same React via Module Federation)
<AuthContext.Provider value={auth}>
  <MFEContainer />
</AuthContext.Provider>

// Option 2: Events (framework agnostic)
window.dispatchEvent(new CustomEvent('auth:token-updated', {
  detail: { accessToken, user, roles }
}));

2.3 Silent Renewal

useEffect(() => {
  const interval = setInterval(async () => {
    const newTokens = await keycloak.refresh(refreshToken);
    broadcastToken(newTokens.accessToken);
  }, 4 * 60 * 1000); // Refresh 1 min before expiry
  return () => clearInterval(interval);
}, [refreshToken]);

3. Authorization — RBAC

Keycloak Roles:
├── admin       → Full access
├── manager     → Order + Product management
├── editor      → Product editing only
├── customer    → Shopping, order history
└── guest       → Browse products only

Frontend Authorization

// Shell: route-level guard
<Route path="/admin/*" element={
  <RequireRole role="admin"><AdminMFE /></RequireRole>
} />

// MFE: feature-level guard
{hasRole('editor') && <EditButton />}
{hasRole('admin') && <DeleteButton />}

Backend Authorization (API Gateway)

routes:
  - path: /api/products
    methods: [POST, PUT, DELETE]
    plugins:
      jwt-auth: {}
      rbac: { required_roles: ["editor", "admin"] }

Quan trọng: Frontend auth chỉ UX — backend phải luôn validate.


4. Security Best Practices

PracticeMô tả
Token in memoryKhông lưu access token trong localStorage
HTTP-only cookiesCho BFF pattern
PKCEBắt buộc cho SPA
Short-lived tokensAccess: 5 min, Refresh: 30 min
Token rotationNew refresh token mỗi lần refresh
CORS strictChỉ accept known origins
CSP headersPrevent XSS

Tóm tắt

  • Shell own authentication — login, logout, token management
  • MFEs nhận token qua Context hoặc Events
  • Tokens in memory + silent refresh
  • RBAC: route-level + feature-level + API-level
  • Backend always validates

Bài tiếp theo: Bài 17: BFF Pattern — Backend for Frontend