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

第 16 課:身份驗證與授權 — 微前端的 SSO

微前端的 SSO 架構。鑰匙斗篷整合。 OAuth2/OIDC 流程。代幣管理。 RBAC。殼牌和 MFE 之間的代幣共享。

🏗️ 建築 — 第 16 課 第 16 課:身分驗證與授權 — 微前端的 SSO

微服務與微前端系統設計-從基礎到生產

第 5 部分:建構實用的微前端

亞洲開發網

簡介

微前端中的身份驗證比常規 SPA 更複雜:Shell 應用程式處理登錄,但所有 MFE 都需要存取權杖。本文使用Keycloak設計SSO架構。


1. 單一登入架構

┌──────────┐   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 授權程式碼流程 + 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. 代幣管理

2.1 儲存安全

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

2.2 代幣共享

// 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 靜默更新

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. 授權-RBAC

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

前端授權

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

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

後端授權(API網關)

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

重要: 前端驗證僅適用於 UX — 後端必須始終驗證。


4. 安全最佳實踐

實踐描述
記憶體中的令牌不要將存取令牌儲存在 localStorage
僅限 HTTP 的 cookie適用於 BFF 模式
PKCESPA 所需
短暫的代幣訪問:5 分鐘,刷新:30 分鐘
代幣輪換每次刷新新的刷新令牌
CORS 嚴格只接受已知來源
CSP 標頭防止XSS

總結

  • Shell 自己的身份驗證 — 登入、登出、令牌管理
  • MFE 透過情境或事件接收代幣
  • 記憶體中的令牌 + 靜默刷新
  • RBAC:路由等級 + 功能等級 + API 級別
  • 後端始終驗證

下一篇文章: 第 17 課:BFF 模式 — 前端的後端