oclaw/uds-auth/README.md
oliver 0e6de055a9
Some checks failed
ci / test (push) Has been cancelled
ci / test-postgresql (push) Has been cancelled
fix(uds-auth): keep sessions until manual sign-out; refresh expired UAC tokens by QR (0.3.20)
Users were asked to sign in again every ~30 minutes, even while active.

Session lifetime
- Browser: UDS_SESSION kept its login-time Max-Age and was never re-issued,
  so the cookie vanished 30 min after login. Re-issue it on use (throttled
  by slidingInterval).
- Desktop: remote.mux WS traffic never passed the HTTP auth middleware, so
  the idle TTL never slid. assertPrincipalLive now reports activity and
  slides the session and the account's bridges (throttled).
- New setting sessionIdleTimeoutHours (Settings page + config). Default 0 =
  no automatic sign-out; only a manual sign-out ends a session, so
  conversations and night-time cron are never cut off. 0.5-168 enables an
  idle timeout with the 7-day cap. The TTL is read live.
- Stores support long TTLs: the absolute cap follows the TTL, older 7-day
  sessions are lifted on activity, and expiry timers re-arm instead of
  overflowing setTimeout (~24.8 days).

UAC token check
- Every 2 hours (and 1 min after start) each QR session's token is checked
  against icenterapi. A rejected token is only flagged, never a sign-out.
  Network errors, 5xx and bad JSON keep the previous verdict (the old 6h
  check revoked all of an account's sessions on any failure, including
  outages).
- GET /uds-auth/session-status (non-sliding) returns alive + tokenValid.
  The client probes it every minute and on focus: a gone session signs the
  UI out with a notice; a rejected token opens a refresh QR once.
- Scanning in refresh mode writes the new token into every live session of
  the account and the skill credential cache in place: no new session, no
  reload. Other accounts are rejected (token_refresh_emp_mismatch).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 19:59:48 +08:00

