--- status: current platform: robot.wtf (VPS) --- Extracted from the original wikibot.io design. AWS-specific content archived at [[Archive/AWS_Design/Auth]]. See also: [[Design/VPS_Architecture]], [[Design/Data_Model]]. --- ## Auth Overview **ATProto OAuth login** — users authenticate via their ATProto identity (Bluesky handle/DID). The platform runs a self-hosted OAuth 2.1 Authorization Server for MCP connections. Three auth paths, all converging on the same identity resolution and ACL check: 1. **Browser session**: ATProto OAuth → platform issues a session JWT (signed with our RS256 key) → middleware validates JWT on each request → resolves user → checks ACL → sets Otterwiki headers. 2. **MCP OAuth (Claude.ai)**: Self-hosted OAuth 2.1 AS handles DCR, PKCE, token issuance, JWKS. Claude.ai discovers `/.well-known/oauth-protected-resource`, authenticates, presents access token. Per-wiki authorization in our middleware. 3. **Bearer token (Claude Code, API clients)**: Token in `Authorization` header → middleware hashes token, looks up in DB → resolves to user + wiki → checks ACL. The platform middleware is the single authentication boundary. Everything downstream trusts it. ## MCP Auth **OAuth 2.1 (Claude.ai)**: Self-hosted AS (authlib-based) provides DCR, PKCE, AS metadata, token endpoint, and JWKS. The MCP endpoint serves `/.well-known/oauth-protected-resource` pointing to the local AS. Per-wiki authorization happens in middleware — the AS identifies the user, middleware checks wiki access. See [[Design/VPS_Architecture]] for implementation details. **Bearer token (Claude Code / API)**: Each wiki gets a unique MCP bearer token, stored as a bcrypt hash in the platform DB. The user sees the token once (at creation) and can regenerate it from the dashboard. Usage: `claude mcp add --transport http`. ## ACL Model Simple role-based model: | Role | Read | Write | Delete | Manage ACL | Delete wiki | |------|------|-------|--------|------------|-------------| | viewer | yes | no | no | no | no | | editor | yes | yes | yes | no | no | | owner | yes | yes | yes | yes | yes | Wiki creator is always owner. Owners can grant viewer/editor access to other registered users. ## Authorization Flow **Layer 1 — Platform middleware** (before Otterwiki sees the request): 1. Resolve user identity from JWT or bearer token 2. Resolve wiki from request routing 3. Look up ACL: does this user have a grant on this wiki? 4. If no grant and wiki is not public → 403 5. Map ACL role to Otterwiki permission headers: | ACL role | `x-otterwiki-permissions` header | |----------|----------------------------------| | viewer | `READ` | | editor | `READ,WRITE,UPLOAD` | | owner | `READ,WRITE,UPLOAD,ADMIN` | | anonymous (public wiki) | Synthetic user with `READ` only | 6. Set headers: `x-otterwiki-email`, `x-otterwiki-name`, `x-otterwiki-permissions` 7. Forward to Otterwiki **Layer 2 — Otterwiki** (`AUTH_METHOD=PROXY_HEADER`): - Reads headers, creates ephemeral user object per request - No local user database — all identity comes from headers - Enforces READ/WRITE/UPLOAD/ADMIN based on the permissions header **For MCP and API paths**, Otterwiki is not involved in auth — the handlers read the git repo directly. Authorization happens entirely in Layer 1. ### Public wiki access The platform middleware injects a synthetic anonymous user with READ permission for public wikis. Otterwiki config stays identical for all wikis: ```python AUTH_METHOD = "PROXY_HEADER" READ_ACCESS = "APPROVED" # always — public access handled by middleware WRITE_ACCESS = "APPROVED" ATTACHMENT_ACCESS = "APPROVED" DISABLE_REGISTRATION = True # no Otterwiki-level registration ``` ## Otterwiki Admin Panel — Section Disposition The wiki owner (ACL role `owner`) gets `ADMIN` permission → access to `/-/admin/*`. | Admin section | Disposition | Reason | |--------------|-------------|--------| | Application Preferences | **Keep** | Wiki branding: site name, description, logo, favicon, language | | Sidebar Preferences | **Keep** | UI layout: sidebar shortcuts, custom menu items | | Content and Editing | **Keep** | Git workflow: commit message mode/template, page name casing, WikiLink style | | Repository Management | **Disable** | Conflicts with platform Git management | | Permissions and Registration | **Disable** | Conflicts with platform auth (middleware-managed) | | User Management | **Disable** | No local user database in ProxyHeaderAuth mode | | Mail Preferences | **Disable for MVP** | SMTP notifications — revisit later | **Implementation**: Override admin navigation template to hide disabled sections. Return 404 from disabled routes in middleware (defense in depth).
