Files
hr-portal/KEYCLOAK-SETUP-CHECKLIST.md
Porsche Chen 360533393f 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>
2026-02-23 20:12:43 +08:00

5.4 KiB

Keycloak Client 設定檢查清單

Client: hr-portal-web

Access Settings (已完成)

  • Valid redirect URIs: 已設定三個環境
  • Valid post logout redirect URIs: 已設定
  • Web origins: 已設定 CORS

General Settings (需確認)

請確認以下設定:

Client ID

hr-portal-web

Client Protocol

openid-connect

Access Type

public  ← 必須是 public,因為是 SPA 應用

Standard Flow Enabled

ON  ← 必須開啟

Direct Access Grants Enabled

OFF  ← 建議關閉 (SPA 不需要)

Implicit Flow Enabled

OFF  ← 必須關閉 (使用 Standard Flow + PKCE)

Advanced Settings (需確認)

Proof Key for Code Exchange Code Challenge Method

S256  ← 必須設定為 S256

這個設定非常重要!必須啟用 PKCE 以確保安全性。

位置:

  1. 進入 Client 詳細頁面
  2. 切換到 Advanced Settings 標籤
  3. 找到 Proof Key for Code Exchange Code Challenge Method
  4. 選擇 S256
  5. 點擊 Save

Client Scopes (需確認)

確認以下 scopes 在 Assigned Default Client Scopes:

必須有的 Scopes

  • openid - OpenID Connect 核心
  • profile - 使用者基本資料 (name, username)
  • email - 使用者電子郵件

檢查方式

  1. 進入 Client 詳細頁面
  2. 切換到 Client Scopes 標籤
  3. 查看 Assigned Default Client Scopes 區塊
  4. 確認 openid, profile, email 都在列表中
  5. 如果沒有,從 Available Client Scopes 加入

Roles (選用,但建議設定)

為了權限控制,建議在 Realm 中建立以下 Roles:

進入 Realm Roles

  1. 左側選單選擇 Realm Roles
  2. 點擊 Add Role

建議的 Roles

hr-admin     - HR 管理員 (完整權限)
hr-manager   - HR 經理 (查看與編輯)
hr-viewer    - HR 檢視者 (僅查看)

設定步驟 (每個 Role)

  1. Role Name: 輸入 hr-admin (或其他)
  2. Description: 輸入說明,例如 "HR Portal Administrator"
  3. 點擊 Save

使用者設定 (測試用)

為測試帳號指派 Role:

  1. 左側選單選擇 Users
  2. 找到你的測試帳號 (例如: porsche)
  3. 點擊進入使用者詳細頁面
  4. 切換到 Role Mappings 標籤
  5. Available Roles 中找到 hr-admin
  6. 點擊 Add selected 將 role 加入
  7. 確認 role 出現在 Assigned Roles

測試流程

1. 檢查 OIDC Discovery Endpoint

在瀏覽器或使用 curl 訪問:

https://auth.ease.taipei/realms/porscheworld/.well-known/openid-configuration

應該能看到完整的 OpenID Connect 配置。

2. 測試前端登入

步驟:

  1. 確認開發伺服器運行: npm run dev
  2. 瀏覽器開啟: http://localhost:3000
  3. 應該會看到登入頁面
  4. 點擊「使用 SSO 登入」
  5. 應該會跳轉到 Keycloak 登入頁面
  6. 輸入帳號密碼登入
  7. 登入成功後應該回到 HR Portal 首頁
  8. Header 應該顯示使用者名稱和 Email

預期結果:

  • 成功跳轉到 Keycloak
  • 登入成功回到應用
  • Header 顯示正確的使用者資訊
  • 可以正常瀏覽各個頁面
  • 登出功能正常

如果失敗:

  1. 開啟瀏覽器開發者工具 (F12)
  2. 查看 Console 是否有錯誤訊息
  3. 查看 Network 標籤,檢查 Keycloak 的請求
  4. 常見錯誤:
    • Invalid redirect_uri: 檢查 Valid Redirect URIs 設定
    • CORS error: 檢查 Web Origins 設定
    • Invalid client: 檢查 Client ID 是否正確
    • PKCE required: 檢查 PKCE 是否設定為 S256

3. 測試 Token 刷新

登入後:

  1. 保持應用開啟
  2. 觀察 Console (每 30 秒會檢查 Token)
  3. 應該會看到 "Token 已刷新" 訊息 (如果 Token 快過期)

4. 測試 API 呼叫

登入後:

  1. 訪問員工列表頁面: http://localhost:3000/employees
  2. 開啟開發者工具 Network 標籤
  3. 檢查 API 請求 (例如: GET /api/v1/employees)
  4. 查看 Request Headers
  5. 應該包含: Authorization: Bearer eyJhbG... (Token)

完成確認

全部完成後,請確認:

  • Client ID 為 hr-portal-web
  • Access Type 為 public
  • Standard Flow 已啟用
  • PKCE 設定為 S256
  • Valid Redirect URIs 已正確設定
  • Web Origins 已正確設定
  • Client Scopes 包含 openid, profile, email
  • 測試帳號已指派 hr-admin role
  • 前端登入測試成功
  • Token 自動刷新運作正常
  • API 請求自動帶入 Bearer Token

疑難排解

問題: Invalid redirect_uri

原因: Valid Redirect URIs 設定錯誤 解決: 確認 URIs 完全匹配,包含 protocol (http/https)、host、port

問題: CORS error

原因: Web Origins 未設定 解決: 在 Web Origins 加入應用的 origin

問題: Token 無法刷新

原因: Realm 的 Token Lifespan 設定太短 解決:

  1. Realm Settings → Tokens
  2. 調整 Access Token Lifespan (建議 5-30 分鐘)
  3. 調整 SSO Session Idle (建議 30 分鐘)
  4. 調整 SSO Session Max (建議 10 小時)

問題: 使用者資訊不完整

原因: Client Scopes 缺少 profile 或 email 解決: 在 Client Scopes 加入對應的 scope

問題: 角色資訊取不到

原因: Token 中沒有包含 roles 解決:

  1. Client Scopes → Create new scope: roles
  2. Mappers → Create Protocol Mapper
  3. Mapper Type: User Realm Role
  4. Token Claim Name: realm_access.roles
  5. 將 scope 加入 Client 的 Default Client Scopes

文件版本: 1.0 最後更新: 2026-02-09 狀態: 待驗證