iDempiere 接 Microsoft Entra (AAD) SSO 實戰

重點摘要
  • iDempiere 12 能接 Microsoft Entra(前 Azure AD),而且是核心內建的 OIDC SSO(plugin org.idempiere.ui.sso.oidc),純視窗設定、零程式碼。
  • 不用碰公司 AAD —— 用免費個人 Entra 租戶(免信用卡)建一個測試 App 就能驗真 Azure。
  • 最容易卡死的是兩個開關:SysConfig ENABLE_SSO=Y(預設 N)和該設定的 IsDefault=Y。缺一個都不會轉址。
  • 登入認人靠 name(顯示名稱)claim 對 AD_User.Name —— 名字對不上就「登入過了卻找不到人」。
  • 改設定後要 Cache Reset + 全新無痕;要看真相請 curl 看是 302 還是 200,別信瀏覽器畫面。

「iDempiere 到底能不能跟公司的 Azure AD 整合登入?還是得換 Odoo?」這是很多人在把開源 ERP 放進企業身分體系時會問的第一個問題。答案很直接:iDempiere 12 原生就支援 Microsoft Entra ID(舊稱 Azure AD)的 OpenID Connect 單一登入(SSO),不用寫外掛、不用改原始碼,填一張視窗就好。這篇是我在自己的 iDempiere 12 上,對「真」的 Entra 租戶從頭跑通一次的完整實戰紀錄,包含幾個文件沒寫、但你一定會踩到的坑。

iDempiere 能不能接 Microsoft Entra(AAD)?

能,而且是核心內建。很多人以為 iDempiere 接 AAD 要找第三方外掛,其實 SSO 框架就在核心 repo 裡:驗證框架在 org.adempiere.base/.../sso/,OIDC provider 是內建的 org.idempiere.ui.sso.oidc。所有設定集中在一張「SSO Configuration」視窗(資料表 SSO_PrincipalConfig),而且有一個專為 Azure 準備的 Authorization Tenant ID 欄位。Azure 支援自 iDempiere 8.2(2021)就進了核心,release-12 開箱即有。

機制上,iDempiere 扮演 OIDC Relying Party:身分驗證交給 Entra,登入後把回傳的身分對應到 iDempiere 的 AD_User。這跟企業「身分集中 Entra、能力分散在各系統」的架構完全吻合 —— 延伸閱讀我先前寫的 Dify 企業落地:AAD / SSO / 分級 RAG 的授權架構,同一套 Entra 身分可以同時罩住 Dify、iDempiere 等後端。

不用碰公司 AAD:用免費個人 Entra 租戶測

公司的 AAD 通常不能讓你隨便加 redirect URI 或建測試帳號。好消息是:任何人都能用個人 Microsoft 帳號(Outlook/Hotmail)建一個免費 Entra 租戶,基本 free tier 不需要信用卡。進 entra.microsoft.com,用個人帳號登入就有一個預設目錄可用。這樣你能對「真」的 Azure 端到端驗證,完全不動到公司資源;之後要正式上線,只要把租戶/用戶端/密鑰三個值換成公司 App Registration 的即可,其餘設定原封不動。

Entra 端:建 App Registration,拿三個值

在 Entra 建一個 App Registration(帳戶類型選「僅此組織目錄中的帳戶 / 單一租戶」),重新導向 URI 平台選 Web,填 iDempiere 的登入頁網址。註冊完到「概觀」抄兩個值,再去「憑證及祕密」產一組 client secret 抄第三個值:

要拿的值 在 Entra 哪裡
Tenant ID(目錄/租用戶識別碼) App → 概觀
Application (client) ID App → 概觀
⚠️ Client Secret 的「值(Value)」 App → 憑證及祕密(離開頁面就看不到,立刻複製)

⚠️ 關鍵鐵則:Azure 只會把使用者導回「已登記在該 App Registration」的 redirect URI。iDempiere 的登入回呼網址一定要逐字登記進 App 的 Authentication 清單,少一個字元就會被擋,回你 AADSTS50011

iDempiere 端:SSO Configuration 欄位對應

用最上方搜尋框打 SSO 開啟「SSO Configuration」視窗(選單路徑:System Admin → General Rules → Security)。供應商下拉只有一個 OpenID Connect 是正常的 —— Azure 就是走 OIDC 這條,靠底下的 Discovery URI + Tenant ID 指向 Entra。逐格對應如下:

視窗欄位 填什麼
SSO ProviderOpenID Connect
Tenant IDEntra 的 Directory (tenant) ID
Application Client IDApplication (client) ID
Application Secret Keyclient secret 的 Value
Application Redirect URIshttps://<host>/webui/index.zul
Application Discovery URI見下方(必須以 .well-known/openid-configuration 結尾)
Monitor / Felix 兩格留空

