oclaw/uds-auth/lib/config.js
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

75 lines
2.6 KiB
JavaScript
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 配置工具
* Config schema 定义在 lib/index.js(由 DSH host 提供 @deepseek-ai/schemastery)
* 这里只做纯 JS 的默认值和工具函数,不依赖 host 运行时
*
* 可配置字段(部署相关,在 DSH 设置面板可改):
* uacBaseUrl UAC 基础 URL
* userSearchUrl icenterapi 用户搜索接口
* loginSystemCode 业务系统 Code
* originSystemCode 来源系统 Code
*
* 内部常量(UDS 固定协议,不暴露给用户):
* uacQrVerifyPath, cookie 名称, header 名称, session 等
*/
const UDS_AUTH_SETTINGS_NAMESPACE = 'uds-auth'
// 可配置字段的默认值(与 lib/index.js 里 Config schema 保持一致)
const DEFAULT_CONFIG = {
uacBaseUrl: 'https://uac.zte.com.cn',
userSearchUrl: 'https://icenterapi.zte.com.cn/zte-km-icenter-addresearch/user/plain/docs/search',
loginSystemCode: '100000455558',
originSystemCode: '',
retainSkillCredentialsOnLogout: true,
skillCredentialTtlSeconds: 7 * 24 * 60 * 60,
sessionIdleTimeoutHours: 0,
outboundAllowedHosts: 'icenterapi.zte.com.cn,icentermsg.dt.zte.com.cn',
initialAdminEmpNo: '',
allowOpenRegistration: true,
allowRawAgentToken: false,
/** Empty = loopback Host only; reverse proxies must set explicit authorities. */
trustedHosts: '',
}
// 内部常量(不暴露)
const INTERNAL = {
uacQrVerifyPath: '/uacqr/auth/qrcode/verify.serv',
cookieEmpNo: 'PORTALSSOUser',
cookieAuthValue: 'PORTALSSOCookie',
altCookieEmpNo: 'ZTEDPGSSOUser',
altCookieAuthValue: 'ZTEDPGSSOCookie',
empNoHeader: 'X-Emp-No',
authValueHeader: 'X-Auth-Value',
session: {
storeType: 'memory',
redisUrl: 'redis://localhost:6379',
cookieName: 'UDS_SESSION',
// Default only; the live idle TTL comes from sessionIdleTimeoutHours (see lib/index.js).
cookieMaxAge: 24 * 60 * 60 * 1000,
},
}
export { DEFAULT_CONFIG, INTERNAL, UDS_AUTH_SETTINGS_NAMESPACE }
export function loadConfig(custom = {}) {
return { ...DEFAULT_CONFIG, ...(custom || {}) }
}
export function buildVerifyUrl(uacBaseUrl, uacQrVerifyPath) {
if (/^https?:\/\//.test(uacQrVerifyPath)) return uacQrVerifyPath
return (uacBaseUrl.replace(/\/$/, '') + '/' + uacQrVerifyPath.replace(/^\//, ''))
}
export function validateConfig(config) {
if (!config?.uacBaseUrl) throw new Error('uacBaseUrl is required')
const checkHttps = (v, name) => {
if (v == null || v === '') return
let u
try { u = new URL(String(v)) } catch { throw new Error(`invalid_${name}`) }
if (u.protocol !== 'https:') throw new Error(`${name}_must_be_https`)
}
checkHttps(config.uacBaseUrl, 'uacBaseUrl')
checkHttps(config.userSearchUrl, 'userSearchUrl')
return true
}