preliminary web support for auth (#26)

Some caveats:

  * it doesn't record the peer IP yet, which makes it harder to verify
    sessions are valid. This is a little annoying to do in hyper now
    (see hyperium/hyper#1410). The direct peer might not be what we want
    right now anyway because there's no TLS support yet (see #27).  In
    the meantime, the sane way to expose Moonfire NVR to the Internet is
    via a proxy server, and recording the proxy's IP is not useful.
    Maybe better to interpret a RFC 7239 Forwarded header (and/or
    the older X-Forwarded-{For,Proto} headers).

  * it doesn't ever use Secure (https-only) cookies, for a similar reason.
    It's not safe to use even with a tls proxy until this is fixed.

  * there's no "moonfire-nvr config" support for inspecting/invalidating
    sessions yet.

  * in debug builds, logging in is crazy slow. See libpasta/libpasta#9.

Some notes:

  * I removed the Javascript "no-use-before-defined" lint, as some of
    the functions form a cycle.

  * Fixed #20 along the way. I needed to add support for properly
    returning non-OK HTTP statuses to signal unauthorized and such.

  * I removed the Access-Control-Allow-Origin header support, which was
    at odds with the "SameSite=lax" in the cookie header. The "yarn
    start" method for running a local proxy server accomplishes the same
    thing as the Access-Control-Allow-Origin support in a more secure
    manner.
This commit is contained in:
Scott Lamb
2018-11-25 21:31:50 -08:00
parent 679370c77a
commit 422cd2a75e
21 changed files with 923 additions and 212 deletions

View File

@@ -15,11 +15,30 @@ In the future, this is likely to be expanded:
## Detailed design
All requests for JSON data should be sent with the header `Accept:
application/json` (exactly). Without this header, replies will generally be in
HTML rather than JSON.
All requests for JSON data should be sent with the header
`Accept: application/json` (exactly).
TODO(slamb): authentication.
### `/api/login`
A `POST` request on this URL should have an `application/x-www-form-urlencoded`
body containing `username` and `password` parameters.
On successful authentication, the server will return an HTTP 204 (no content)
with a `Set-Cookie` header for the `s` cookie, which is an opaque, HttpOnly
(unavailable to Javascript) session identifier.
If authentication or authorization fails, the server will return a HTTP 403
(forbidden) response. Currently the body will be a `text/plain` error message;
future versions will likely be more sophisticated.
### `/api/logout`
A `POST` request on this URL should have an `application/x-www-form-urlencoded`
body containing a `csrf` parameter copied from the `session.csrf` of the
top-level API request.
On success, returns an HTTP 204 (no content) responses. On failure, returns a
4xx response with `text/plain` error message.
### `/api/`
@@ -69,6 +88,9 @@ The `application/json` response will have a dict as follows:
time zone. It is usually 24 hours after the start time. It
might be 23 hours or 25 hours during spring forward or fall
back, respectively.
* `session`: if logged in, a dict with the following properties:
* `username`
* `csrf`: a cross-site request forgery token for use in `POST` requests.
Example response:
@@ -104,6 +126,10 @@ Example response:
},
...
],
"session": {
"username": "slamb",
"csrf": "2DivvlnKUQ9JD4ao6YACBJm8XK4bFmOc",
}
}
```