Files
vmis/docs/WebMail_SSO_Integration_Guide.md
VMIS Developer 62baadb06f feat(vmis): 租戶自動開通完整流程 + Admin Portal SSO + NC 行事曆訂閱
Backend:
- schedule_tenant: NC 新容器自動 pgsql 安裝 (_nc_db_check 全新容器處理)
- schedule_tenant: NC 初始化加入 Redis + APCu memcache 設定 (修正 OIDC invalid_state)
- schedule_tenant: 新租戶 KC realm 自動設定 accessCodeLifespan=600s (修正 authentication_expired)
- schedule_account: NC Mail 帳號自動設定 (nc_mail_result/nc_mail_done_at)
- schedule_account: NC 台灣國定假日行事曆自動訂閱 (CalDAV MKCALENDAR)
- nextcloud_client: 新增 subscribe_calendar() CalDAV 訂閱方法
- settings: 新增系統設定 API (site_title/version/timezone/SSO/Keycloak)
- models/result: 新增 nc_mail_result, nc_mail_done_at 欄位
- alembic: 遷移 002(system_settings) 003(keycloak_admin) 004(nc_mail_result)

Frontend (Admin Portal):
- 新增完整管理後台 (index/tenants/accounts/servers/schedules/logs/settings/system-status)
- api.js: Keycloak JS Adapter SSO 整合 (PKCE/S256, fallback KC JS 來源, 自動 token 更新)
- index.html: Promise.allSettled 取代 Promise.all,防止單一 API 失敗影響整頁
- 所有頁面加入 try/catch + toast 錯誤處理
- 新增品牌 LOGO 與 favicon

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-15 15:31:37 +08:00

5.7 KiB

WebMail Keycloak SSO 整合指南

本指南說明如何將 Roundcube WebMail 與 Keycloak SSO 整合。

前置條件

已完成:

  • Keycloak Client 已建立
  • Client ID: webmail
  • Client Secret: CDUcB68SZUEZ2zmiQV4cz22czjw6Sn1q
  • Realm: vmis-admin

步驟 1: 連接到 WebMail 主機

ssh 10.1.0.254

步驟 2: 查看 Roundcube 容器

docker ps | grep -i roundcube

記錄容器名稱 (例如: roundcubewebmail)

步驟 3: 查看 Roundcube 配置掛載路徑

docker inspect <容器名稱> | grep -A 5 "Mounts"

找出配置檔案的掛載路徑 (通常是 /var/www/html/config 或類似路徑)

步驟 4: 安裝 OAuth2 插件

方法 A: 如果 Roundcube 使用官方 Docker 映像

  1. 進入容器:
docker exec -it <容器名稱> bash
  1. 使用 Composer 安裝 OAuth2 插件:
cd /var/www/html
composer require roundcube/oauth2
  1. 啟用插件 (編輯 config/config.inc.php):
vi config/config.inc.php

找到 $config['plugins'] 行,加入 'oauth2':

$config['plugins'] = array(
    'oauth2',
    // ... 其他插件
);

方法 B: 如果無法使用 Composer

手動下載並安裝插件:

cd /var/www/html/plugins
git clone https://github.com/roundcube/roundcubemail-oauth2.git oauth2

步驟 5: 配置 OAuth2 插件

建立或編輯 config/oauth2.inc.php:

vi /var/www/html/config/oauth2.inc.php

加入以下內容:

<?php

/**
 * Roundcube OAuth2 Configuration
 * Keycloak SSO Integration for WebMail
 */

$config['oauth2'] = array(
    'provider' => 'generic',
    'client_id' => 'webmail',
    'client_secret' => 'CDUcB68SZUEZ2zmiQV4cz22czjw6Sn1q',
    'auth_uri' => 'https://auth.lab.taipei/realms/vmis-admin/protocol/openid-connect/auth',
    'token_uri' => 'https://auth.lab.taipei/realms/vmis-admin/protocol/openid-connect/token',
    'identity_uri' => 'https://auth.lab.taipei/realms/vmis-admin/protocol/openid-connect/userinfo',
    'redirect_uri' => 'https://webmail.porscheworld.tw/index.php/login/oauth',
    'scope' => 'openid email profile',
    'login_redirect' => true,
    'username_field' => 'email',
    'identity_fields' => array(
        'email' => 'email',
        'name' => 'name',
        'username' => 'preferred_username'
    ),
);