87 lines
6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# uds-auth
0.3.10: [升级与协议变更说明](docs/upgrade-0.3.10.zh.md) · [SBOM](docs/sbom.cdx.json) · [第三方许可证](docs/THIRD-PARTY-NOTICES.txt)
UDS authentication plugin for DeepSeek Harness (**trusted single-instance** access control — **not** strong multi-tenant isolation).
See `package.json` for the current 0.3.x version (breaking auth protocol vs 0.2.x — re-login required).
## Support boundary
| Item | Notes |
|------|--------|
| Runtime | Node `^22.19.0 \|\| >=24` (aligned with DSH Host) |
| Mode | Single Host, trusted enterprise users, controlled skills |
| Out of scope | Untrusted multi-tenant execution isolation; multi-instance without shared session store |
## Install
```bash
dsh plugin --profile web add -w "<abs>/oclaw/uds-auth"
# or clean tarball
dsh plugin add -w "<abs>/uds-auth-0.3.9.tgz"
```
Empty roles table requires `UDS_AUTH_INITIAL_ADMIN` or `initialAdminEmpNo`. Restart Harness after install.
`ctx.get('udsAuth').runAsHost(cb)` — Host background ALS.
`ctx.get('udsAuth').mintTaskCapability({ empNo, dshSessionId, scopes, ttlSeconds })` — inject `UDS_TASK_CAPABILITY` for cron/skill.
## Config
```yaml
uacBaseUrl: https://uac.zte.com.cn # HTTPS required at startup/merge
userSearchUrl: https://icenterapi.zte.com.cn/...
loginSystemCode: '100000455558'
initialAdminEmpNo: ''
allowOpenRegistration: true
allowRawAgentToken: false
outboundAllowedHosts: icenterapi.zte.com.cn,icentermsg.dt.zte.com.cn
trustedHosts: '' # empty = loopback Host only; proxies must set allowlist
retainSkillCredentialsOnLogout: true
skillCredentialTtlSeconds: 604800
sessionIdleTimeoutHours: 0 # 0 = never auto sign out; 0.5–168h idle timeout; editable in Settings
```
Durable state defaults to `~/.uds-auth/` (roles / owners / credentials / bridge / sessions / `config.runtime.json`; override with `UDS_AUTH_DATA_DIR`). Security toggles take effect on the next request after Settings save. Empty outbound allowlist denies all.
## Sessions
- **Lifetime**: by default (`sessionIdleTimeoutHours: 0`) sessions never sign out on their own — only a manual sign-out ends them, so running conversations and night-time scheduled tasks are never cut off. Setting 0.5–168 hours in Settings enables an idle timeout that slides on activity (HTTP requests and Desktop WS calls) with a 7-day absolute cap. The browser cookie and the Desktop bridge token slide with the session.
- **UAC token check**: every 2 hours (and 1 minute after start) each QR session's UAC token is re-checked against the icenterapi department profile. A rejected token (401/403, business error code, employee not visible/mismatched) never signs out: the client shows a QR prompt, and the scan writes the new token into every live session of that account in place — no new session, no reload. Network errors, 5xx and malformed responses keep the previous verdict.
- **Client probe**: `GET /uds-auth/session-status` (never slides the TTL) runs every minute and on window focus. It returns `alive` and `tokenValid`; a gone session signs the UI out, a rejected token opens the refresh QR once.
- **Survives restarts**: the default in-memory store is persisted to `~/.uds-auth/sessions.json` and restored on Host start (emergency admins have no SSO re-login, so they depend on this).
- Only the SHA-256 hash of each session token is stored; user data (may include the UAC token) is AES-256-GCM encrypted with the plugin key `.uds-auth-secret-key`.
- Expired, undecryptable or tampered rows are dropped on load; disabled-account and emergency-password rotation checks still run on every request.
- **Delete `sessions.json` and restart to sign everyone out.** If the key file is unavailable, sessions are simply not persisted.
- Not used when a Redis session store is configured.
## Admin / emergency
- `super_admin` / `admin` / `fallback_admin` share the same admin-class permissions (identity labels, not stronger isolation).
- The emergency account is enabled by default: username `administrator`, password `Admin@123`. Change it in Settings after first sign-in. Admins can also disable it. Older roles files without an explicit emergency-account state receive this default; an explicitly disabled account stays disabled. Historical SHA-256 hashes of `Admin@123` migrate to scrypt.
- Local unlock: `node scripts/seal-local-admin.mjs` (interactive / `--stdin` — **no argv passphrase**) → `UDS_AUTH_LOCAL_ADMIN_BOX`.
- Removing a user disables the account by default (open registration cannot auto-revive).
## DSH compatibility
Verified on **DeepSeek Harness Desktop 0.2.0-rc.2**. The plugin relies on DSH internals that are not a public API; after a DSH upgrade run `npm test` and check login, workspaces and Settings → Models on a real install:
- Gateway `prepareInvocation` / `resolveDescriptor` / `openRemoteEvents` / `receiveRemoteEventResult` (if missing, the ACL refuses to install instead of failing open);
- the client `connection/reset` event (emitted after login so boot-time caches such as the settings mirror re-read);
- endpoint names `workspace/follow`, `workspace/initializeDefault`, and the Desktop welcome reads `settings/describe`, `llm/listConfigurableProviders`, `credentials/describe`, `account/getState`.
Desktop opens its connection anonymously at boot and reconnects after login. The plugin therefore:
- parks anonymous stream calls (e.g. account state) without data instead of failing them (a failure is terminal for DSH and shows "sign-in failed / add API key");
- answers anonymous `workspace/follow` with an empty list and anonymous `workspace/initializeDefault` with "nothing created";
- holds `/api/*` requests for up to 15 s while the gateway ACL is still installing, instead of returning 403.
## Skill / cron
Prefer Host-minted `UDS_TASK_CAPABILITY` + `DSH_SESSION_ID` with `/uds-auth/outbound`. Raw `/agent-credentials` stays off unless explicitly enabled. Python helper: `skill-helpers/python/uds_skill_auth.py`.
Chinese docs: [README.zh.md](README.zh.md), [docs/skill-auth-standard.zh.md](docs/skill-auth-standard.zh.md).
## License
MIT