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

Lesson 16: Authentication & Authorization — SSO for Micro Frontend

SSO architecture for Micro Frontend. Keycloak integration. OAuth2/OIDC flow. Token management. RBAC. Token sharing between Shell and MFEs.

🏗️ Architecture — Lesson 16 Lesson 16: Authentication & Authorization — SSO for Micro Frontend

Microservices & Micro Frontend system design — From basics to Production

Part 5: Building a practical Micro Frontend

xdev.asia

Introduction

Authentication in Micro Frontend is more complicated than regular SPA: Shell App handles login, but all MFEs need an access token. This article designs SSO architecture with 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"] }

Important: Frontend auth is UX only — backend must always validate.


4. Security Best Practices

PracticeDescription
Tokens in memoryDo not save access tokens in localStorage
HTTP-only cookiesFor BFF pattern
PKCERequired for SPA
Short-lived tokensAccess: 5 min, Refresh: 30 min
Token rotationNew refresh token every time refresh
CORS strictOnly accept known origins
CSP headersPrevent XSS

Summary

  • Shell own authentication — login, logout, token management
  • MFEs receive tokens via Context or Events
  • Tokens in memory + silent refresh
  • RBAC: route-level + feature-level + API-level
  • Backend always validates

Next article: Lesson 17: BFF Pattern — Backend for Frontend