From 3a9be114d82f882f777fc54c7453e4c21a32c194 Mon Sep 17 00:00:00 2001 From: Samuel Lorch Date: Thu, 26 Oct 2023 00:28:17 +0200 Subject: [PATCH] get Authentication and Sessions working --- src/web/auth.rs | 106 ++++++++++++++++++++++++++++++++++++------------ 1 file changed, 79 insertions(+), 27 deletions(-) diff --git a/src/web/auth.rs b/src/web/auth.rs index 8348573..15d521a 100644 --- a/src/web/auth.rs +++ b/src/web/auth.rs @@ -1,12 +1,14 @@ use std::collections::HashMap; +use std::error::Error; use std::hash::Hash; use std::sync::{Arc, RwLock}; +use uuid::Uuid; use super::super::AppState; use axum::routing::post; use axum::{Json, Router}; use serde::Deserialize; -use tower_cookies::Cookies; +use tower_cookies::{Cookie, Cookies}; use axum::{ extract::Extension, @@ -16,6 +18,13 @@ use axum::{ response::{IntoResponse, Response}, }; +use custom_error::custom_error; + +custom_error! { AuthError + NoSessionCookie = "No Session Cookie Found", + InvalidSession = "Invalid Session" +} + const SESSION_COOKIE: &str = "session"; #[derive(Clone, Debug)] @@ -25,8 +34,10 @@ pub struct SessionState { #[derive(Clone, Debug)] pub struct Session { - username: String, + pub username: String, //expires: time, + // TODO have permissions here for fast access, update Permissions with a config manager apply function + // permissions } #[derive(Clone, Debug, Deserialize)] @@ -46,50 +57,91 @@ async fn login_handler( cookies: Cookies, State(state): State, Json(payload): Json, - // mut session_state: SessionState, ) -> impl IntoResponse { - //cookies.add(Cookie::new()); - todo!() + if let Some(user) = state + .config_manager + .get_current_config() + .system + .users + .get(&payload.username.to_string()) + { + // TODO use propper hash algorithm compatible with /etc/passwd + if payload.password == "nfsense" { + let mut sessions = state.session_state.sessions.write().unwrap(); + let id = Uuid::new_v4().to_string(); + + sessions.insert( + id.clone(), + Session { + username: payload.username, + }, + ); + + cookies.add(Cookie::new(SESSION_COOKIE, id)); + return StatusCode::OK; + } + } + StatusCode::UNAUTHORIZED } -async fn logout_handler(cookies: Cookies, app_state: State) -> impl IntoResponse { - /* - if let Some(session_cookie) = cookies.get(SESSION_COOKIE) { - let session_id = session_cookie.value(); +async fn logout_handler(cookies: Cookies, state: State) -> impl IntoResponse { + let session_cookie = cookies.get(SESSION_COOKIE); + match session_cookie { + Some(s) => { + let session_id = s.value(); - // TODO check that sessions_id is a valid uuidv4 + let mut sessions = state.session_state.sessions.write().unwrap(); - session_state.sessions.remove(session_id); - cookies.remove(session_cookie); + // TODO Fix Cookie remove + // cookies.remove(s.clone()); + + if let Some(session) = sessions.get(session_id) { + sessions.remove(session_id); + return StatusCode::OK; + } + return StatusCode::UNAUTHORIZED; + } + None => return StatusCode::UNAUTHORIZED, + } +} + +fn get_session(cookies: Cookies, state: SessionState) -> Result { + let session_cookie = cookies.get(SESSION_COOKIE); + match session_cookie { + Some(s) => { + let session_id = s.value(); + + let sessions = state.sessions.write().unwrap(); + + if let Some(session) = sessions.get(session_id) { + return Ok(session.clone()); + } + return Err(AuthError::InvalidSession); + } + None => return Err(AuthError::NoSessionCookie), } - */ - todo!() } async fn session_handler(cookies: Cookies, State(state): State) -> impl IntoResponse { - //return Err(StatusCode::UNAUTHORIZED); - todo!() + match get_session(cookies, state.session_state) { + // TODO Return build git commit hash as json result for frontend reloading + Ok(_) => return StatusCode::OK, + Err(_) => return StatusCode::UNAUTHORIZED, + } } pub async fn mw_auth( - app_state: State, + state: State, cookies: Cookies, mut req: Request, next: Next, // session_state: SessionState, ) -> Result { - /* - if let Some(session_cookie) = cookies.get(SESSION_COOKIE) { - let session_id = session_cookie.value(); - - // TODO check that sessions_id is a valid uuidv4 - - if let Some(session) = session_state.sessions.get(session_id) { + match get_session(cookies, state.session_state.clone()) { + Ok(session) => { req.extensions_mut().insert(session.clone()); return Ok(next.run(req).await); } + Err(_) => return Err(StatusCode::UNAUTHORIZED), } - return Err(StatusCode::UNAUTHORIZED); - */ - todo!() }