From 4eb63b8adda4559df3dadcf721e2bb0d1f65a01f Mon Sep 17 00:00:00 2001 From: Owen Jacobson Date: Sun, 24 Aug 2025 03:48:17 -0400 Subject: Stop returning body data from `POST /api/auth/login`. As with `/api/setup`, the response was an ad-hoc choice, which we are not using and which constrains future development just by existing. --- src/token/app.rs | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) (limited to 'src/token') diff --git a/src/token/app.rs b/src/token/app.rs index 49f9a45..7d70534 100644 --- a/src/token/app.rs +++ b/src/token/app.rs @@ -32,7 +32,7 @@ impl<'a> Tokens<'a> { name: &Name, password: &Password, login_at: &DateTime, - ) -> Result<(User, Secret), LoginError> { + ) -> Result { let mut tx = self.db.begin().await?; let (user, stored_hash) = tx .auth() @@ -47,18 +47,16 @@ impl<'a> Tokens<'a> { // if the account is deleted during that time. tx.commit().await?; - let snapshot = user.as_snapshot().ok_or(LoginError::Rejected)?; + user.as_snapshot().ok_or(LoginError::Rejected)?; - let token = if stored_hash.verify(password)? { + if stored_hash.verify(password)? { let mut tx = self.db.begin().await?; - let token = tx.tokens().issue(&user, login_at).await?; + let secret = tx.tokens().issue(&user, login_at).await?; tx.commit().await?; - token + Ok(secret) } else { - Err(LoginError::Rejected)? - }; - - Ok((snapshot, token)) + Err(LoginError::Rejected) + } } pub async fn change_password( -- cgit v1.2.3 From b922c4646aac28fd5f762604e54fd050e973ecd3 Mon Sep 17 00:00:00 2001 From: Owen Jacobson Date: Sun, 24 Aug 2025 04:08:20 -0400 Subject: Stop returning a body from `POST /api/password`. --- docs/api/authentication.md | 23 +++-------------------- src/token/app.rs | 6 +++--- src/user/handlers/password/mod.rs | 8 ++++---- src/user/handlers/password/test.rs | 13 +++++++++++-- 4 files changed, 21 insertions(+), 29 deletions(-) (limited to 'src/token') diff --git a/docs/api/authentication.md b/docs/api/authentication.md index 7694609..f1c0aea 100644 --- a/docs/api/authentication.md +++ b/docs/api/authentication.md @@ -121,29 +121,12 @@ The request must have the following fields: ### Success -This endpoint will respond with a status of -`200 Okay` when successful. The body of the response will be a JSON object describing the authenticated user: - -```json -{ - "id": "Uabcd1234", - "name": "Andrea" -} -``` - -The response will include the following fields: - -| Field | Type | Description | -| :----- | :----- | :----------------------------- | -| `id` | string | The authenticated user's ID. | -| `name` | string | The authenticated user's name. | +This endpoint will respond with a status of `204 No Content` when successful. -The response will include a `Set-Cookie` header for the -`identity` cookie, providing the client with a newly-minted identity token associated with the login identified in the request. This token's value must be kept confidential. All previously-created identity cookies will cease to be valid. +The response will include a `Set-Cookie` header for the `identity` cookie, providing the client with a newly-minted identity token associated with the login identified in the request. This token's value must be kept confidential. All previously-created identity cookies will cease to be valid. The cookie will expire if it is not used regularly. ### Authentication failure -This endpoint will respond with a status of `400 Bad Request` if the -`password` does not match the login's current password. +This endpoint will respond with a status of `400 Bad Request` if the `password` does not match the login's current password. diff --git a/src/token/app.rs b/src/token/app.rs index 7d70534..56c0e21 100644 --- a/src/token/app.rs +++ b/src/token/app.rs @@ -65,7 +65,7 @@ impl<'a> Tokens<'a> { password: &Password, to: &Password, changed_at: &DateTime, - ) -> Result<(User, Secret), LoginError> { + ) -> Result { let mut tx = self.db.begin().await?; let (user, stored_hash) = tx .auth() @@ -84,7 +84,7 @@ impl<'a> Tokens<'a> { return Err(LoginError::Rejected); } - let snapshot = user.as_snapshot().ok_or(LoginError::Rejected)?; + user.as_snapshot().ok_or(LoginError::Rejected)?; let to_hash = to.hash()?; let mut tx = self.db.begin().await?; @@ -97,7 +97,7 @@ impl<'a> Tokens<'a> { self.token_events.broadcast(event); } - Ok((snapshot, secret)) + Ok(secret) } pub async fn validate( diff --git a/src/user/handlers/password/mod.rs b/src/user/handlers/password/mod.rs index c327e87..5e69c1c 100644 --- a/src/user/handlers/password/mod.rs +++ b/src/user/handlers/password/mod.rs @@ -7,13 +7,13 @@ use axum::{ use crate::{ app::App, clock::RequestedAt, + empty::Empty, error::Internal, password::Password, token::{ app, extract::{Identity, IdentityCookie}, }, - user::User, }; #[cfg(test)] @@ -25,14 +25,14 @@ pub async fn handler( identity: Identity, cookie: IdentityCookie, Json(request): Json, -) -> Result<(IdentityCookie, Json), Error> { - let (login, secret) = app +) -> Result<(IdentityCookie, Empty), Error> { + let secret = app .tokens() .change_password(&identity.user, &request.password, &request.to, &now) .await .map_err(Error)?; let cookie = cookie.set(secret); - Ok((cookie, Json(login))) + Ok((cookie, Empty)) } #[derive(serde::Deserialize)] diff --git a/src/user/handlers/password/test.rs b/src/user/handlers/password/test.rs index 278d27b..ffa12f3 100644 --- a/src/user/handlers/password/test.rs +++ b/src/user/handlers/password/test.rs @@ -1,6 +1,7 @@ use axum::extract::{Json, State}; use crate::{ + empty::Empty, test::fixtures, token::app::{LoginError, ValidateError}, }; @@ -20,7 +21,7 @@ async fn password_change() { password: password.clone(), to: to.clone(), }; - let (new_cookie, Json(response)) = super::handler( + let (new_cookie, Empty) = super::handler( State(app.clone()), fixtures::now(), identity.clone(), @@ -34,7 +35,15 @@ async fn password_change() { assert_ne!(cookie.secret(), new_cookie.secret()); // Verify that we're still ourselves - assert_eq!(identity.user, response); + let new_secret = new_cookie + .secret() + .expect("we should have a secret after changing our password"); + let (_, login) = app + .tokens() + .validate(&new_secret, &fixtures::now()) + .await + .expect("the newly-issued secret should be valid"); + assert_eq!(identity.user, login); // Verify that our original token is no longer valid let validate_err = app -- cgit v1.2.3