feat: HR Portal - Complete Multi-Tenant System with Redis Session Storage
Major Features: - ✅ Multi-tenant architecture (tenant isolation) - ✅ Employee CRUD with lifecycle management (onboarding/offboarding) - ✅ Department tree structure with email domain management - ✅ Company info management (single-record editing) - ✅ System functions CRUD (permission management) - ✅ Email account management (multi-account per employee) - ✅ Keycloak SSO integration (auth.lab.taipei) - ✅ Redis session storage (10.1.0.254:6379) - Solves Cookie 4KB limitation - Cross-system session sharing - Sliding expiration (8 hours) - Automatic token refresh Technical Stack: Backend: - FastAPI + SQLAlchemy - PostgreSQL 16 (10.1.0.20:5433) - Keycloak Admin API integration - Docker Mailserver integration (SSH) - Alembic migrations Frontend: - Next.js 14 (App Router) - NextAuth 4 with Keycloak Provider - Redis session storage (ioredis) - Tailwind CSS Infrastructure: - Redis 7 (10.1.0.254:6379) - Session + Cache - Keycloak 26.1.0 (auth.lab.taipei) - Docker Mailserver (10.1.0.254) Architecture Highlights: - Session管理由 Keycloak + Redis 統一控制 - 支援多系統 (HR/WebMail/Calendar/Drive/Office) 共享 session - Token 自動刷新,異質服務整合 - 未來可無縫遷移到雲端 Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
162
KEYCLOAK-CLIENT-SETUP.md
Normal file
162
KEYCLOAK-CLIENT-SETUP.md
Normal file
@@ -0,0 +1,162 @@
|
||||
# Keycloak Client 配置 - HR Portal Frontend
|
||||
|
||||
## 需要在 Keycloak 建立的 Client
|
||||
|
||||
### Client 基本資訊
|
||||
- **Client ID**: `hr-portal-web`
|
||||
- **Client Type**: OpenID Connect
|
||||
- **Access Type**: Public (因為是 SPA 應用)
|
||||
|
||||
### Client 配置
|
||||
|
||||
#### 1. Settings
|
||||
```
|
||||
Client ID: hr-portal-web
|
||||
Name: HR Portal Web Application
|
||||
Description: HR Portal Frontend SPA
|
||||
Client Protocol: openid-connect
|
||||
Access Type: public
|
||||
Standard Flow Enabled: ON
|
||||
Direct Access Grants Enabled: OFF
|
||||
Implicit Flow Enabled: OFF
|
||||
```
|
||||
|
||||
#### 2. Valid Redirect URIs
|
||||
開發環境:
|
||||
```
|
||||
http://localhost:3000/*
|
||||
http://10.1.0.245:3000/*
|
||||
```
|
||||
|
||||
生產環境 (待部署):
|
||||
```
|
||||
https://hr.ease.taipei/*
|
||||
```
|
||||
|
||||
**建議**: 如果想要更嚴格的安全控制,可以只允許根路徑:
|
||||
```
|
||||
http://localhost:3000/
|
||||
http://10.1.0.245:3000/
|
||||
https://hr.ease.taipei/
|
||||
```
|
||||
|
||||
**說明**:
|
||||
- `/*` - 允許任何路徑作為回調 URI (方便但較不安全)
|
||||
- `/` - 只允許根路徑作為回調 URI (更安全但需確保 Keycloak 回調到根路徑)
|
||||
- 對於開發環境,使用 `/*` 比較方便
|
||||
- 對於生產環境,建議使用更具體的路徑
|
||||
|
||||
#### 3. Valid Post Logout Redirect URIs
|
||||
```
|
||||
http://localhost:3000/
|
||||
http://10.1.0.245:3000/
|
||||
https://hr.ease.taipei/
|
||||
```
|
||||
|
||||
**注意**: Post Logout URIs 不需要 `*`,因為登出後只會導向根路徑
|
||||
|
||||
#### 4. Web Origins
|
||||
```
|
||||
http://localhost:3000
|
||||
http://10.1.0.245:3000
|
||||
https://hr.ease.taipei
|
||||
```
|
||||
|
||||
#### 5. Advanced Settings
|
||||
```
|
||||
PKCE Code Challenge Method: S256
|
||||
```
|
||||
|
||||
### Realm Roles (如果需要)
|
||||
|
||||
為 HR Portal 建立以下角色:
|
||||
- `hr-admin` - HR 管理員 (完整權限)
|
||||
- `hr-manager` - HR 經理 (查看與編輯)
|
||||
- `hr-viewer` - HR 檢視者 (僅查看)
|
||||
|
||||
### Client Scopes
|
||||
|
||||
確保以下 scopes 已啟用:
|
||||
- `openid` - 必須
|
||||
- `profile` - 使用者基本資料
|
||||
- `email` - 使用者電子郵件
|
||||
- `roles` - 角色資訊
|
||||
|
||||
## 建立步驟
|
||||
|
||||
### 1. 登入 Keycloak Admin Console
|
||||
```
|
||||
URL: https://auth.ease.taipei
|
||||
Realm: porscheworld
|
||||
```
|
||||
|
||||
### 2. 建立 Client
|
||||
1. 進入 **Clients** 頁面
|
||||
2. 點擊 **Create** 或 **Add Client**
|
||||
3. 填寫 Client ID: `hr-portal-web`
|
||||
4. 選擇 Client Protocol: `openid-connect`
|
||||
5. 點擊 **Save**
|
||||
|
||||
### 3. 配置 Client Settings
|
||||
1. **Access Type**: 改為 `public`
|
||||
2. **Standard Flow Enabled**: 勾選 ON
|
||||
3. **Direct Access Grants Enabled**: 取消勾選
|
||||
4. **Implicit Flow Enabled**: 取消勾選
|
||||
5. **Valid Redirect URIs**: 加入上述 URIs
|
||||
6. **Web Origins**: 加入上述 Origins
|
||||
7. 點擊 **Save**
|
||||
|
||||
### 4. 配置 Advanced Settings
|
||||
1. 進入 **Advanced Settings** 標籤
|
||||
2. **PKCE Code Challenge Method**: 選擇 `S256`
|
||||
3. 點擊 **Save**
|
||||
|
||||
### 5. 驗證 Client Scopes
|
||||
1. 進入 **Client Scopes** 標籤
|
||||
2. 確認 `openid`, `profile`, `email` 都在 **Assigned Default Client Scopes**
|
||||
3. 如果沒有,從 **Available Client Scopes** 加入
|
||||
|
||||
## 測試配置
|
||||
|
||||
### 1. 測試 OIDC Discovery
|
||||
```bash
|
||||
curl https://auth.ease.taipei/realms/porscheworld/.well-known/openid-configuration | jq
|
||||
```
|
||||
|
||||
### 2. 測試前端登入流程
|
||||
1. 啟動開發伺服器: `npm run dev`
|
||||
2. 瀏覽器開啟: http://localhost:3000
|
||||
3. 應該會被導向登入頁面
|
||||
4. 點擊「使用 SSO 登入」
|
||||
5. 應該會跳轉到 Keycloak 登入頁面
|
||||
6. 登入成功後應該回到 HR Portal 首頁
|
||||
|
||||
## 環境變數配置
|
||||
|
||||
前端 `.env` 檔案:
|
||||
```env
|
||||
VITE_API_BASE_URL=https://hr-api.ease.taipei
|
||||
VITE_KEYCLOAK_URL=https://auth.ease.taipei
|
||||
VITE_KEYCLOAK_REALM=porscheworld
|
||||
VITE_KEYCLOAK_CLIENT_ID=hr-portal-web
|
||||
```
|
||||
|
||||
## 常見問題
|
||||
|
||||
### CORS 錯誤
|
||||
- 確認 **Web Origins** 已正確設定
|
||||
- 檢查 Keycloak Realm Settings 的 CORS 設定
|
||||
|
||||
### 重新導向錯誤
|
||||
- 確認 **Valid Redirect URIs** 包含當前使用的 URL
|
||||
- 確認 URL 結尾有 `/*` 萬用字元
|
||||
|
||||
### Token 過期
|
||||
- 檢查 Keycloak 的 Token Lifespan 設定
|
||||
- 確認前端有正確實作 Token 刷新機制
|
||||
|
||||
## 相關文件
|
||||
|
||||
- Keycloak Documentation: https://www.keycloak.org/docs/latest/
|
||||
- Keycloak JS Adapter: https://www.keycloak.org/docs/latest/securing_apps/#_javascript_adapter
|
||||
- PKCE Flow: https://oauth.net/2/pkce/
|
||||
Reference in New Issue
Block a user