はじめに
マイクロ フロントエンドでの認証は通常の SPA よりも複雑です。シェル アプリがログインを処理しますが、すべての MFE にはアクセス トークンが必要です。この記事では、Keycloak を使用して SSO アーキテクチャを設計します。
1. SSO アーキテクチャ
┌──────────┐ 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 パターンの場合 |
| PKCE | SPAに必要 |
| 有効期間の短いトークン | アクセス: 5 分、リフレッシュ: 30 分 |
| トークンローテーション | 更新するたびに新しい更新トークン |
| CORS 厳格 | 既知の起源のみを受け入れる |
| CSP ヘッダー | XSS を防ぐ |
概要
- シェル独自の認証 — ログイン、ログアウト、トークン管理
- MFE はコンテキストまたはイベント経由でトークンを受け取ります
- メモリ内のトークン + サイレントリフレッシュ
- RBAC: ルートレベル + 機能レベル + API レベル
- バックエンドは常に検証します