From e19f71fd1c4dae25971c5eb00a5e8ac88971f201 Mon Sep 17 00:00:00 2001 From: phoenix Date: Mon, 7 Apr 2025 12:27:21 -0400 Subject: [PATCH 01/10] Simplifying code --- src/callers/login.rs | 77 ++++++++++++++++++++++---------------------- 1 file changed, 38 insertions(+), 39 deletions(-) diff --git a/src/callers/login.rs b/src/callers/login.rs index 66286ee..4724a88 100644 --- a/src/callers/login.rs +++ b/src/callers/login.rs @@ -49,53 +49,52 @@ pub mod endpoint { }; // Check if user exists - match repo::user::exists(&pool, &usr.username).await { - Ok(exists) => { - if !exists { - return not_found("Not Found").await; - } - } - Err(err) => { - return not_found(&err.to_string()).await; - } - }; + // match repo::user::exists(&pool, &usr.username).await { + match repo::user::get(&pool, &usr.username).await { + Ok(user) => { + let salt = repo::salt::get(&pool, &user.salt_id).await.unwrap(); + let salt_str = hashing::get_salt(&salt.salt).unwrap(); - let user = repo::user::get(&pool, &usr.username).await.unwrap(); - let salt = repo::salt::get(&pool, &user.salt_id).await.unwrap(); - let salt_str = hashing::get_salt(&salt.salt).unwrap(); + // Check if password is correct + match hashing::hash_password(&usr.password, &salt_str) { + Ok(hash_password) => { + if hashing::verify_password(&usr.password, hash_password.clone()).unwrap() { + // Create token + let key = token_stuff::get_key().unwrap(); + let (token_literal, duration) = + token_stuff::create_token(&key).unwrap(); - // Check if password is correct - match hashing::hash_password(&usr.password, &salt_str) { - Ok(hash_password) => { - if hashing::verify_password(&usr.password, hash_password.clone()).unwrap() { - // Create token - let key = token_stuff::get_key().unwrap(); - let (token_literal, duration) = token_stuff::create_token(&key).unwrap(); - - if token_stuff::verify_token(&key, &token_literal) { - ( - StatusCode::OK, - Json(response::Response { - message: String::from("Successful"), - data: vec![icarus_models::login_result::LoginResult { - id: user.id, - username: user.username, - token: token_literal, - token_type: String::from(token_stuff::TOKENTYPE), - expiration: duration, - }], - }), - ) - } else { - return not_found("Could not verify password").await; + if token_stuff::verify_token(&key, &token_literal) { + ( + StatusCode::OK, + Json(response::Response { + message: String::from("Successful"), + data: vec![icarus_models::login_result::LoginResult { + id: user.id, + username: user.username, + token: token_literal, + token_type: String::from(token_stuff::TOKENTYPE), + expiration: duration, + }], + }), + ) + } else { + return not_found("Could not verify password").await; + } + } else { + return not_found("Error Hashing").await; + } + } + Err(err) => { + return not_found(&err.to_string()).await; } - } else { - return not_found("Error Hashing").await; } } Err(err) => { return not_found(&err.to_string()).await; } } + + // let user = repo::user::get(&pool, &usr.username).await.unwrap(); } } -- 2.43.0 From 7cac6d5aae9ff8b0ab673533dcec1879f21ed623 Mon Sep 17 00:00:00 2001 From: phoenix Date: Mon, 7 Apr 2025 12:31:58 -0400 Subject: [PATCH 02/10] Code refactor --- src/callers/login.rs | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/src/callers/login.rs b/src/callers/login.rs index 4724a88..76a4272 100644 --- a/src/callers/login.rs +++ b/src/callers/login.rs @@ -42,23 +42,19 @@ pub mod endpoint { axum::Extension(pool): axum::Extension, Json(payload): Json, ) -> (StatusCode, Json) { - let usr = icarus_models::user::User { - username: payload.username, - password: payload.password, - ..Default::default() - }; - // Check if user exists - // match repo::user::exists(&pool, &usr.username).await { - match repo::user::get(&pool, &usr.username).await { + match repo::user::get(&pool, &payload.username).await { Ok(user) => { let salt = repo::salt::get(&pool, &user.salt_id).await.unwrap(); let salt_str = hashing::get_salt(&salt.salt).unwrap(); + let unhashed_password = payload.password; // Check if password is correct - match hashing::hash_password(&usr.password, &salt_str) { + match hashing::hash_password(&unhashed_password, &salt_str) { Ok(hash_password) => { - if hashing::verify_password(&usr.password, hash_password.clone()).unwrap() { + if hashing::verify_password(&unhashed_password, hash_password.clone()) + .unwrap() + { // Create token let key = token_stuff::get_key().unwrap(); let (token_literal, duration) = @@ -94,7 +90,5 @@ pub mod endpoint { return not_found(&err.to_string()).await; } } - - // let user = repo::user::get(&pool, &usr.username).await.unwrap(); } } -- 2.43.0 From 8ddc2f73c4f80f93613d65eba0cc5a549ddf85d7 Mon Sep 17 00:00:00 2001 From: phoenix Date: Mon, 7 Apr 2025 13:11:49 -0400 Subject: [PATCH 03/10] Using functions for setting times on tokens --- src/token_stuff/mod.rs | 39 ++++++++++++++++++++++++++++++++------- 1 file changed, 32 insertions(+), 7 deletions(-) diff --git a/src/token_stuff/mod.rs b/src/token_stuff/mod.rs index 2771dec..31ca615 100644 --- a/src/token_stuff/mod.rs +++ b/src/token_stuff/mod.rs @@ -18,11 +18,28 @@ pub fn get_key() -> Result { Ok(key) } -pub fn get_expiration() -> time::Result { +pub fn get_issued() -> time::Result { let now = time::OffsetDateTime::now_utc(); - let epoch = time::OffsetDateTime::UNIX_EPOCH; - let since_the_epoch = now - epoch; - Ok(since_the_epoch) + // let epoch = time::OffsetDateTime::UNIX_EPOCH; + // let since_the_epoch = now - epoch; + // Ok(since_the_epoch) + Ok(now) +} + +pub fn get_expiration(issued: &time::OffsetDateTime) -> Result { + let duration_expire = time::Duration::hours(4); + let expiration = *issued + duration_expire; + Ok(expiration) +} + +mod util { + // use std::time; + pub fn time_to_std_time( + provided_time: &time::OffsetDateTime, + ) -> Result { + let converted = std::time::SystemTime::from(*provided_time); + Ok(converted) + } } pub fn create_token(provided_key: &String) -> Result<(String, i64), josekit::JoseError> { @@ -33,13 +50,19 @@ pub fn create_token(provided_key: &String) -> Result<(String, i64), josekit::Jos payload.set_subject(MESSAGE); payload.set_issuer(ISSUER); payload.set_audience(vec![AUDIENCE]); - match get_expiration() { - Ok(duration) => { + match get_issued() { + Ok(issued) => { + /* let expire = duration.whole_seconds(); let _ = payload.set_claim( - "expiration", + "issued", Some(serde_json::to_value(expire.to_string()).unwrap()), ); + */ + let expire = get_expiration(&issued).unwrap(); + // payload.set_issued_at(std::time::Duration::try_from(duration).unwrap()); + payload.set_issued_at(&util::time_to_std_time(&issued).unwrap()); + payload.set_expires_at(&util::time_to_std_time(&expire).unwrap()); let key: String = if provided_key.is_empty() { get_key().unwrap() @@ -47,6 +70,8 @@ pub fn create_token(provided_key: &String) -> Result<(String, i64), josekit::Jos provided_key.to_owned() }; + let duration = expire - time::OffsetDateTime::UNIX_EPOCH; + let signer = Hs256.signer_from_bytes(key.as_bytes()).unwrap(); Ok(( josekit::jwt::encode_with_signer(&payload, &header, &signer).unwrap(), -- 2.43.0 From 90db1a97fb09f17d45f92a39ba8abf18c2cc810b Mon Sep 17 00:00:00 2001 From: phoenix Date: Mon, 7 Apr 2025 13:16:21 -0400 Subject: [PATCH 04/10] Code cleanup --- src/token_stuff/mod.rs | 22 +++------------------- 1 file changed, 3 insertions(+), 19 deletions(-) diff --git a/src/token_stuff/mod.rs b/src/token_stuff/mod.rs index 31ca615..d189a2d 100644 --- a/src/token_stuff/mod.rs +++ b/src/token_stuff/mod.rs @@ -19,21 +19,15 @@ pub fn get_key() -> Result { } pub fn get_issued() -> time::Result { - let now = time::OffsetDateTime::now_utc(); - // let epoch = time::OffsetDateTime::UNIX_EPOCH; - // let since_the_epoch = now - epoch; - // Ok(since_the_epoch) - Ok(now) + Ok(time::OffsetDateTime::now_utc()) } pub fn get_expiration(issued: &time::OffsetDateTime) -> Result { let duration_expire = time::Duration::hours(4); - let expiration = *issued + duration_expire; - Ok(expiration) + Ok(*issued + duration_expire) } mod util { - // use std::time; pub fn time_to_std_time( provided_time: &time::OffsetDateTime, ) -> Result { @@ -52,15 +46,7 @@ pub fn create_token(provided_key: &String) -> Result<(String, i64), josekit::Jos payload.set_audience(vec![AUDIENCE]); match get_issued() { Ok(issued) => { - /* - let expire = duration.whole_seconds(); - let _ = payload.set_claim( - "issued", - Some(serde_json::to_value(expire.to_string()).unwrap()), - ); - */ let expire = get_expiration(&issued).unwrap(); - // payload.set_issued_at(std::time::Duration::try_from(duration).unwrap()); payload.set_issued_at(&util::time_to_std_time(&issued).unwrap()); payload.set_expires_at(&util::time_to_std_time(&expire).unwrap()); @@ -70,12 +56,10 @@ pub fn create_token(provided_key: &String) -> Result<(String, i64), josekit::Jos provided_key.to_owned() }; - let duration = expire - time::OffsetDateTime::UNIX_EPOCH; - let signer = Hs256.signer_from_bytes(key.as_bytes()).unwrap(); Ok(( josekit::jwt::encode_with_signer(&payload, &header, &signer).unwrap(), - duration.whole_seconds(), + (expire - time::OffsetDateTime::UNIX_EPOCH).whole_seconds(), )) } Err(e) => Err(josekit::JoseError::InvalidClaim(e.into())), -- 2.43.0 From 905a06111cf4f7ac041bcc61ea5449dad4b0a9e3 Mon Sep 17 00:00:00 2001 From: phoenix Date: Mon, 7 Apr 2025 13:38:04 -0400 Subject: [PATCH 05/10] Added test for checking for wrong hashed password --- src/hashing/mod.rs | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/src/hashing/mod.rs b/src/hashing/mod.rs index a3fbbd4..83e7806 100644 --- a/src/hashing/mod.rs +++ b/src/hashing/mod.rs @@ -81,4 +81,30 @@ mod tests { } } } + + #[test] + fn test_wrong_password() { + let some_password = String::from("somethingrandom"); + let salt = generate_salt().unwrap(); + match hash_password(&some_password, &salt) { + Ok(p) => { + match verify_password(&some_password, p.clone()) { + Ok(res) => { + assert_eq!(res, true, "Passwords are not verified"); + let wrong_password = String::from("Differentanotherlevel"); + // wrong_password = some_password; + // let hashed_wrong_password = hash_password(&wrong_password, &salt).unwrap(); + let result = verify_password(&wrong_password, p.clone()).unwrap(); + assert_eq!(false, result, "Passwords should not match"); + } + Err(err) => { + assert!(false, "Error: {:?}", err.to_string()); + } + } + } + Err(err) => { + assert!(false, "Error: {:?}", err.to_string()); + } + } + } } -- 2.43.0 From 6b7fa86f592a025a2eb73ca672017e0e330e6afa Mon Sep 17 00:00:00 2001 From: phoenix Date: Mon, 7 Apr 2025 13:46:23 -0400 Subject: [PATCH 06/10] Bug fix --- src/callers/login.rs | 60 ++++++++++++++++++++++---------------------- 1 file changed, 30 insertions(+), 30 deletions(-) diff --git a/src/callers/login.rs b/src/callers/login.rs index 76a4272..6558af6 100644 --- a/src/callers/login.rs +++ b/src/callers/login.rs @@ -45,46 +45,46 @@ pub mod endpoint { // Check if user exists match repo::user::get(&pool, &payload.username).await { Ok(user) => { - let salt = repo::salt::get(&pool, &user.salt_id).await.unwrap(); - let salt_str = hashing::get_salt(&salt.salt).unwrap(); + // let salt = repo::salt::get(&pool, &user.salt_id).await.unwrap(); + // let salt_str = hashing::get_salt(&salt.salt).unwrap(); let unhashed_password = payload.password; + if hashing::verify_password(&unhashed_password, user.password.clone()).unwrap() { + // Create token + let key = token_stuff::get_key().unwrap(); + let (token_literal, duration) = token_stuff::create_token(&key).unwrap(); + + if token_stuff::verify_token(&key, &token_literal) { + ( + StatusCode::OK, + Json(response::Response { + message: String::from("Successful"), + data: vec![icarus_models::login_result::LoginResult { + id: user.id, + username: user.username, + token: token_literal, + token_type: String::from(token_stuff::TOKENTYPE), + expiration: duration, + }], + }), + ) + } else { + return not_found("Could not verify password").await; + } + } else { + return not_found("Error Hashing").await; + } + // Check if password is correct + /* match hashing::hash_password(&unhashed_password, &salt_str) { Ok(hash_password) => { - if hashing::verify_password(&unhashed_password, hash_password.clone()) - .unwrap() - { - // Create token - let key = token_stuff::get_key().unwrap(); - let (token_literal, duration) = - token_stuff::create_token(&key).unwrap(); - - if token_stuff::verify_token(&key, &token_literal) { - ( - StatusCode::OK, - Json(response::Response { - message: String::from("Successful"), - data: vec![icarus_models::login_result::LoginResult { - id: user.id, - username: user.username, - token: token_literal, - token_type: String::from(token_stuff::TOKENTYPE), - expiration: duration, - }], - }), - ) - } else { - return not_found("Could not verify password").await; - } - } else { - return not_found("Error Hashing").await; - } } Err(err) => { return not_found(&err.to_string()).await; } } + */ } Err(err) => { return not_found(&err.to_string()).await; -- 2.43.0 From 785af4b4a3a35c57f0c335214fd0cf63ab4df459 Mon Sep 17 00:00:00 2001 From: phoenix Date: Mon, 7 Apr 2025 13:56:26 -0400 Subject: [PATCH 07/10] Code cleanup --- src/callers/login.rs | 17 +---------------- src/hashing/mod.rs | 25 ++++++++----------------- 2 files changed, 9 insertions(+), 33 deletions(-) diff --git a/src/callers/login.rs b/src/callers/login.rs index 6558af6..6f2908e 100644 --- a/src/callers/login.rs +++ b/src/callers/login.rs @@ -45,11 +45,7 @@ pub mod endpoint { // Check if user exists match repo::user::get(&pool, &payload.username).await { Ok(user) => { - // let salt = repo::salt::get(&pool, &user.salt_id).await.unwrap(); - // let salt_str = hashing::get_salt(&salt.salt).unwrap(); - let unhashed_password = payload.password; - - if hashing::verify_password(&unhashed_password, user.password.clone()).unwrap() { + if hashing::verify_password(&payload.password, user.password.clone()).unwrap() { // Create token let key = token_stuff::get_key().unwrap(); let (token_literal, duration) = token_stuff::create_token(&key).unwrap(); @@ -74,17 +70,6 @@ pub mod endpoint { } else { return not_found("Error Hashing").await; } - - // Check if password is correct - /* - match hashing::hash_password(&unhashed_password, &salt_str) { - Ok(hash_password) => { - } - Err(err) => { - return not_found(&err.to_string()).await; - } - } - */ } Err(err) => { return not_found(&err.to_string()).await; diff --git a/src/hashing/mod.rs b/src/hashing/mod.rs index 83e7806..2c53f0b 100644 --- a/src/hashing/mod.rs +++ b/src/hashing/mod.rs @@ -11,8 +11,7 @@ use argon2::{ pub fn generate_salt() -> Result { // Generate a random salt // SaltString::generate uses OsRng internally for cryptographic security - let salt = SaltString::generate(&mut OsRng); - Ok(salt) + Ok(SaltString::generate(&mut OsRng)) } pub fn get_salt(s: &str) -> Result { @@ -32,9 +31,7 @@ pub fn hash_password( // Hash the password with the salt // The output is a PasswordHash string format that includes algorithm, version, // parameters, salt, and the hash itself. - let password_hash = argon2.hash_password(password_bytes, salt)?.to_string(); - - Ok(password_hash) + Ok(argon2.hash_password(password_bytes, salt)?.to_string()) } pub fn verify_password( @@ -48,11 +45,9 @@ pub fn verify_password( let parsed_hash = argon2::PasswordHash::new(stored_hash.as_str())?; // Create an Argon2 instance (it will use the parameters from the parsed hash) - let argon2 = Argon2::default(); - // Verify the password against the parsed hash // This automatically uses the correct salt and parameters embedded in `parsed_hash` - match argon2.verify_password(password_bytes, &parsed_hash) { + match Argon2::default().verify_password(password_bytes, &parsed_hash) { Ok(()) => Ok(true), // Passwords match Err(argon2::password_hash::Error::Password) => Ok(false), // Passwords don't match Err(e) => Err(e), // Some other error occurred (e.g., invalid hash format) @@ -66,8 +61,7 @@ mod tests { #[test] fn test_hash_password() { let some_password = String::from("somethingrandom"); - let salt = generate_salt().unwrap(); - match hash_password(&some_password, &salt) { + match hash_password(&some_password, &generate_salt().unwrap()) { Ok(p) => match verify_password(&some_password, p.clone()) { Ok(res) => { assert_eq!(res, true); @@ -85,22 +79,19 @@ mod tests { #[test] fn test_wrong_password() { let some_password = String::from("somethingrandom"); - let salt = generate_salt().unwrap(); - match hash_password(&some_password, &salt) { + match hash_password(&some_password, &generate_salt().unwrap()) { Ok(p) => { match verify_password(&some_password, p.clone()) { Ok(res) => { assert_eq!(res, true, "Passwords are not verified"); - let wrong_password = String::from("Differentanotherlevel"); - // wrong_password = some_password; - // let hashed_wrong_password = hash_password(&wrong_password, &salt).unwrap(); - let result = verify_password(&wrong_password, p.clone()).unwrap(); - assert_eq!(false, result, "Passwords should not match"); } Err(err) => { assert!(false, "Error: {:?}", err.to_string()); } } + let wrong_password = String::from("Differentanotherlevel"); + let result = verify_password(&wrong_password, p.clone()).unwrap(); + assert_eq!(false, result, "Passwords should not match"); } Err(err) => { assert!(false, "Error: {:?}", err.to_string()); -- 2.43.0 From 713108aa6d36a70f8c167436dc4292172c233df5 Mon Sep 17 00:00:00 2001 From: phoenix Date: Mon, 7 Apr 2025 14:02:54 -0400 Subject: [PATCH 08/10] Code cleanup --- src/callers/common.rs | 61 ++++++++++++++++++++++++------------------- src/main.rs | 10 +++++-- 2 files changed, 42 insertions(+), 29 deletions(-) diff --git a/src/callers/common.rs b/src/callers/common.rs index afb5ffb..bf178b3 100644 --- a/src/callers/common.rs +++ b/src/callers/common.rs @@ -1,30 +1,37 @@ -use axum::{Extension, Json, http::StatusCode}; +pub mod response { + use serde::{Deserialize, Serialize}; -use serde::{Deserialize, Serialize}; - -#[derive(Deserialize, Serialize)] -pub struct TestResult { - message: String, -} - -// basic handler that responds with a static string -pub async fn root() -> &'static str { - "Hello, World!" -} - -pub async fn db_ping(Extension(pool): Extension) -> (StatusCode, Json) { - match sqlx::query("SELECT 1").execute(&pool).await { - Ok(_) => { - let tr = TestResult { - message: String::from("This works"), - }; - (StatusCode::OK, Json(tr)) - } - Err(e) => ( - StatusCode::BAD_REQUEST, - Json(TestResult { - message: e.to_string(), - }), - ), + #[derive(Deserialize, Serialize)] + pub struct TestResult { + pub message: String, + } +} + +pub mod endpoint { + use super::*; + use axum::{Extension, Json, http::StatusCode}; + + // basic handler that responds with a static string + pub async fn root() -> &'static str { + "Hello, World!" + } + + pub async fn db_ping( + Extension(pool): Extension, + ) -> (StatusCode, Json) { + match sqlx::query("SELECT 1").execute(&pool).await { + Ok(_) => { + let tr = response::TestResult { + message: String::from("This works"), + }; + (StatusCode::OK, Json(tr)) + } + Err(e) => ( + StatusCode::BAD_REQUEST, + Json(response::TestResult { + message: e.to_string(), + }), + ), + } } } diff --git a/src/main.rs b/src/main.rs index 2dfe642..48239d6 100644 --- a/src/main.rs +++ b/src/main.rs @@ -25,8 +25,14 @@ mod init { pub async fn routes() -> Router { // build our application with a route Router::new() - .route(callers::endpoints::DBTEST, get(callers::common::db_ping)) - .route(callers::endpoints::ROOT, get(callers::common::root)) + .route( + callers::endpoints::DBTEST, + get(callers::common::endpoint::db_ping), + ) + .route( + callers::endpoints::ROOT, + get(callers::common::endpoint::root), + ) .route( callers::endpoints::REGISTER, post(callers::register::register_user), -- 2.43.0 From f9aaa2970fada8b58e33a1325688150839133212 Mon Sep 17 00:00:00 2001 From: phoenix Date: Mon, 7 Apr 2025 13:11:49 -0400 Subject: [PATCH 09/10] Using functions for setting times on tokens --- src/token_stuff/mod.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/token_stuff/mod.rs b/src/token_stuff/mod.rs index d189a2d..7ecb355 100644 --- a/src/token_stuff/mod.rs +++ b/src/token_stuff/mod.rs @@ -56,6 +56,8 @@ pub fn create_token(provided_key: &String) -> Result<(String, i64), josekit::Jos provided_key.to_owned() }; + let duration = expire - time::OffsetDateTime::UNIX_EPOCH; + let signer = Hs256.signer_from_bytes(key.as_bytes()).unwrap(); Ok(( josekit::jwt::encode_with_signer(&payload, &header, &signer).unwrap(), -- 2.43.0 From 8952763fd0f8caf704d268976a243f0309897326 Mon Sep 17 00:00:00 2001 From: phoenix Date: Mon, 7 Apr 2025 13:16:21 -0400 Subject: [PATCH 10/10] Code cleanup --- src/token_stuff/mod.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/token_stuff/mod.rs b/src/token_stuff/mod.rs index 7ecb355..d189a2d 100644 --- a/src/token_stuff/mod.rs +++ b/src/token_stuff/mod.rs @@ -56,8 +56,6 @@ pub fn create_token(provided_key: &String) -> Result<(String, i64), josekit::Jos provided_key.to_owned() }; - let duration = expire - time::OffsetDateTime::UNIX_EPOCH; - let signer = Hs256.signer_from_bytes(key.as_bytes()).unwrap(); Ok(( josekit::jwt::encode_with_signer(&payload, &header, &signer).unwrap(), -- 2.43.0