dsh-teams
Team access for the DeepSeek Harness web UI.
The dsh web server ships with no TLS, auth, or origin policy — deliberately out of scope. That's correct for a loopback dev tool, and a problem the moment you want your team on one shared instance.
dsh-teams is a zero-dependency auth gateway: a login wall plus a full HTTP and WebSocket reverse proxy in front of a loopback-bound dsh web. Your dsh stays on 127.0.0.1; the gateway is the only thing exposed.
browser ──> dsh-teams :3081 (auth wall) ──> dsh web 127.0.0.1:3080
Quick start
# 1. run dsh as usual (loopback-bound, the default)
npx @deepseek-ai/dsh web
# 2. create a user and start the gateway
npx dsh-teams add-user alice
npx dsh-teams start # http://0.0.0.0:3081 -> 127.0.0.1:3080
Point your team at http://<host>:3081. Unauthenticated requests — including WebSocket upgrades — get a login page; authenticated ones are proxied through untouched.
What it does
- Login wall on every HTTP route and WebSocket upgrade
- scrypt password hashing, HMAC-signed HttpOnly cookies, login rate limiting (10 tries / 15 min / IP)
- Forwards the authenticated username upstream as
x-dsh-teams-user(audit / future per-user routing) - Zero npm dependencies —
node:http,node:net,node:crypto; survives dsh rc churn because it never touches dsh internals
CLI
dsh-teams add-user <name> [password] create user (prompts if password omitted)
dsh-teams start [port] start gateway (default 3081)
dsh-teams remove-user <name>
dsh-teams list-users
Env: DSH_TEAMS_PORT, DSH_TEAMS_HOST, DSH_UPSTREAM_HOST, DSH_UPSTREAM_PORT, DSH_TEAMS_HOME (default ~/.dsh-teams).
SSO (OIDC)
Sign in with Google Workspace, Okta, Azure AD, Auth0 — anything speaking OIDC.
Authorization Code + PKCE, with full ID-token verification: RS256 signature
against the issuer's JWKS, plus iss / aud / exp / nonce. state is
single-use and expires in 10 minutes.
export DSH_TEAMS_OIDC_ISSUER=https://accounts.google.com
export DSH_TEAMS_OIDC_CLIENT_ID=xxx.apps.googleusercontent.com
export DSH_TEAMS_OIDC_CLIENT_SECRET=xxx # omit for public clients
export DSH_TEAMS_OIDC_REDIRECT_URI=https://your.host/__teams/sso/callback
export DSH_TEAMS_OIDC_ALLOWED_DOMAINS=corp.example
export DSH_TEAMS_OIDC_LABEL=Google
dsh-teams start
It refuses to start without an allowlist. ALLOWED_DOMAINS or
ALLOWED_EMAILS is mandatory: with a public issuer like Google, no allowlist
means any Google account on earth could sign in. Failing closed is deliberate.
Password login keeps working alongside SSO, so you can keep a break-glass local account.
Verified against a test IdP signing real RS256 tokens. The suite rejects:
tampered payloads, wrong-key signatures, issuer/audience mismatch, expired
tokens, nonce replay, alg=none downgrade, unverified emails, non-allowlisted
domains, forged state, and state replay.
Why it strips Origin
dsh's API returns 403 to any request carrying an Origin header — it assumes
loopback-only access, where browsers omit Origin on same-origin requests. Put
any proxy in front and the browser starts sending it, so every /api call 403s
while static assets still load, and the UI half-renders (missing composer,
unstyled text). The gateway therefore strips Origin/Referer and rewrites
Host to the upstream, preserving the original as x-forwarded-host.
Security notes
- Run behind TLS (Caddy/nginx/Cloudflare Tunnel) for anything beyond a trusted LAN — cookies are not
Secureover plain HTTP. - All authenticated users share one dsh instance and see the same sessions/workspaces. Per-user isolated instances are the next milestone (below).
- Sessions are in-memory: restarting the gateway logs everyone out.
Roadmap
- Per-user dsh instances — one process +
DSH_HOMEper user, gateway routes by identity (true isolation) - OIDC / SSO login (Google, GitHub, Okta)
- Roles & per-user workspace allowlists
- Usage quotas per user
- Audit log of who ran what
Test
npm test # 6-check smoke test: wall, bad login, login, proxy, tamper, logout
MIT. Not affiliated with DeepSeek AI.
还没有评论,来写第一条。