From 8164c89d8ee7801638de8640bf45539089e74743 Mon Sep 17 00:00:00 2001 From: phoenix Date: Mon, 4 Aug 2025 19:54:58 -0400 Subject: [PATCH 01/16] tsk-51: Added string for refresh token endpoint --- src/callers/mod.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/callers/mod.rs b/src/callers/mod.rs index 4fdaf82..f280a4f 100644 --- a/src/callers/mod.rs +++ b/src/callers/mod.rs @@ -8,4 +8,5 @@ pub mod endpoints { pub const DBTEST: &str = "/api/v2/test/db"; pub const LOGIN: &str = "/api/v2/login"; pub const SERVICE_LOGIN: &str = "/api/v2/service/login"; + pub const REFRESH_TOKEN: &str = "/api/v2/token/refresh"; } -- 2.43.0 From ce4e2c1712c0b13d377513ff230a4dcaf280b971 Mon Sep 17 00:00:00 2001 From: phoenix Date: Mon, 4 Aug 2025 19:55:20 -0400 Subject: [PATCH 02/16] tsk-51: Added TODO --- src/callers/login.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/callers/login.rs b/src/callers/login.rs index 6d5fd20..33e0d52 100644 --- a/src/callers/login.rs +++ b/src/callers/login.rs @@ -132,4 +132,6 @@ pub mod endpoint { } } } + + // TODO: Add endpoint to get a refresh token } -- 2.43.0 From 6333444b04b53658b4e9947a007f81f3365c1586 Mon Sep 17 00:00:00 2001 From: phoenix Date: Tue, 5 Aug 2025 18:49:20 -0400 Subject: [PATCH 03/16] tsk-51: Added endpoint to obtain refresh token --- src/callers/login.rs | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/src/callers/login.rs b/src/callers/login.rs index 33e0d52..b1c79ab 100644 --- a/src/callers/login.rs +++ b/src/callers/login.rs @@ -13,6 +13,13 @@ pub mod request { pub passphrase: String, } } + + pub mod refresh_token { + #[derive(Debug, serde::Deserialize, serde::Serialize)] + pub struct Request { + pub access_token: String, + } + } } pub mod response { @@ -31,6 +38,14 @@ pub mod response { pub data: Vec, } } + + pub mod refresh_token { + #[derive(Debug, Default, serde::Deserialize, serde::Serialize)] + pub struct Response { + pub message: String, + pub data: Vec, + } + } } pub mod endpoint { @@ -134,4 +149,18 @@ pub mod endpoint { } // TODO: Add endpoint to get a refresh token + pub async fn refresh_token(axum::Extension(pool): axum::Extension, axum::Json(payload): axum::Json) -> (axum::http::StatusCode, axum::Json) { + let mut response = response::refresh_token::Response::default(); + let key = icarus_envy::environment::get_secret_key().await; + + if token_stuff::verify_token(&key, &payload.access_token) { + // * Check token type + // - For right now, just worry about service tokens + // * Create a new token with a longer expiration + (axum::http::StatusCode::OK, axum::Json(response)) + } else { + response.message = String::from("Could not verify token"); + (axum::http::StatusCode::BAD_REQUEST, axum::Json(response)) + } + } } -- 2.43.0 From 1e8dcc25662bdd3f0ab885cf5cd9579f78854423 Mon Sep 17 00:00:00 2001 From: phoenix Date: Tue, 5 Aug 2025 18:49:51 -0400 Subject: [PATCH 04/16] tsk-51: Code formatting --- src/callers/login.rs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/callers/login.rs b/src/callers/login.rs index b1c79ab..1e84e97 100644 --- a/src/callers/login.rs +++ b/src/callers/login.rs @@ -149,7 +149,13 @@ pub mod endpoint { } // TODO: Add endpoint to get a refresh token - pub async fn refresh_token(axum::Extension(pool): axum::Extension, axum::Json(payload): axum::Json) -> (axum::http::StatusCode, axum::Json) { + pub async fn refresh_token( + axum::Extension(pool): axum::Extension, + axum::Json(payload): axum::Json, + ) -> ( + axum::http::StatusCode, + axum::Json, + ) { let mut response = response::refresh_token::Response::default(); let key = icarus_envy::environment::get_secret_key().await; -- 2.43.0 From cd2b624e4ca809cb3d9991395f334abd1618d3a5 Mon Sep 17 00:00:00 2001 From: phoenix Date: Wed, 6 Aug 2025 18:50:27 -0400 Subject: [PATCH 05/16] icarus_models version bump --- Cargo.lock | 4 ++-- Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ba72c60..8f4fa8c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -761,8 +761,8 @@ dependencies = [ [[package]] name = "icarus_models" -version = "0.5.4" -source = "git+ssh://git@git.kundeng.us/phoenix/icarus_models.git?tag=v0.5.4-devel-1e95822b5a-111#1e95822b5a349bd73cc501d921052f289105ec55" +version = "0.5.5" +source = "git+ssh://git@git.kundeng.us/phoenix/icarus_models.git?tag=v0.5.5-devel-bd793db08e-111#bd793db08e06b256ffecd9f4528e55e3026fede7" dependencies = [ "josekit", "rand 0.9.1", diff --git a/Cargo.toml b/Cargo.toml index caa4c42..3c739dd 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -18,7 +18,7 @@ argon2 = { version = "0.5.3", features = ["std"] } # Use the latest 0.5.x versio rand = { version = "0.9.1" } time = { version = "0.3.41", features = ["macros", "serde"] } josekit = { version = "0.10.3" } -icarus_models = { git = "ssh://git@git.kundeng.us/phoenix/icarus_models.git", tag = "v0.5.4-devel-1e95822b5a-111" } +icarus_models = { git = "ssh://git@git.kundeng.us/phoenix/icarus_models.git", tag = "v0.5.5-devel-bd793db08e-111" } icarus_envy = { git = "ssh://git@git.kundeng.us/phoenix/icarus_envy.git", tag = "v0.3.1-main-3cd42dab6b-006" } [dev-dependencies] -- 2.43.0 From 41796fd7682e5b599ec002ac918d10c267dbcece Mon Sep 17 00:00:00 2001 From: phoenix Date: Wed, 6 Aug 2025 18:51:14 -0400 Subject: [PATCH 06/16] tsk-51: Changes made related to icarus_models --- src/callers/login.rs | 4 ++-- src/token_stuff/mod.rs | 6 ++++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/callers/login.rs b/src/callers/login.rs index 1e84e97..11fc6a4 100644 --- a/src/callers/login.rs +++ b/src/callers/login.rs @@ -78,7 +78,7 @@ pub mod endpoint { if hashing::verify_password(&payload.password, user.password.clone()).unwrap() { // Create token let key = icarus_envy::environment::get_secret_key().await; - let (token_literal, duration) = token_stuff::create_token(&key).unwrap(); + let (token_literal, duration) = token_stuff::create_token(&key, &user.id).unwrap(); if token_stuff::verify_token(&key, &token_literal) { let current_time = time::OffsetDateTime::now_utc(); @@ -122,7 +122,7 @@ pub mod endpoint { match repo::service::valid_passphrase(&pool, &payload.passphrase).await { Ok((id, _passphrase, _date_created)) => { let key = icarus_envy::environment::get_secret_key().await; - let (token_literal, duration) = token_stuff::create_service_token(&key).unwrap(); + let (token_literal, duration) = token_stuff::create_service_token(&key, &id).unwrap(); if token_stuff::verify_token(&key, &token_literal) { let login_result = icarus_models::login_result::LoginResult { diff --git a/src/token_stuff/mod.rs b/src/token_stuff/mod.rs index 241216a..a9d2647 100644 --- a/src/token_stuff/mod.rs +++ b/src/token_stuff/mod.rs @@ -20,20 +20,22 @@ pub fn get_expiration(issued: &time::OffsetDateTime) -> Result Result<(String, i64), josekit::JoseError> { +pub fn create_token(provided_key: &String, id: &uuid::Uuid) -> Result<(String, i64), josekit::JoseError> { let resource = icarus_models::token::TokenResource { message: String::from(MESSAGE), issuer: String::from(ISSUER), audiences: vec![String::from(AUDIENCE)], + id: *id, }; icarus_models::token::create_token(provided_key, &resource, time::Duration::hours(4)) } -pub fn create_service_token(provided: &String) -> Result<(String, i64), josekit::JoseError> { +pub fn create_service_token(provided: &String, id: &uuid::Uuid) -> Result<(String, i64), josekit::JoseError> { let resource = icarus_models::token::TokenResource { message: String::from("Service random"), issuer: String::from(ISSUER), audiences: vec![String::from(AUDIENCE)], + id: *id, }; icarus_models::token::create_token(provided, &resource, time::Duration::hours(1)) } -- 2.43.0 From cfd61e203f5aea3145c9de041cbccc95d3d1042e Mon Sep 17 00:00:00 2001 From: phoenix Date: Wed, 6 Aug 2025 19:10:43 -0400 Subject: [PATCH 07/16] tsk-51: Added function to extract id from the token --- src/token_stuff/mod.rs | 45 +++++++++++++++++++++++++++++++++++++----- 1 file changed, 40 insertions(+), 5 deletions(-) diff --git a/src/token_stuff/mod.rs b/src/token_stuff/mod.rs index a9d2647..aa9454f 100644 --- a/src/token_stuff/mod.rs +++ b/src/token_stuff/mod.rs @@ -41,14 +41,49 @@ pub fn create_service_token(provided: &String, id: &uuid::Uuid) -> Result<(Strin } pub fn verify_token(key: &String, token: &String) -> bool { - let ver = Hs256.verifier_from_bytes(key.as_bytes()).unwrap(); - let (payload, _header) = jwt::decode_with_verifier(token, &ver).unwrap(); - match payload.subject() { - Some(_sub) => true, - None => false, + match get_payload(key, token) { + Ok((payload, _header)) => { + match payload.subject() { + Some(_sub) => true, + None => false, + } + } + Err(_err) => { + false + } } } +pub fn extract_id_from_token(key: &String, token: &String) -> Result { + match get_payload(key, token) { + Ok((payload, _header)) => { + match payload.claim("id") { + Some(id) => { + match uuid::Uuid::parse_str(id.as_str().unwrap()) { + Ok(extracted) => { + Ok(extracted) + } + Err(err) => { + Err(std::io::Error::other(err.to_string())) + } + } + } + None => { + Err(std::io::Error::other("No claim found")) + } + } + } + Err(err) => { + Err(std::io::Error::other(err.to_string())) + } + } +} + +fn get_payload(key: &String, token: &String) -> Result<(josekit::jwt::JwtPayload, josekit::jws::JwsHeader), josekit::JoseError> { + let ver = Hs256.verifier_from_bytes(key.as_bytes()).unwrap(); + jwt::decode_with_verifier(token, &ver) +} + #[cfg(test)] mod tests { use super::*; -- 2.43.0 From 34d3e66c7ba53fdfd52611f99c0f954cdfb7cc14 Mon Sep 17 00:00:00 2001 From: phoenix Date: Wed, 6 Aug 2025 19:14:15 -0400 Subject: [PATCH 08/16] tsk-51: Code formatting --- src/callers/login.rs | 6 +++-- src/token_stuff/mod.rs | 57 ++++++++++++++++++------------------------ 2 files changed, 29 insertions(+), 34 deletions(-) diff --git a/src/callers/login.rs b/src/callers/login.rs index 11fc6a4..6f94daf 100644 --- a/src/callers/login.rs +++ b/src/callers/login.rs @@ -78,7 +78,8 @@ pub mod endpoint { if hashing::verify_password(&payload.password, user.password.clone()).unwrap() { // Create token let key = icarus_envy::environment::get_secret_key().await; - let (token_literal, duration) = token_stuff::create_token(&key, &user.id).unwrap(); + let (token_literal, duration) = + token_stuff::create_token(&key, &user.id).unwrap(); if token_stuff::verify_token(&key, &token_literal) { let current_time = time::OffsetDateTime::now_utc(); @@ -122,7 +123,8 @@ pub mod endpoint { match repo::service::valid_passphrase(&pool, &payload.passphrase).await { Ok((id, _passphrase, _date_created)) => { let key = icarus_envy::environment::get_secret_key().await; - let (token_literal, duration) = token_stuff::create_service_token(&key, &id).unwrap(); + let (token_literal, duration) = + token_stuff::create_service_token(&key, &id).unwrap(); if token_stuff::verify_token(&key, &token_literal) { let login_result = icarus_models::login_result::LoginResult { diff --git a/src/token_stuff/mod.rs b/src/token_stuff/mod.rs index aa9454f..0a94595 100644 --- a/src/token_stuff/mod.rs +++ b/src/token_stuff/mod.rs @@ -20,7 +20,10 @@ pub fn get_expiration(issued: &time::OffsetDateTime) -> Result Result<(String, i64), josekit::JoseError> { +pub fn create_token( + provided_key: &String, + id: &uuid::Uuid, +) -> Result<(String, i64), josekit::JoseError> { let resource = icarus_models::token::TokenResource { message: String::from(MESSAGE), issuer: String::from(ISSUER), @@ -30,7 +33,10 @@ pub fn create_token(provided_key: &String, id: &uuid::Uuid) -> Result<(String, i icarus_models::token::create_token(provided_key, &resource, time::Duration::hours(4)) } -pub fn create_service_token(provided: &String, id: &uuid::Uuid) -> Result<(String, i64), josekit::JoseError> { +pub fn create_service_token( + provided: &String, + id: &uuid::Uuid, +) -> Result<(String, i64), josekit::JoseError> { let resource = icarus_models::token::TokenResource { message: String::from("Service random"), issuer: String::from(ISSUER), @@ -42,44 +48,31 @@ pub fn create_service_token(provided: &String, id: &uuid::Uuid) -> Result<(Strin pub fn verify_token(key: &String, token: &String) -> bool { match get_payload(key, token) { - Ok((payload, _header)) => { - match payload.subject() { - Some(_sub) => true, - None => false, - } - } - Err(_err) => { - false - } + Ok((payload, _header)) => match payload.subject() { + Some(_sub) => true, + None => false, + }, + Err(_err) => false, } } pub fn extract_id_from_token(key: &String, token: &String) -> Result { match get_payload(key, token) { - Ok((payload, _header)) => { - match payload.claim("id") { - Some(id) => { - match uuid::Uuid::parse_str(id.as_str().unwrap()) { - Ok(extracted) => { - Ok(extracted) - } - Err(err) => { - Err(std::io::Error::other(err.to_string())) - } - } - } - None => { - Err(std::io::Error::other("No claim found")) - } - } - } - Err(err) => { - Err(std::io::Error::other(err.to_string())) - } + Ok((payload, _header)) => match payload.claim("id") { + Some(id) => match uuid::Uuid::parse_str(id.as_str().unwrap()) { + Ok(extracted) => Ok(extracted), + Err(err) => Err(std::io::Error::other(err.to_string())), + }, + None => Err(std::io::Error::other("No claim found")), + }, + Err(err) => Err(std::io::Error::other(err.to_string())), } } -fn get_payload(key: &String, token: &String) -> Result<(josekit::jwt::JwtPayload, josekit::jws::JwsHeader), josekit::JoseError> { +fn get_payload( + key: &String, + token: &String, +) -> Result<(josekit::jwt::JwtPayload, josekit::jws::JwsHeader), josekit::JoseError> { let ver = Hs256.verifier_from_bytes(key.as_bytes()).unwrap(); jwt::decode_with_verifier(token, &ver) } -- 2.43.0 From 90342dd493afb72d5bd960c46ea151bfb874f0aa Mon Sep 17 00:00:00 2001 From: phoenix Date: Fri, 8 Aug 2025 18:19:27 -0400 Subject: [PATCH 09/16] tsk-51: Saving changes Adding more functions to access and validate the token type --- src/callers/login.rs | 10 +++++++++- src/repo/mod.rs | 3 +++ src/token_stuff/mod.rs | 8 ++++++++ 3 files changed, 20 insertions(+), 1 deletion(-) diff --git a/src/callers/login.rs b/src/callers/login.rs index 6f94daf..c171218 100644 --- a/src/callers/login.rs +++ b/src/callers/login.rs @@ -165,7 +165,15 @@ pub mod endpoint { // * Check token type // - For right now, just worry about service tokens // * Create a new token with a longer expiration - (axum::http::StatusCode::OK, axum::Json(response)) + let token_type = token_stuff::get_token_type(&key, &payload.access_token).unwrap(); + + if token_stuff::is_token_type_valid(&token_type) { + // let (token_literal, dur) = token_stuff::create_service_refresh_token(&key, ) + (axum::http::StatusCode::OK, axum::Json(response)) + } else { + response.message = String::from("Invalid token type"); + (axum::http::StatusCode::NOT_FOUND, axum::Json(response)) + } } else { response.message = String::from("Could not verify token"); (axum::http::StatusCode::BAD_REQUEST, axum::Json(response)) diff --git a/src/repo/mod.rs b/src/repo/mod.rs index db62bb4..e959406 100644 --- a/src/repo/mod.rs +++ b/src/repo/mod.rs @@ -223,4 +223,7 @@ pub mod service { Err(err) => Err(err), } } + + // TODO: Write a function to get a passphrase record with an id + // pub async fn get_passphrase(pool: &) } diff --git a/src/token_stuff/mod.rs b/src/token_stuff/mod.rs index 0a94595..f14848b 100644 --- a/src/token_stuff/mod.rs +++ b/src/token_stuff/mod.rs @@ -69,6 +69,14 @@ pub fn extract_id_from_token(key: &String, token: &String) -> Result Result { + Ok(String::new()) +} + +pub fn is_token_type_valid(token_type: &String) -> bool { + false +} + fn get_payload( key: &String, token: &String, -- 2.43.0 From 2e4c289998a225424feb31c6feaf892d33af21f0 Mon Sep 17 00:00:00 2001 From: phoenix Date: Sun, 10 Aug 2025 17:19:57 -0400 Subject: [PATCH 10/16] tsk-51: Functionality of endpoint is almost done --- src/callers/login.rs | 38 +++++++++++++++++++++++++++++++++- src/repo/mod.rs | 24 ++++++++++++++++++++- src/token_stuff/mod.rs | 47 +++++++++++++++++++++++++++++++++++++++--- 3 files changed, 104 insertions(+), 5 deletions(-) diff --git a/src/callers/login.rs b/src/callers/login.rs index c171218..e58e077 100644 --- a/src/callers/login.rs +++ b/src/callers/login.rs @@ -169,7 +169,43 @@ pub mod endpoint { if token_stuff::is_token_type_valid(&token_type) { // let (token_literal, dur) = token_stuff::create_service_refresh_token(&key, ) - (axum::http::StatusCode::OK, axum::Json(response)) + // Get passphrase record with id + // match repo::service::get_passphrase + match token_stuff::extract_id_from_token(&key, &payload.access_token) { + Ok(id) => { + match repo::service::get_passphrase(&pool, &id).await { + Ok((returned_id, _, _)) => { + match token_stuff::create_service_refresh_token(&key, &returned_id) + { + Ok((access_token, exp_dur)) => { + let login_result = + icarus_models::login_result::LoginResult { + id: returned_id, + token: access_token, + expiration: exp_dur, + token_type: String::from( + icarus_models::token::TOKEN_TYPE, + ), + username: String::from("service"), + }; + } + Err(err) => {} + } + /* + */ + (axum::http::StatusCode::OK, axum::Json(response)) + } + Err(err) => { + response.message = err.to_string(); + (axum::http::StatusCode::OK, axum::Json(response)) + } + } + } + Err(err) => { + response.message = err.to_string(); + (axum::http::StatusCode::OK, axum::Json(response)) + } + } } else { response.message = String::from("Invalid token type"); (axum::http::StatusCode::NOT_FOUND, axum::Json(response)) diff --git a/src/repo/mod.rs b/src/repo/mod.rs index e959406..189ebbe 100644 --- a/src/repo/mod.rs +++ b/src/repo/mod.rs @@ -225,5 +225,27 @@ pub mod service { } // TODO: Write a function to get a passphrase record with an id - // pub async fn get_passphrase(pool: &) + pub async fn get_passphrase( + pool: &sqlx::PgPool, + id: &uuid::Uuid, + ) -> Result<(uuid::Uuid, String, time::OffsetDateTime), sqlx::Error> { + let result = sqlx::query( + r#" + SELECT * FROM "passphrase" WHERE id = $1; + "#, + ) + .bind(id) + .fetch_one(pool) + .await; + + match result { + Ok(row) => { + let returned_id: uuid::Uuid = row.try_get("id")?; + let passphrase: String = row.try_get("passphrase")?; + let date_created: time::OffsetDateTime = row.try_get("date_created")?; + Ok((returned_id, passphrase, date_created)) + } + Err(err) => Err(err), + } + } } diff --git a/src/token_stuff/mod.rs b/src/token_stuff/mod.rs index f14848b..38f04d7 100644 --- a/src/token_stuff/mod.rs +++ b/src/token_stuff/mod.rs @@ -38,7 +38,7 @@ pub fn create_service_token( id: &uuid::Uuid, ) -> Result<(String, i64), josekit::JoseError> { let resource = icarus_models::token::TokenResource { - message: String::from("Service random"), + message: String::from(SERVICE_SUBJECT), issuer: String::from(ISSUER), audiences: vec![String::from(AUDIENCE)], id: *id, @@ -46,6 +46,19 @@ pub fn create_service_token( icarus_models::token::create_token(provided, &resource, time::Duration::hours(1)) } +pub fn create_service_refresh_token( + key: &String, + id: &uuid::Uuid, +) -> Result<(String, i64), josekit::JoseError> { + let resource = icarus_models::token::TokenResource { + message: String::from(SERVICE_SUBJECT), + issuer: String::from(ISSUER), + audiences: vec![String::from(AUDIENCE)], + id: *id, + }; + icarus_models::token::create_token(key, &resource, time::Duration::hours(4)) +} + pub fn verify_token(key: &String, token: &String) -> bool { match get_payload(key, token) { Ok((payload, _header)) => match payload.subject() { @@ -69,12 +82,40 @@ pub fn extract_id_from_token(key: &String, token: &String) -> Result Result { - Ok(String::new()) + match get_payload(key, token) { + Ok((payload, _header)) => match payload.subject() { + Some(subject) => { + if subject == APP_SUBJECT { + Ok(String::from(APP_TOKEN_TYPE)) + } else if subject == SERVICE_SUBJECT { + Ok(String::from(SERVICE_TOKEN_TYPE)) + } else { + Err(std::io::Error::other(String::from("Invalid subject"))) + } + } + None => Err(std::io::Error::other(String::from("Invalid payload"))), // } + /* + match payload.claim("id") { + Some(id) => match uuid::Uuid::parse_str(id.as_str().unwrap()) { + Ok(extracted) => Ok(extracted), + Err(err) => Err(std::io::Error::other(err.to_string())), + }, + None => Err(std::io::Error::other("No claim found")), + */ + }, + Err(err) => Err(std::io::Error::other(err.to_string())), + } } pub fn is_token_type_valid(token_type: &String) -> bool { - false + token_type == SERVICE_TOKEN_TYPE + // false } fn get_payload( -- 2.43.0 From 17fd2de892f89452c71e2263296d1b642f0b185e Mon Sep 17 00:00:00 2001 From: phoenix Date: Mon, 11 Aug 2025 17:22:30 -0400 Subject: [PATCH 11/16] tsk-51: Endpoint is now available --- src/callers/login.rs | 67 ++++++++++++++++++++++++++------------------ src/main.rs | 4 +++ 2 files changed, 43 insertions(+), 28 deletions(-) diff --git a/src/callers/login.rs b/src/callers/login.rs index e58e077..efa1144 100644 --- a/src/callers/login.rs +++ b/src/callers/login.rs @@ -58,6 +58,10 @@ pub mod endpoint { use super::request; use super::response; + // TODO: At some point, get the username from the DB + // Name of service username when returning a login result + pub const SERVICE_USERNAME: &str = "service"; + async fn not_found(message: &str) -> (StatusCode, Json) { ( StatusCode::NOT_FOUND, @@ -129,7 +133,7 @@ pub mod endpoint { if token_stuff::verify_token(&key, &token_literal) { let login_result = icarus_models::login_result::LoginResult { id, - username: String::from("service"), + username: String::from(SERVICE_USERNAME), token: token_literal, token_type: String::from(icarus_models::token::TOKEN_TYPE), expiration: duration, @@ -172,38 +176,45 @@ pub mod endpoint { // Get passphrase record with id // match repo::service::get_passphrase match token_stuff::extract_id_from_token(&key, &payload.access_token) { - Ok(id) => { - match repo::service::get_passphrase(&pool, &id).await { - Ok((returned_id, _, _)) => { - match token_stuff::create_service_refresh_token(&key, &returned_id) - { - Ok((access_token, exp_dur)) => { - let login_result = - icarus_models::login_result::LoginResult { - id: returned_id, - token: access_token, - expiration: exp_dur, - token_type: String::from( - icarus_models::token::TOKEN_TYPE, - ), - username: String::from("service"), - }; - } - Err(err) => {} + Ok(id) => match repo::service::get_passphrase(&pool, &id).await { + Ok((returned_id, _, _)) => { + match token_stuff::create_service_refresh_token(&key, &returned_id) { + Ok((access_token, exp_dur)) => { + let login_result = icarus_models::login_result::LoginResult { + id: returned_id, + token: access_token, + expiration: exp_dur, + token_type: String::from(icarus_models::token::TOKEN_TYPE), + username: String::from(SERVICE_USERNAME), + }; + response.message = String::from("Successful"); + response.data.push(login_result); + + (axum::http::StatusCode::OK, axum::Json(response)) + } + Err(err) => { + response.message = err.to_string(); + ( + axum::http::StatusCode::INTERNAL_SERVER_ERROR, + axum::Json(response), + ) } - /* - */ - (axum::http::StatusCode::OK, axum::Json(response)) - } - Err(err) => { - response.message = err.to_string(); - (axum::http::StatusCode::OK, axum::Json(response)) } } - } + Err(err) => { + response.message = err.to_string(); + ( + axum::http::StatusCode::INTERNAL_SERVER_ERROR, + axum::Json(response), + ) + } + }, Err(err) => { response.message = err.to_string(); - (axum::http::StatusCode::OK, axum::Json(response)) + ( + axum::http::StatusCode::INTERNAL_SERVER_ERROR, + axum::Json(response), + ) } } } else { diff --git a/src/main.rs b/src/main.rs index 5d8a4ab..06fa5c9 100644 --- a/src/main.rs +++ b/src/main.rs @@ -45,6 +45,10 @@ mod init { callers::endpoints::SERVICE_LOGIN, post(callers::login::endpoint::service_login), ) + .route( + callers::endpoints::REFRESH_TOKEN, + post(callers::login::endpoint::refresh_token), + ) } pub async fn app() -> Router { -- 2.43.0 From dc3b540599de3ac38815d356febc242920ada140 Mon Sep 17 00:00:00 2001 From: phoenix Date: Mon, 11 Aug 2025 17:48:10 -0400 Subject: [PATCH 12/16] tsk-51: Test fix --- src/token_stuff/mod.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/token_stuff/mod.rs b/src/token_stuff/mod.rs index 38f04d7..a0a1cba 100644 --- a/src/token_stuff/mod.rs +++ b/src/token_stuff/mod.rs @@ -134,7 +134,8 @@ mod tests { fn test_tokenize() { let rt = tokio::runtime::Runtime::new().unwrap(); let special_key = rt.block_on(icarus_envy::environment::get_secret_key()); - match create_token(&special_key) { + let id = uuid::Uuid::new_v4(); + match create_token(&special_key, &id) { Ok((token, _duration)) => { let result = verify_token(&special_key, &token); assert!(result, "Token not verified"); -- 2.43.0 From 47027e95be031f4b5377d5095f6b2b6712c11ccb Mon Sep 17 00:00:00 2001 From: phoenix Date: Mon, 11 Aug 2025 18:05:40 -0400 Subject: [PATCH 13/16] tsk-51: Updated migrations to manually insert id --- migrations/20250802185652_passphrase_data.sql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/migrations/20250802185652_passphrase_data.sql b/migrations/20250802185652_passphrase_data.sql index e18d2a1..c1edf34 100644 --- a/migrations/20250802185652_passphrase_data.sql +++ b/migrations/20250802185652_passphrase_data.sql @@ -1,2 +1,2 @@ -- Add migration script here -INSERT INTO "passphrase" (passphrase) VALUES('iUOo1fxshf3y1tUGn1yU8l9raPApHCdinW0VdCHdRFEjqhR3Bf02aZzsKbLtaDFH'); +INSERT INTO "passphrase" (id, passphrase) VALUES('22f9c775-cce9-457a-a147-9dafbb801f61', 'iUOo1fxshf3y1tUGn1yU8l9raPApHCdinW0VdCHdRFEjqhR3Bf02aZzsKbLtaDFH'); -- 2.43.0 From 3985e78c248c5b5fc5df87b4925a94d38598cc56 Mon Sep 17 00:00:00 2001 From: phoenix Date: Mon, 11 Aug 2025 18:06:05 -0400 Subject: [PATCH 14/16] tsk-51: Added test --- src/main.rs | 99 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 99 insertions(+) diff --git a/src/main.rs b/src/main.rs index 06fa5c9..1f5a4ba 100644 --- a/src/main.rs +++ b/src/main.rs @@ -401,4 +401,103 @@ mod tests { let _ = db_mgr::drop_database(&tm_pool, &db_name).await; } + + #[tokio::test] + async fn test_refresh_token() { + let tm_pool = db_mgr::get_pool().await.unwrap(); + + let db_name = db_mgr::generate_db_name().await; + + match db_mgr::create_database(&tm_pool, &db_name).await { + Ok(_) => { + println!("Success"); + } + Err(e) => { + assert!(false, "Error: {:?}", e.to_string()); + } + } + + let pool = db_mgr::connect_to_db(&db_name).await.unwrap(); + + icarus_auth::db::migrations(&pool).await; + + let app = init::routes().await.layer(axum::Extension(pool)); + let id = uuid::Uuid::parse_str("22f9c775-cce9-457a-a147-9dafbb801f61").unwrap(); + let key = icarus_envy::environment::get_secret_key().await; + + match icarus_auth::token_stuff::create_service_token(&key, &id) { + Ok((token, _expire)) => { + let payload = serde_json::json!({ + "access_token": token + }); + + match app + .oneshot( + Request::builder() + .method(axum::http::Method::POST) + .uri(callers::endpoints::REFRESH_TOKEN) + .header(axum::http::header::CONTENT_TYPE, "application/json") + .body(Body::from(payload.to_string())) + .unwrap(), + ) + .await + { + Ok(response) => { + let body = axum::body::to_bytes(response.into_body(), usize::MAX) + .await + .unwrap(); + let parsed_body: callers::login::response::service_login::Response = + serde_json::from_slice(&body).unwrap(); + let login_result = &parsed_body.data[0]; + + assert_eq!( + id, login_result.id, + "The Id from the response does not match {id:?} {:?}", + login_result.id + ); + } + Err(err) => { + assert!(false, "Error: {err:?}"); + } + } + } + Err(err) => { + assert!(false, "Error: {err:?}"); + } + } + /* + let passphrase = + String::from("iUOo1fxshf3y1tUGn1yU8l9raPApHCdinW0VdCHdRFEjqhR3Bf02aZzsKbLtaDFH"); + let payload = serde_json::json!({ + "passphrase": passphrase + }); + + match app + .oneshot( + Request::builder() + .method(axum::http::Method::POST) + .uri(callers::endpoints::SERVICE_LOGIN) + .header(axum::http::header::CONTENT_TYPE, "application/json") + .body(Body::from(payload.to_string())) + .unwrap(), + ) + .await + { + Ok(response) => { + assert_eq!(StatusCode::OK, response.status(), "Status is not right"); + let body = axum::body::to_bytes(response.into_body(), usize::MAX) + .await + .unwrap(); + let parsed_body: callers::login::response::service_login::Response = + serde_json::from_slice(&body).unwrap(); + let _login_result = &parsed_body.data[0]; + } + Err(err) => { + assert!(false, "Error: {err:?}"); + } + } + */ + + let _ = db_mgr::drop_database(&tm_pool, &db_name).await; + } } -- 2.43.0 From 3517bbf015e093cd730b614af87f8e124cd7bce1 Mon Sep 17 00:00:00 2001 From: phoenix Date: Mon, 11 Aug 2025 18:11:42 -0400 Subject: [PATCH 15/16] tsk-51: Code cleanup --- src/callers/login.rs | 6 ------ src/main.rs | 32 -------------------------------- src/repo/mod.rs | 1 - src/token_stuff/mod.rs | 11 +---------- 4 files changed, 1 insertion(+), 49 deletions(-) diff --git a/src/callers/login.rs b/src/callers/login.rs index efa1144..fb065e5 100644 --- a/src/callers/login.rs +++ b/src/callers/login.rs @@ -154,7 +154,6 @@ pub mod endpoint { } } - // TODO: Add endpoint to get a refresh token pub async fn refresh_token( axum::Extension(pool): axum::Extension, axum::Json(payload): axum::Json, @@ -166,15 +165,10 @@ pub mod endpoint { let key = icarus_envy::environment::get_secret_key().await; if token_stuff::verify_token(&key, &payload.access_token) { - // * Check token type - // - For right now, just worry about service tokens - // * Create a new token with a longer expiration let token_type = token_stuff::get_token_type(&key, &payload.access_token).unwrap(); if token_stuff::is_token_type_valid(&token_type) { - // let (token_literal, dur) = token_stuff::create_service_refresh_token(&key, ) // Get passphrase record with id - // match repo::service::get_passphrase match token_stuff::extract_id_from_token(&key, &payload.access_token) { Ok(id) => match repo::service::get_passphrase(&pool, &id).await { Ok((returned_id, _, _)) => { diff --git a/src/main.rs b/src/main.rs index 1f5a4ba..e052521 100644 --- a/src/main.rs +++ b/src/main.rs @@ -465,38 +465,6 @@ mod tests { assert!(false, "Error: {err:?}"); } } - /* - let passphrase = - String::from("iUOo1fxshf3y1tUGn1yU8l9raPApHCdinW0VdCHdRFEjqhR3Bf02aZzsKbLtaDFH"); - let payload = serde_json::json!({ - "passphrase": passphrase - }); - - match app - .oneshot( - Request::builder() - .method(axum::http::Method::POST) - .uri(callers::endpoints::SERVICE_LOGIN) - .header(axum::http::header::CONTENT_TYPE, "application/json") - .body(Body::from(payload.to_string())) - .unwrap(), - ) - .await - { - Ok(response) => { - assert_eq!(StatusCode::OK, response.status(), "Status is not right"); - let body = axum::body::to_bytes(response.into_body(), usize::MAX) - .await - .unwrap(); - let parsed_body: callers::login::response::service_login::Response = - serde_json::from_slice(&body).unwrap(); - let _login_result = &parsed_body.data[0]; - } - Err(err) => { - assert!(false, "Error: {err:?}"); - } - } - */ let _ = db_mgr::drop_database(&tm_pool, &db_name).await; } diff --git a/src/repo/mod.rs b/src/repo/mod.rs index 189ebbe..037ee0f 100644 --- a/src/repo/mod.rs +++ b/src/repo/mod.rs @@ -224,7 +224,6 @@ pub mod service { } } - // TODO: Write a function to get a passphrase record with an id pub async fn get_passphrase( pool: &sqlx::PgPool, id: &uuid::Uuid, diff --git a/src/token_stuff/mod.rs b/src/token_stuff/mod.rs index a0a1cba..64e4429 100644 --- a/src/token_stuff/mod.rs +++ b/src/token_stuff/mod.rs @@ -99,15 +99,7 @@ pub fn get_token_type(key: &String, token: &String) -> Result Err(std::io::Error::other(String::from("Invalid payload"))), // } - /* - match payload.claim("id") { - Some(id) => match uuid::Uuid::parse_str(id.as_str().unwrap()) { - Ok(extracted) => Ok(extracted), - Err(err) => Err(std::io::Error::other(err.to_string())), - }, - None => Err(std::io::Error::other("No claim found")), - */ + None => Err(std::io::Error::other(String::from("Invalid payload"))), }, Err(err) => Err(std::io::Error::other(err.to_string())), } @@ -115,7 +107,6 @@ pub fn get_token_type(key: &String, token: &String) -> Result bool { token_type == SERVICE_TOKEN_TYPE - // false } fn get_payload( -- 2.43.0 From c1f2a30069d3ff4068c4b321d49d3ec007c221bb Mon Sep 17 00:00:00 2001 From: phoenix Date: Mon, 11 Aug 2025 18:12:11 -0400 Subject: [PATCH 16/16] tsk-51: Version bump --- Cargo.lock | 2 +- Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 8f4fa8c..c5b54f2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -728,7 +728,7 @@ dependencies = [ [[package]] name = "icarus_auth" -version = "0.4.2" +version = "0.4.3" dependencies = [ "argon2", "axum", diff --git a/Cargo.toml b/Cargo.toml index 3c739dd..8d25e4a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "icarus_auth" -version = "0.4.2" +version = "0.4.3" edition = "2024" rust-version = "1.88" -- 2.43.0