Inventory and gap analysis of the 0.2.0 codebase against the full Gitea API and the official gitea-mcp toolset, the B1..B11 + security chunk plan, ADRs 0001-0006 for the full-access rebuild, SDK/OAuth research notes, and the instance swagger pinned for tool generation. The audit-logging doc moves to docs/audit-logging.md.
2.0 KiB
2.0 KiB
ADR 0004: admin-token mode and per-user OAuth mode
Status: accepted (2026-10-14)
Context
Two authentication models must coexist on one deployment: an admin with full
access, and other users who log in as themselves. Gitea is an OAuth2 provider
but has no RFC 8414 metadata and no dynamic client registration; Mistral Le
Chat requires dynamic client registration and Claude prefers it. Details:
docs/research/sdk-oauth-gitea.md sections 4 and 6.
Decision
- Admin-token mode (default).
GITEA_TOKENis used for every call. stdio always runs in this mode. On HTTP, a request carrying the staticMCP_BEARER_TOKEN(constant-time comparison) runs in this mode. - Per-user OAuth mode (HTTP). The server is an OAuth 2.1 authorization
server for MCP clients, using the SDK's
OAuthAuthorizationServerProviderwith dynamic client registration, and a confidential OAuth2 client of Gitea upstream (authorization code with PKCE S256, fixed and validated scope list). Our/oauth/callbackexchanges the Gitea code, then issues our own opaque access and refresh tokens mapped to the user's Gitea tokens. Tool calls use the user's Gitea access token, so Gitea enforces that user's permissions; admin tools fail with Gitea's own 403 for non-admins. Upstream refresh is automatic. - Token store. A JSON file under
DATA_DIR(default~/.local/state/aegis-gitea-mcp,/var/lib/aegis-mcpin the image), mode 0600, values encrypted with Fernet using a key derived fromTOKEN_ENCRYPTION_KEY. Our own tokens are stored only as SHA-256 hashes. - Combined verifier. One
TokenVerifieraccepts the static bearer (admin identity) or an issued OAuth token (user identity). The SDK requires passing it explicitly on the low-level server. - Identity in results. Every tool result carries
identity: {login, mode, sudo}.
Consequences
The server holds per-user Gitea tokens. That is the most sensitive asset after the admin token and is covered by the threat model.