老實說,這篇內容並不簡單,我也研究好幾個月,當初的需求是,希望能取代Azure AD原本的驗證機制,自建另外一套驗證,就能在上面進行更多操作。本篇將說明如何自建SAML伺服器,取代原本Azure AD驗證。
SAML
下面會需要了解的SAML的驗證機制,先說明一下。
SAML(Security Assertion Markup Language)是一種用於在不同安全環境下進行身份驗證和授權的標準協議。在SAML中,有兩個主要的角色:身份提供者(Identity Provider,IdP)和服務提供者(Service Provider,SP)。
IdP是一個系統或服務,負責驗證和管理使用者的身份資訊。並通過使用者提供的帳號、密碼進行身份驗證,並生成一個包含使用者身份資訊的SAML 斷言,斷言會被傳送給SP。
SP是指需要介接身分驗證的系統,SP在與IdP建立信任關係後,可以接收和解析SAML斷言,以驗證使用者身份。
介接原理
基本上網頁服務若要在Azure AD進行帳號驗證,都會使用SSO,SSO又分為OAuth、SAML兩種方式提供開發者串接。
微軟允許管理員設定當我們進入SSO後,可以跳轉到第三方的SAML IdP伺服器進行驗證,此時Azure AD SSO則扮演SAML SP的角色,驗證完成後再跳轉回Azure AD SSO,來完成登入的動作。
設定跳轉到SAML IdP,是將網域所有使用者進行跳轉,沒辦法在同個網域中,部分人使用SAML驗證,部分人使用微軟原本的驗證機制。
要完成以上介接需要解決Azure AD與SAML的串聯,並開發自己的SAML IdP伺服器。介接資訊可以參考微軟文件。

Demo
先展示一下效果,會比較好理解。我已經將twcanhelp.me這個網域設定SAML驗證。

按下登入後,會顯示 正在將您導向您組織的登入頁面。

接下來會跳轉到我撰寫的頁面,我這裡設計是只要按下登入,不用密碼就會登入,之後就會跳回去微軟頁面完成登入。

開設測試帳號
上面的範例不管登入Email填誰,最後都會登入同一個帳號,我們需要先建立這一個測試帳號。建議不要在Azure Portal建立帳號,因為會缺少一些參數。
隨便找一台電腦執行Powershell,並輸入以下語法建立使用者:
Connect-MsolService # 登入 -DisplayName "test" -ImmutableId "Meow"ImmutableId(內部部署固定 ID)這個使用者欄位相當於身份證字號,作為使用者的唯一識別,Azure AD SSO與SAML Idp溝通就是透過該欄位,然後在Azure Portal預設建立使用者並不會產生ImmutableId,會是一個空白,就會導致使用者無法透過SAML驗證,因此我建議透過指令新增測試帳號。
如果是從AD透過Azure AD Connect同步上來的帳號預設都會有ImmutableId,就不需要手動設定。
開發SAML IdP伺服器
我們需要先架設好自己的SAML IdP伺服器,才能夠跟Azure AD介接,我開發了Laravel的範例可以參考。我的範例PHP主要是用lightsaml來實作,其他語言要架設IdP可以參考這篇文章。
首先,SAML伺服器會有一組憑證作驗證,需要自己產,透過以下指令產生公鑰與私鑰。
openssl req -x509 -newkey rsa:4096 -sha256 -nodes -keyout key.pem -out cert.pem -days 3650接下來我們設定參數到 .env檔,參數如下
- SAML_KEY_BASE64 : 上面產生key.pem的base64
- SAML_CERT_BASE64 : 上面產生cert.pem的base64
- SAML_ISSUER : 發行人,我建議填網址,如https://saml.twcanhelp.me/
- SAML_NAME_ID : 填上面測試帳號的ImmutableID
再來將服務跑起來,並綁到網域saml.twcanhelp.me。
docker-compose up -d php設定介接Azure AD
接下來需要設定Azure AD的設定,告訴他要跳轉到哪裡進行驗證。主要步驟都是參考這篇文章。
隨便找一台電腦執行powershell,並設定參數,參數說明如下:
- DomainName : 帳號的網域
- FederationBrandName : 隨便自訂名稱
- Authentication : 設定Federated,代表使用同盟進行驗證
- SigningCertificate : 剛剛上面自簽的公鑰,把頭尾標籤拿掉,中間換行字元拿掉組成一行字。
- PassiveLogOnUri : 登入的網址
- LogOffUri : 登出的網址,這邊我用不到登出,就隨便寫個
- IssuerUri : 發行人識別,需要跟上面SAML_ISSUER一樣
Connect-MsolService # 登入
$dom = "twcanhelp.me"$BrandName = "SAML 2.0 IDP"$LogOnUrl = "https://saml.twcanhelp.me/login"$LogOffUrl = "https://saml.twcanhelp.me/"$MyURI = "https://saml.twcanhelp.me/"$MySigningCert = "XXXXXXXXXX"$Protocol = "SAMLP"Set-MsolDomainAuthentication ` -DomainName $dom ` -FederationBrandName $BrandName ` -Authentication Federated ` -PassiveLogOnUri $LogOnUrl ` -SigningCertificate $MySigningCert ` -IssuerUri $MyURI ` -LogOffUri $LogOffUrl ` -PreferredAuthenticationProtocol $Protocol執行成功後,到Azure Portal後台,會發現網域的同盟被打勾,這樣就完成了。同盟後,就無法再Azure Portal頁面新增使用者,需要透過指令。

若是要解除跳到第三方驗證,則要下指令
Set-MsolDomainAuthentication -DomainName $domain -Authentication Managed要取得目前設定的資訊可以下
Get-MsolDomainFederationSettings結語
透過自建SAML伺服器就能整合原本的Azure AD驗證機制,而且由於是先經過Azure AD再跳轉到SAML驗證,並不會影響到原本已經跟Azure AD SSO介接的系統。