03|建立 Keycloak SSO
你要完成什麼
Section titled “你要完成什麼”讓瀏覽器登入後,後端拿到可驗證的身分;測試未登入、錯誤 Token 與角色不符。登入成功不代表可讀所有資料。
1. 產生自己的身分配置
Section titled “1. 產生自己的身分配置”準備章已建立 .env 與秘密檔。確認 ORIGIN 是自己的 HTTPS 網址,再執行:
python3 scripts/prepare_sso.pypython3 scripts/prepare_openbao.pydocker compose up -d --build gatewaydocker compose pspython3 scripts/configure_sso.pypython3 scripts/configure_grafana.pygateway 會依 Compose 相依關係啟動 PostgreSQL、Keycloak 的獨立 DB、Keycloak、SSO、Grafana 與 pgAdmin。此時 OpenBao 尚未啟動,因此不要按短效憑證實驗。
Keycloak 初次啟動需要等待 healthcheck 通過。configure_sso.py 維護必要 client scope;它不會重建 realm 或重設帳號。四個示範帳密在本機 private/SSO-ACCESS.md,不要貼到共享文件。
2. 用 Tailscale 提供 HTTPS 入口
Section titled “2. 用 Tailscale 提供 HTTPS 入口”在自己的 Tailscale 主機上配置(既有講師環境已完成,不要重複修改):
tailscale serve --bg --https=28100 --set-path=/textile http://127.0.0.1:28400/textile這是私有 Serve,不是 Funnel。其他服務也使用 28100 時,不要停用整個 port。
3. 檢視 realm 與 clients
Section titled “3. 檢視 realm 與 clients”到 Keycloak 管理頁選 textile realm:
| 設定 | 本版值 | 為什麼 |
|---|---|---|
| Web client | textile-portal |
登入實驗工作台 |
| Grafana client | textile-grafana |
儀表板 SSO |
| 流程 | Authorization Code + PKCE S256 | 把登入回呼綁到原始流程 |
| API audience | textile-api |
不接受發給其他服務的 Token |
| 必要 scope | basic、profile、roles 等 |
basic 提供 subject |
| Access token | 5 分鐘 | 限制有效期 |
後端驗證簽章、issuer、audience、期限、subject、Token 類型與 authorized party。自行加 X-User: teacher 不會變成講師。
4. 親手測登入與角色
Section titled “4. 親手測登入與角色”- 未登入開
/textile/sso/api/me,應 401。 - 開實驗工作台,用
sales.a登入,檢查 username/department/roles。 - 按「測試講師限定端點」:業務應 403。
- 登出,再用
teacher登入:同一端點應 200。 - 以 SSO 進 Grafana,確認是 Viewer;不會因此成為管理員。
- 先登出 Grafana,再登出實驗工作台;
api/me應回 401。
5. 自動化驗收
Section titled “5. 自動化驗收”docker compose exec -T sso python - < scripts/verify_sso.py預期 18 項檢查通過。這套測試用測試簽章金鑰驗證拒絕邏輯;真正的 Keycloak 登入仍需做上面的瀏覽器驗收。
工作階段的限制
Section titled “工作階段的限制”Token 留在單一後端程序記憶體;瀏覽器拿的是 Secure/HttpOnly/SameSite=Lax 不透明 cookie。工作階段最長五分鐘,重啟 SSO 會清除。Grafana 有自己的 session,目前未實作跨應用 back-channel logout。
離線 JWT 驗證不代表登出後所有既發 Token 立即作廢;沒有逐次 introspection。尚未強制 MFA,也未接 AD/LDAP。
原始碼:scripts/prepare_sso.py、scripts/configure_sso.py、sso/app.py、keycloak/start.sh。