Commit Graph
1 Commits
  • Add single-user GitHub OAuth, hardened for internet exposure
    muse drives a download client and writes to the media library, so exposing it
    publicly needs more than a login form.
    
    It fails closed. Auth is on unless MUSE_AUTH=off is set explicitly, and when
    it is on with incomplete config the app refuses to start rather than serving
    open. The mode worth engineering against is not a broken login page, it is a
    misconfigured deploy quietly publishing an unauthenticated download client.
    
    Sessions are server-side: the cookie carries a 256-bit random token and
    nothing else, and only its SHA-256 is stored. There is no signed payload to
    get subtly wrong, a stolen database yields no usable cookies, and logout
    revokes for real. The allowlist is re-checked on every request so removing a
    user takes effect immediately rather than at session expiry.
    
    OAuth state is compared with secrets.compare_digest, so a callback the user
    did not initiate is rejected. MUSE_BASE_URL comes from config rather than
    X-Forwarded-* because those headers are attacker-controllable and this one is
    a redirect target.
    
    CSP is default-src 'self' with no unsafe-inline, which is why the stylesheet
    and script moved out of index.html into static files -- an injected <script>
    now cannot execute. Also frame-ancestors 'none', base-uri 'none', nosniff,
    DENY, no-referrer and HSTS. FastAPI's /docs, /redoc and /openapi.json are
    disabled so the login page does not hand out a map of every endpoint.
    
    /healthz is the only unauthenticated route and returns a bare ok, so the
    container healthcheck works without leaking anything.
    
    Verified: misconfigured auth refuses to boot; unauthenticated / redirects and
    /api/* returns 401; a forged state is rejected 400; a junk cookie is 401; a
    valid session for a non-allowlisted user is 401; all headers present; and the
    UI renders with no CSP violations in the console.
    
    Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>