Add explicit login functionality
This commit is contained in:
@@ -81,22 +81,27 @@ as `Authorization: Bearer <token>`, or paste it into the form's token field.
|
||||
and on `SIGHUP`. It must stay mode `0600` — the server refuses to start
|
||||
otherwise, since it holds credential material.
|
||||
|
||||
### Remembering a token
|
||||
### Logging in
|
||||
|
||||
Tick **Remember this token on this device** and the server sets a cookie, so the
|
||||
token only has to be pasted once. The upload page then says who you are and
|
||||
shows your real limits; **Forget** clears it, as does unticking the box on your
|
||||
next upload. It works with JavaScript disabled, because the browser sends the
|
||||
cookie either way.
|
||||
Open **Log in**, paste a token, and the browser keeps it until you log out. The
|
||||
header then shows who you are, the upload page shows your real limits, and
|
||||
**Administration** appears if the token is an admin one. Tick *stay logged in*
|
||||
and it survives a browser restart; leave it unticked and it dies with the
|
||||
browser, which is the right choice on a machine that is not yours.
|
||||
|
||||
The cookie is `HttpOnly`, which means the page's own script cannot read it — the
|
||||
server resolves the identity and renders it instead. That is deliberately
|
||||
unlike `localStorage`, where any script injected into the origin could read the
|
||||
token straight out and walk away with it. It is also `SameSite=Strict`, so no
|
||||
other site can make your browser upload or delete anything with it attached.
|
||||
The upload form also keeps a collapsed **Use a different token for this upload**
|
||||
field. That one applies to a single upload and never changes the session, so a
|
||||
quick upload under another token does not mean logging in and out.
|
||||
|
||||
Callers sending `Authorization: Bearer` are never given a cookie; an API client
|
||||
keeps its own credentials.
|
||||
The session cookie is `HttpOnly`, so the page's own script cannot read it — the
|
||||
server resolves the session and renders it. That is deliberately unlike
|
||||
`localStorage`, where any script injected into the origin could read the token
|
||||
straight out. It is also `SameSite=Strict`, so no other site can make your
|
||||
browser upload or delete anything with it attached.
|
||||
|
||||
Nothing about the session involves JavaScript: every page states who you are
|
||||
because the server rendered it that way. Callers sending `Authorization: Bearer`
|
||||
are never given a cookie; an API client keeps its own credentials.
|
||||
|
||||
## Uploading
|
||||
|
||||
@@ -143,8 +148,10 @@ file is accepted.
|
||||
| `GET /d/{id}` | the file, as an attachment; supports resuming |
|
||||
| `GET /i/{id}` | a page showing name, size, expiry, digest — and where a delete token is used |
|
||||
| `POST /api/d/{id}/delete` | delete, with `token=` in the form or `Authorization: Bearer` |
|
||||
| `POST /api/forget` | clear a remembered token |
|
||||
| `GET /login`, `POST /login` | start a browser session with a token |
|
||||
| `POST /logout` | end it |
|
||||
| `GET /admin` | administration page; admin tokens only |
|
||||
| `GET /api/limits` | what the presented credential may do; for scripts, the pages do not use it |
|
||||
|
||||
Deleting accepts the object's delete token, the token that uploaded it, or any
|
||||
admin token.
|
||||
@@ -225,12 +232,20 @@ Worth knowing if you are going to run this somewhere real.
|
||||
protection — so the upload handler maintains a per-read deadline instead.
|
||||
- **`X-Forwarded-For` is ignored** unless the peer is a configured
|
||||
`--trusted-proxy`, and then only to skip further trusted hops.
|
||||
- **A remembered token lives in an `HttpOnly`, `SameSite=Strict` cookie**, not
|
||||
in `localStorage`, so neither an injected script nor another website can get
|
||||
at it. `Secure` is set whenever the service knows it is being served over
|
||||
- **The session lives in an `HttpOnly`, `SameSite=Strict` cookie**, not in
|
||||
`localStorage`, so neither an injected script nor another website can get at
|
||||
it. `Secure` is set whenever the service knows it is being served over
|
||||
HTTPS — from `--public-url`, from a TLS connection, or from a trusted proxy's
|
||||
`X-Forwarded-Proto`. On browsers old enough to ignore `SameSite` entirely
|
||||
(pre-2017) the cookie would be CSRF-exposed; nothing here defends that case.
|
||||
`X-Forwarded-Proto`.
|
||||
- **Every `POST` must be same-origin.** `SameSite` covers requests that need a
|
||||
cookie, but logging in needs none: without this check a hostile page could
|
||||
sign a visitor into an account it controls and collect what they upload next.
|
||||
Browsers label their own requests with `Sec-Fetch-Site`, falling back to
|
||||
`Origin`; a request carrying neither is not a browser and is allowed through,
|
||||
since a bearer token cannot be attached by a third party anyway.
|
||||
- **Failed credential attempts are throttled per address** — a wrong delete
|
||||
token or a wrong login — while correct ones are never delayed, because only
|
||||
failures consume the budget.
|
||||
- Rate limiting is per client address, with a separate bound on uploads in
|
||||
flight. Both are in memory and reset on restart.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user