From 38aab46534e823a9d33b33b23924405e2d5f58ca Mon Sep 17 00:00:00 2001 From: Radical Date: Sat, 31 May 2025 14:41:29 +0200 Subject: [PATCH 1/2] style: rename refresh_token_cookie() to new_refresh_token_cookie() and fix error message when no refresh_token is found on refresh --- src/api/v1/auth/login.rs | 4 ++-- src/api/v1/auth/refresh.rs | 16 ++++------------ src/api/v1/auth/register.rs | 4 ++-- src/utils.rs | 2 +- 4 files changed, 9 insertions(+), 17 deletions(-) diff --git a/src/api/v1/auth/login.rs b/src/api/v1/auth/login.rs index 5229425..04d6b4f 100644 --- a/src/api/v1/auth/login.rs +++ b/src/api/v1/auth/login.rs @@ -11,7 +11,7 @@ use crate::{ error::Error, schema::*, utils::{ - PASSWORD_REGEX, generate_access_token, generate_refresh_token, refresh_token_cookie, + PASSWORD_REGEX, generate_access_token, generate_refresh_token, new_refresh_token_cookie, user_uuid_from_identifier, }, }; @@ -89,6 +89,6 @@ pub async fn response( .await?; Ok(HttpResponse::Ok() - .cookie(refresh_token_cookie(refresh_token)) + .cookie(new_refresh_token_cookie(refresh_token)) .json(Response { access_token })) } diff --git a/src/api/v1/auth/refresh.rs b/src/api/v1/auth/refresh.rs index b64b10e..cc3bbe9 100644 --- a/src/api/v1/auth/refresh.rs +++ b/src/api/v1/auth/refresh.rs @@ -11,20 +11,16 @@ use crate::{ access_tokens::{self, dsl}, refresh_tokens::{self, dsl as rdsl}, }, - utils::{generate_access_token, generate_refresh_token, refresh_token_cookie}, + utils::{generate_access_token, generate_refresh_token, new_refresh_token_cookie}, }; use super::Response; #[post("/refresh")] pub async fn res(req: HttpRequest, data: web::Data) -> Result { - let recv_refresh_token_cookie = req.cookie("refresh_token"); + let mut refresh_token_cookie = req.cookie("refresh_token").ok_or(Error::Unauthorized("request has no refresh token".to_string()))?; - if recv_refresh_token_cookie.is_none() { - return Ok(HttpResponse::Unauthorized().finish()); - } - - let mut refresh_token = String::from(recv_refresh_token_cookie.unwrap().value()); + let mut refresh_token = String::from(refresh_token_cookie.value()); let current_time = SystemTime::now().duration_since(UNIX_EPOCH)?.as_secs() as i64; @@ -47,8 +43,6 @@ pub async fn res(req: HttpRequest, data: web::Data) -> Result) -> Result Result<&str, Error> { Ok(auth_value.unwrap()) } -pub fn refresh_token_cookie(refresh_token: String) -> Cookie<'static> { +pub fn new_refresh_token_cookie(refresh_token: String) -> Cookie<'static> { Cookie::build("refresh_token", refresh_token) .http_only(true) .secure(true) From 60f0219e85a74e9a41c834179983d41689a3a9e3 Mon Sep 17 00:00:00 2001 From: Radical Date: Sat, 31 May 2025 14:43:48 +0200 Subject: [PATCH 2/2] feat: add logout endpoint --- src/api/v1/auth/logout.rs | 31 +++++++++++++++++++++++++++++++ src/api/v1/auth/mod.rs | 2 ++ 2 files changed, 33 insertions(+) create mode 100644 src/api/v1/auth/logout.rs diff --git a/src/api/v1/auth/logout.rs b/src/api/v1/auth/logout.rs new file mode 100644 index 0000000..79b5c36 --- /dev/null +++ b/src/api/v1/auth/logout.rs @@ -0,0 +1,31 @@ +use actix_web::{HttpRequest, HttpResponse, post, web}; +use diesel::{ExpressionMethods, delete}; +use diesel_async::RunQueryDsl; + +use crate::{ + Data, + error::Error, + schema::refresh_tokens::{self, dsl}, +}; + +// TODO: Should maybe be a delete request? +#[post("/logout")] +pub async fn res( + req: HttpRequest, + data: web::Data, +) -> Result { + let mut refresh_token_cookie = req.cookie("refresh_token").ok_or(Error::Unauthorized("request has no refresh token".to_string()))?; + + let refresh_token = String::from(refresh_token_cookie.value()); + + let mut conn = data.pool.get().await?; + + delete(refresh_tokens::table) + .filter(dsl::token.eq(refresh_token)) + .execute(&mut conn) + .await?; + + refresh_token_cookie.make_removal(); + + Ok(HttpResponse::Ok().cookie(refresh_token_cookie).finish()) +} diff --git a/src/api/v1/auth/mod.rs b/src/api/v1/auth/mod.rs index d627a59..75a6b0b 100644 --- a/src/api/v1/auth/mod.rs +++ b/src/api/v1/auth/mod.rs @@ -9,6 +9,7 @@ use uuid::Uuid; use crate::{Conn, error::Error, schema::access_tokens::dsl}; mod login; +mod logout; mod refresh; mod register; mod reset_password; @@ -24,6 +25,7 @@ pub fn web() -> Scope { web::scope("/auth") .service(register::res) .service(login::response) + .service(logout::res) .service(refresh::res) .service(revoke::res) .service(verify_email::get)