Add OAuth2/OIDC per-user Gitea authentication
Some checks failed
docker / lint (push) Has been cancelled
docker / test (push) Has been cancelled
docker / docker-build (push) Has been cancelled
lint / lint (push) Has been cancelled
test / test (push) Has been cancelled

Introduce a GiteaOAuthValidator for JWT and userinfo validation and
fallbacks, add /oauth/token proxy, and thread per-user tokens through
the
request context and automation paths. Update config and .env.example for
OAuth-first mode, add OpenAPI, extensive unit/integration tests,
GitHub/Gitea CI workflows, docs, and lint/test enforcement (>=80% cov).
This commit is contained in:
2026-02-25 16:54:01 +01:00
parent a00b6a0ba2
commit 59e1ea53a8
31 changed files with 2575 additions and 660 deletions

View File

@@ -1,23 +1,21 @@
# Configuration
All configuration is done through environment variables. Copy `.env.example` to `.env` and set the values before starting the server.
Copy `.env.example` to `.env` and set values before starting:
```bash
cp .env.example .env
```
---
## Gitea Settings
## OAuth/OIDC Settings (Primary)
| Variable | Required | Default | Description |
|---|---|---|---|
| `GITEA_URL` | Yes | | Base URL of your Gitea instance (e.g. `https://gitea.example.com`) |
| `GITEA_TOKEN` | Yes | — | API token of the Gitea bot user |
The `GITEA_TOKEN` must be a token belonging to a user that has at least read access to all repositories you want the AI to access. The server validates the token on startup by calling the Gitea `/api/v1/user` endpoint.
---
| `GITEA_URL` | Yes | - | Base URL of your Gitea instance |
| `OAUTH_MODE` | No | `false` | Enables OAuth-oriented validation settings |
| `GITEA_OAUTH_CLIENT_ID` | Yes when `OAUTH_MODE=true` | - | OAuth client id |
| `GITEA_OAUTH_CLIENT_SECRET` | Yes when `OAUTH_MODE=true` | - | OAuth client secret |
| `OAUTH_EXPECTED_AUDIENCE` | No | empty | Expected JWT audience; defaults to client id |
| `OAUTH_CACHE_TTL_SECONDS` | No | `300` | OIDC discovery/JWKS cache TTL |
## MCP Server Settings
@@ -25,84 +23,44 @@ The `GITEA_TOKEN` must be a token belonging to a user that has at least read acc
|---|---|---|---|
| `MCP_HOST` | No | `127.0.0.1` | Interface to bind to |
| `MCP_PORT` | No | `8080` | Port to listen on |
| `MCP_DOMAIN` | No | — | Public domain name (used for Traefik labels in Docker) |
| `LOG_LEVEL` | No | `INFO` | Log level: `DEBUG`, `INFO`, `WARNING`, `ERROR`, `CRITICAL` |
| `STARTUP_VALIDATE_GITEA` | No | `true` | Validate Gitea token and connectivity at startup via `/api/v1/user` |
| `ALLOW_INSECURE_BIND` | No | `false` | Explicit opt-in required for `0.0.0.0` bind |
| `LOG_LEVEL` | No | `INFO` | `DEBUG`, `INFO`, `WARNING`, `ERROR`, `CRITICAL` |
| `STARTUP_VALIDATE_GITEA` | No | `true` | Validate OIDC discovery endpoint at startup |
If startup validation fails with `403 Forbidden`, the token is authenticated but lacks permission to access `/api/v1/user`. Grant the bot user token the required API scope/permissions, or temporarily set `STARTUP_VALIDATE_GITEA=false` in controlled troubleshooting environments.
---
## Authentication Settings
## Security and Limits
| Variable | Required | Default | Description |
|---|---|---|---|
| `AUTH_ENABLED` | No | `true` | Enable or disable API key authentication |
| `MCP_API_KEYS` | Yes (if auth enabled) | — | Comma-separated list of valid API keys |
| `MAX_AUTH_FAILURES` | No | `5` | Number of failed attempts before rate limiting an IP |
| `AUTH_FAILURE_WINDOW` | No | `300` | Time window in seconds for counting failures |
| `MAX_AUTH_FAILURES` | No | `5` | Failed auth attempts before rate limiting |
| `AUTH_FAILURE_WINDOW` | No | `300` | Window in seconds for auth failure counting |
| `RATE_LIMIT_PER_MINUTE` | No | `60` | Per-IP request limit |
| `TOKEN_RATE_LIMIT_PER_MINUTE` | No | `120` | Per-token request limit |
| `MAX_FILE_SIZE_BYTES` | No | `1048576` | Max file payload returned by read tools |
| `MAX_TOOL_RESPONSE_ITEMS` | No | `200` | Max list items in tool responses |
| `MAX_TOOL_RESPONSE_CHARS` | No | `20000` | Max chars in text fields |
| `REQUEST_TIMEOUT_SECONDS` | No | `30` | Upstream timeout for Gitea calls |
| `SECRET_DETECTION_MODE` | No | `mask` | `off`, `mask`, `block` |
### API Key Requirements
- Minimum length: 32 characters
- Recommended: generate with `make generate-key` (produces 64-character hex keys)
- Multiple keys: separate with commas — useful during key rotation
```env
# Single key
MCP_API_KEYS=abc123...
# Multiple keys (grace period during rotation)
MCP_API_KEYS=newkey123...,oldkey456...
```
> **Warning:** Setting `AUTH_ENABLED=false` disables all authentication. Only do this in isolated development environments.
---
## File Access Settings
## Write Mode
| Variable | Required | Default | Description |
|---|---|---|---|
| `MAX_FILE_SIZE_BYTES` | No | `1048576` | Maximum file size the server will return (bytes). Default: 1 MB |
| `REQUEST_TIMEOUT_SECONDS` | No | `30` | Timeout for upstream Gitea API calls (seconds) |
| `WRITE_MODE` | No | `false` | Enables write tools |
| `WRITE_REPOSITORY_WHITELIST` | Required if write mode enabled and allow-all disabled | empty | Comma-separated `owner/repo` allow list |
| `WRITE_ALLOW_ALL_TOKEN_REPOS` | No | `false` | Allow all repos accessible by token |
---
## Audit Logging Settings
## Automation
| Variable | Required | Default | Description |
|---|---|---|---|
| `AUDIT_LOG_PATH` | No | `/var/log/aegis-mcp/audit.log` | Absolute path for the JSON audit log file |
| `AUTOMATION_ENABLED` | No | `false` | Enables automation endpoints |
| `AUTOMATION_SCHEDULER_ENABLED` | No | `false` | Enables scheduler loop |
| `AUTOMATION_STALE_DAYS` | No | `30` | Age threshold for stale issue checks |
The directory is created automatically if it does not exist (requires write permission).
## Legacy Compatibility Variables
---
These are retained for compatibility but not used for OAuth-protected MCP tool execution:
## Full Example
```env
# Gitea
GITEA_URL=https://gitea.example.com
GITEA_TOKEN=abcdef1234567890abcdef1234567890
# Server
MCP_HOST=127.0.0.1
MCP_PORT=8080
MCP_DOMAIN=mcp.example.com
LOG_LEVEL=INFO
STARTUP_VALIDATE_GITEA=true
# Auth
AUTH_ENABLED=true
MCP_API_KEYS=a1b2c3d4e5f6...64chars
MAX_AUTH_FAILURES=5
AUTH_FAILURE_WINDOW=300
# Limits
MAX_FILE_SIZE_BYTES=1048576
REQUEST_TIMEOUT_SECONDS=30
# Audit
AUDIT_LOG_PATH=/var/log/aegis-mcp/audit.log
```
- `GITEA_TOKEN`
- `MCP_API_KEYS`
- `AUTH_ENABLED`