mirror of
https://gitee.com/mateos/mateclaw.git
synced 2026-09-13 11:13:43 +08:00
* feat(sso): feishu OAuth2 single sign-on (ISSUE #405 P0) Implements the SSO design (ISSUE #405) with feishu as the first IdP and a generic OAuth2 provider abstraction for future dingtalk/wecom extensions. SSO is disabled by default — existing deployments are unaffected until mateclaw.sso.enabled=true. Backend: - SsoProvider interface + SsoUserInfo record: generic IdP abstraction - FeishuSsoProvider: OAuth2 authorization-code flow (app_access_token with Caffeine cache → user_access_token → user info). apiBase switches between feishu.cn / larksuite.com by domain config. - SsoProviderRegistry: conditional registration, lists enabled providers - SsoStateService: HMAC-signed OAuth2 state + self-contained bind_token JWT, both persisted to sso_state DB table for multi-node correctness. State is one-time-consumable (conditional UPDATE), bind_token jti anti-replay via PK insert. Hourly ShedLock purge (LambdaQuery + Java time, works on all 3 dialects). - SsoService: authorize/callback/bind, user mapping (union_id first → external_id fallback), auto-create with concurrent idempotency (DuplicateKeyException → rollback orphan user → re-query), link-only mode issues bind_token for existing-account binding. - SsoController: 4 endpoints (/providers, /authorize, /callback, /bind) all permitAll. - V159 migration (h2/mysql/kingbase): mate_user_external_identity, sso_state, ALTER mate_user.password NULL (SSO-only users). - AuthService: generateToken promoted to public; login() guards password=null (SSO-only users cannot password-login). - SecurityConfig: /auth/sso/** added to permitAll whitelist. - LoginRateLimitFilter: expanded to cover /auth/sso/bind (brute-force surface equivalent to /auth/login). - application.yml: mateclaw.sso.* config block (all env-var driven). Frontend: - Login.vue: dynamic SSO buttons (only shown when providers configured), OAuth2 callback detection (?sso=callback), link-only bind dialog, shared applyLogin flow (localStorage + workspace + route). - api/index.ts: ssoApi (providers, authorize, callback, bind). Tests: SsoStateServiceTest (11) — state issue/verify/replay/tamper, bind_token issue/verify/anti-replay/garbage. Regression: PAT (23) + Approval resolve (13) all green. Not in scope (P1/P2): link-only bind/unbind management endpoints, user enable/disable endpoint, dingtalk/wecom providers, admin SSO config page. Workspace assignment for auto-created users remains a product decision (design doc §12 item 2). * fix(sso): self-review fixes — P0 security + P1 quality P0-1 BindRequired serialization: replaced the R.fail(200, Map.toString()) hack with a structured SsoCallbackResponse record. Controller no longer catches an exception for a non-error path; frontend reads bindRequired flag directly instead of regex-parsing a stringified map. P0-2 createSsoUser unbounded recursion: added a retry flag — second DuplicateKeyException (extreme race where identity was concurrently deleted) now throws a 503 instead of recursing to stack overflow. P0-3 state TTL not enforced: verifyState's conditional UPDATE now includes created_at > cutoff, so a state unused for 5+ min is rejected at consumption time, not just at the 1h purge. Without this the 5-min window was advisory only. P1-5 SsoStateService unused ObjectMapper: removed dead injection. P1-6 audit JSON string concat: replaced with ObjectMapper serialization (provider/externalId no longer risk breaking the JSON structure). P1-7 LoginRateLimitFilter shared counter: documented the intentional decision that login + bind share a per-IP counter (same brute-force surface) with guidance on switching to per-path if finer isolation is needed. |
||
|---|---|---|
| .. | ||
| acp/client | ||
| agent | ||
| approval | ||
| architecture | ||
| auth | ||
| channel | ||
| common | ||
| config | ||
| cron | ||
| dashboard/service | ||
| exception | ||
| goal | ||
| hook | ||
| i18n | ||
| llm | ||
| memory | ||
| skill | ||
| stt | ||
| system | ||
| task | ||
| tool | ||
| trigger | ||
| wiki | ||
| workflow | ||
| workspace | ||