aboutsummaryrefslogtreecommitdiffstats
path: root/src/api/login.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/api/login.rs')
-rw-r--r--src/api/login.rs15
1 files changed, 13 insertions, 2 deletions
diff --git a/src/api/login.rs b/src/api/login.rs
index de6e390..1907bac 100644
--- a/src/api/login.rs
+++ b/src/api/login.rs
@@ -54,6 +54,16 @@ pub(crate) struct Token {
/// `HttpOnly`, `SameSite=Strict`, so no script and no other site's page sends it.
pub(crate) const SESSION_COOKIE: &str = "continuum-token";
+/// Whether the session cookie lets `request` in: one that reads (`GET`, `HEAD`), or
+/// renews or ends the session. One that changes anything brings the token itself
+/// (`Authorization`), as a page of another site, or of another port of the same host
+/// (which a cookie doesn't tell apart), can't make a browser send it.
+fn cookie_lets_in(request: &Request<Body>) -> bool {
+ use axum::http::Method;
+ let method = request.method();
+ method == Method::GET || method == Method::HEAD || request.uri().path() == "/auth/session"
+}
+
/// The session cookie's token, if the request brings one.
fn session_cookie(request: &Request<Body>) -> Option<String> {
request
@@ -70,7 +80,8 @@ fn session_cookie(request: &Request<Body>) -> Option<String> {
/// A request with `Authorization: Bearer <token>`: its user is the token's, if this
/// node takes it (`token::verify`); `401`, saying why, if not. One without
/// `Authorization` but with the session cookie: the cookie's token's, if taken (if not,
-/// as if it brought none). Others go on to `auth::basic_auth`.
+/// as if it brought none), for reading only (`cookie_lets_in`). Others go on to
+/// `auth::basic_auth`.
pub(crate) async fn bearer(
State(state): State<AppState>,
mut request: Request<Body>,
@@ -86,7 +97,7 @@ pub(crate) async fn bearer(
Some(text) => (text.to_owned(), false),
None => return next.run(request).await,
},
- None => match session_cookie(&request) {
+ None => match session_cookie(&request).filter(|_| cookie_lets_in(&request)) {
Some(text) => (text, true),
None => return next.run(request).await,
},