// 自動登入 (可選)
$config['oauth2_auto_login'] = true;

// 允許傳統登入 (開發階段建議保留)
$config['oauth2_allow_traditional_login'] = true;

步驟 6: 修改 Roundcube 主配置

編輯 config/config.inc.php:

vi /var/www/html/config/config.inc.php

確保以下設定:

// 啟用插件
$config['plugins'] = array(
    'oauth2',
    // ... 其他插件
);

// IMAP 設定 (根據實際郵件伺服器調整)
$config['default_host'] = 'ssl://10.1.0.254';
$config['default_port'] = 993;

// SMTP 設定
$config['smtp_server'] = 'tls://10.1.0.254';
$config['smtp_port'] = 587;

// 使用者名稱網域 (根據 Keycloak 使用者的 email 設定)
$config['username_domain'] = array(
    'porscheworld.tw' => 'porscheworld.tw',
    'lab.taipei' => 'lab.taipei',
    'ease.taipei' => 'ease.taipei',
);

// 自動完成郵件地址
$config['mail_domain'] = 'lab.taipei';

步驟 7: 設定郵件地址對應規則

Keycloak 使用者的 email 屬性應該對應到郵件伺服器的帳號。

確保 Keycloak 使用者有正確的 email

  1. 登入 Keycloak Admin Console:
https://auth.lab.taipei/admin
  1. 進入 vmis-admin Realm

  2. 檢查使用者的 Email 欄位,例如:

    • Username: sysadmin
    • Email: admin@lab.taipei

這個 Email 必須是郵件伺服器上實際存在的帳號。

步驟 8: 重啟 Roundcube 容器

docker restart <容器名稱>

步驟 9: 測試 SSO 登入

  1. 清除瀏覽器 Cookie

  2. 訪問 WebMail:

https://webmail.porscheworld.tw
  1. 應該會自動重導向到 Keycloak 登入頁面:
https://auth.lab.taipei/realms/vmis-admin/protocol/openid-connect/auth?...
  1. 使用 Keycloak 帳號登入 (例如: sysadmin)

  2. 登入成功後,應該會重導向回 WebMail 並自動登入郵件帳號

故障排除

問題 1: 無法重導向到 Keycloak

檢查:

  • OAuth2 插件是否正確安裝
  • config/oauth2.inc.php 是否存在且設定正確
  • Roundcube 容器日誌: docker logs <容器名稱>

問題 2: 登入後顯示「Invalid credentials」

可能原因:

  • Keycloak 使用者的 email 與郵件伺服器帳號不符
  • 郵件伺服器密碼與 Keycloak 密碼不同

解決方案: 需要實作「密碼同步」或使用「IMAP OAuth2」:

  1. 方案 A: 密碼同步 - Keycloak 密碼變更時同步到郵件伺服器
  2. 方案 B: IMAP OAuth2 - 郵件伺服器支援 OAuth2 認證 (需要 Docker Mailserver 配置)

問題 3: 重導向 URI 不符

錯誤訊息:

Invalid redirect_uri

解決方案: 檢查 Keycloak Client 的 Valid Redirect URIs 設定:

https://webmail.porscheworld.tw/*

進階設定

整合 HR Portal 多帳號切換

如果要實現「員工可以使用 SSO 登入後,切換不同的郵件帳號」:

  1. 安裝 multi_accounts 插件
  2. 配置 API 端點連接 HR Portal
  3. 從 HR Portal 取得員工授權的郵件帳號列表

詳見: 郵件系統設計文件

相關連結

完成檢查清單

  • OAuth2 插件已安裝
  • config/oauth2.inc.php 設定完成
  • config/config.inc.php 啟用插件
  • Keycloak 使用者 email 正確設定
  • Roundcube 容器已重啟
  • SSO 登入測試成功
  • 郵件收發測試成功