Discovery URI 的格式(把 {tenantId} 換成你的 Tenant ID);beforeSave 會驗證結尾,不對就存不進去:

https://login.microsoftonline.com/{tenantId}/v2.0/.well-known/openid-configuration

還有一個設計上的巧妙:redirect URI = 登入頁 = /webui/index.zul。filter SSOWebUIFilter 是判斷「請求 URI 結尾是 index.zul」就攔截觸發 SSO,所以同一個網址同時是使用者登入頁、也是 Azure 驗證完導回來的落點。

兩個真正的開關 —— ENABLE_SSO 與 IsDefault

這是整篇最重要、也最容易卡死的地方。光把 SSO_PrincipalConfig 填好存檔,是不會有任何反應的。要能自動轉址到 Microsoft,四個條件缺一不可:

① SysConfig ENABLE_SSO = Y(預設 N)—— 總開關。沒開整段 SSO 邏輯是死的,填再多設定都沒反應。
② 該筆設定 IsDefault = Y —— 實測證實是關鍵開關(不是只看「有幾筆 active」)。
SSO_SHOW_LOGINPAGE 不是 Y(預設不存在=false)—— 是 Y 會強制停在帳密頁不轉址。
④ client 0 剛好 1 筆 active 設定(查詢只算 active 記錄)。

其中 IsDefault 這條特別值得記一筆:我原本讀 master 原始碼,以為自動轉址只看「有幾筆 active 設定」、跟 IsDefault 無關。結果實測打臉 —— 單一 active 設定、只切 IsDefault,行為完全不同。這種「源碼跟實跑行為不一致」的情況,永遠以實跑為準。乾淨的 A/B 證據如下:

IsDefault curl /webui/ 的回應 結果
Y HTTP 302 → login.microsoftonline.com ✅ 轉去 Microsoft
N HTTP 200 → iDempiere 帳密頁 🚫 不轉址

使用者對應與逃生門

驗證通過後,iDempiere 要把 Entra 的身分對應到本地使用者。對應邏輯在 OIDCPrincipalService.getUserName():

  • USE_EMAIL_FOR_LOGIN=N(預設)→ 拿 token 的 name(顯示名稱) claim 對 AD_User.Name
  • =Y → 拿 email claim 對 AD_User.EMail

快速測試技巧:把 Entra 測試帳號的「顯示名稱」直接設成一個現有 AD_User 的登入名(例如 SuperUser),就能一步對上、免在 iDempiere 另建使用者。名字對不上,就會出現「Azure 登入明明成功、iDempiere 卻說找不到人」的經典坑。

逃生門(避免把自己鎖在外面):設定測試期間,先不要把 SSO 設成強制、也保留一個已登入的管理員分頁別關。萬一 SSO 出錯,那個活著的分頁就是你重設設定的救命通道。SSO 啟用後,/webui/admin 也會走到帳密登入頁當備援。

用 curl 驗證,別信瀏覽器

改完設定「看起來沒生效」,十之八九是快取假象:設定清單和 ENABLE_SSO 都有 cache,舊分頁重整還是拿到舊值。正確做法是 Cache Reset + 開全新無痕,而看真相的方式是直接 curl 打 server 看它回 302 還是 200:

$ curl -s -o /dev/null -D - "https://your-idempiere/webui/" | grep -iE '^HTTP|^location'

HTTP/2 302
location: https://login.microsoftonline.com/{tenant}/oauth2/v2.0/authorize
          ?scope=openid+profile+email
          &response_type=code
          &redirect_uri=https%3A%2F%2Fyour-idempiere%2Fwebui%2Findex.zul
          &client_id={your-client-id}
          &prompt=login ...

看到 302 帶著正確的 client_idredirect_uriscope,就代表 server 端已經在運作 —— 這時瀏覽器還是舊畫面,純粹是本機快取,關掉所有無痕視窗重開就好。整條閉環(登入 → Microsoft 驗證 → 認出使用者 → 選角色 → 登出)在我這台 release-12 全跑通了。

那要不要換 Odoo?

Odoo 對 AAD 的整合更成熟(官方逐版本文件、auto-provision、屬性對應開箱即用),但如果你已經在用 iDempiere、也熟它的模型與客製,那沒有為了 SSO 換 ERP 的理由 —— iDempiere 的 OIDC 是核心內建、純設定、剛剛也親手驗證可行。真正的取捨在整體生態與客製深度,不在「能不能接 AAD」這一題。等到要搬進公司,只換三個值就好,其餘照本文設定不動。

留言

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *