summaryrefslogtreecommitdiffstats
path: root/src/api/auth.rs
diff options
context:
space:
mode:
authortv <tv@krebsco.de>2026-10-24 19:25:54 +0200
committertv <tv@krebsco.de>2026-10-24 19:25:54 +0200
commit815ec2e9a641ad5ac5c2f886291e63c89966bd6c (patch)
tree5840ab9e9adc8e5ab5259ef0da7949880cde5f53 /src/api/auth.rs
parent09f2dfd083c4fcdce4c5ca7376353906eb025c42 (diff)
only protocol-writers may modify _continuum
Diffstat (limited to 'src/api/auth.rs')
-rw-r--r--src/api/auth.rs25
1 files changed, 15 insertions, 10 deletions
diff --git a/src/api/auth.rs b/src/api/auth.rs
index 70b1af5..de4220c 100644
--- a/src/api/auth.rs
+++ b/src/api/auth.rs
@@ -72,14 +72,18 @@ fn parse_basic(headers: &HeaderMap) -> Option<(String, String)> {
Some((user.to_owned(), pass.to_owned()))
}
-async fn authenticate(state: &AuthState, headers: &HeaderMap) -> bool {
- let Some((user, pass)) = parse_basic(headers) else {
- return false;
- };
- let Some(hash) = state.users.get(&user).cloned() else {
- return false;
- };
+/// The user a request authenticated as (a request extension, set by [`basic_auth`]).
+#[derive(Clone, Debug)]
+pub(crate) struct AuthenticatedUser(pub(crate) String);
+/// The user, if the credentials are valid.
+async fn authenticate(state: &AuthState, headers: &HeaderMap) -> Option<String> {
+ let (user, pass) = parse_basic(headers)?;
+ let hash = state.users.get(&user).cloned()?;
+ verify(state, &user, pass, hash).await.then_some(user)
+}
+
+async fn verify(state: &AuthState, user: &str, pass: String, hash: String) -> bool {
let key = *blake3::hash(format!("{user}\0{pass}\0{hash}").as_bytes()).as_bytes();
// Fast path. The shard guard lives only until the end of this `match`;
@@ -124,10 +128,10 @@ async fn authenticate(state: &AuthState, headers: &HeaderMap) -> bool {
pub async fn basic_auth(
State(state): State<AuthState>,
headers: HeaderMap,
- request: Request<Body>,
+ mut request: Request<Body>,
next: axum::middleware::Next,
) -> Response {
- if !authenticate(&state, &headers).await {
+ let Some(user) = authenticate(&state, &headers).await else {
sleep(Duration::from_millis(1500)).await;
return (
StatusCode::UNAUTHORIZED,
@@ -135,7 +139,8 @@ pub async fn basic_auth(
"Unauthorized",
)
.into_response();
- }
+ };
+ request.extensions_mut().insert(AuthenticatedUser(user));
next.run(request).await
}