From 1db5eade4e59e86758b07e80e49de48172d79448 Mon Sep 17 00:00:00 2001 From: Benjamin Sherriff Date: Wed, 18 Oct 2023 16:22:45 -0400 Subject: [PATCH] Implemented logout --- service/src/auth/routes.rs | 68 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 65 insertions(+), 3 deletions(-) diff --git a/service/src/auth/routes.rs b/service/src/auth/routes.rs index d5588c9..a9f0f6c 100644 --- a/service/src/auth/routes.rs +++ b/service/src/auth/routes.rs @@ -158,7 +158,7 @@ async fn refresh(req: HttpRequest) -> HttpResponse { }; match QueryUser::get_by_email(&email) { - Ok(_) => { + Ok(query_user) => { let access_token_details = match generate_access_token(&email) { Ok(token_details) => token_details, Err(err) => { @@ -192,10 +192,12 @@ async fn refresh(req: HttpRequest) -> HttpResponse { .http_only(false) .finish(); + let access_token_uuid = uuid::Uuid::parse_str(&access_token_details.token_uuid.to_string()).unwrap(); + HttpResponse::Ok() .cookie(access_cookie) .cookie(logged_in_cookie) - .json(access_token_details.token.unwrap()) + .json(JwtAuth { token: access_token_uuid, user: query_user.into() }) }, Err(err) => return ResponseError::error_response(&err) } @@ -203,7 +205,61 @@ async fn refresh(req: HttpRequest) -> HttpResponse { #[post("/logout")] async fn logout(req: HttpRequest, auth: JwtAuth) -> HttpResponse { - HttpResponse::Ok().finish() + let refresh_token = match req.cookie("refresh_token") { + Some(cookie) => cookie.value().to_string(), + None => return ResponseError::error_response(&ServiceError { + status: 401, + message: "Refresh token not found".to_string() + }) + }; + let public_key = env::var("REFRESH_TOKEN_PUBLIC_KEY") + .expect("REFRESH_TOKEN_PUBLIC_KEY must be set"); + let refresh_token_details = match verify_token(&refresh_token, &public_key) { + Ok(token_details) => token_details, + Err(err) => return ResponseError::error_response(&err) + }; + + let mut conn = match db::redis_async_connection().await { + Ok(conn) => conn, + Err(err) => { + error!("Failed to get redis connection: {}", err); + return ResponseError::error_response(&err) + } + }; + + let access_result: redis::RedisResult<()> = conn.del(&[ + refresh_token_details.token_uuid.to_string(), + auth.token.to_string() + ]).await; + if let Err(err) = access_result { + error!("Failed to set access token in redis: {}", err); + return ResponseError::error_response(&ServiceError { + status: 500, + message: format!("Failed to set access token in redis: {}", err) + }) + }; + + let access_cookie = Cookie::build("access_token", "") + .path("/") + .max_age(Duration::new(-1, 0)) + .http_only(true) + .finish(); + let refresh_cookie = Cookie::build("refresh_token", "") + .path("/") + .max_age(Duration::new(-1, 0)) + .http_only(true) + .finish(); + let logged_in_cookie = Cookie::build("logged_in", "") + .path("/") + .max_age(Duration::new(-1, 0)) + .http_only(true) + .finish(); + + HttpResponse::Ok() + .cookie(access_cookie) + .cookie(refresh_cookie) + .cookie(logged_in_cookie) + .finish() } #[get("/me")] @@ -211,6 +267,11 @@ async fn me(auth: JwtAuth) -> HttpResponse { HttpResponse::Ok().json(auth) } +#[get("/roles")] +async fn roles() -> HttpResponse { + HttpResponse::Ok().json(vec!["admin", "user"]) +} + pub fn init_routes(config: &mut web::ServiceConfig) { let r = RegisterUser { email: "admin".to_string(), @@ -227,5 +288,6 @@ pub fn init_routes(config: &mut web::ServiceConfig) { .service(refresh) .service(logout) .service(me) + .service(roles) ); } \ No newline at end of file