diff --git a/src/channels/web/handlers/invitations.rs b/src/channels/web/handlers/invitations.rs index bb92d2f3..5e0e904e 100644 --- a/src/channels/web/handlers/invitations.rs +++ b/src/channels/web/handlers/invitations.rs @@ -5,7 +5,6 @@ use std::sync::Arc; use axum::{Json, extract::State, http::StatusCode}; use rand::RngCore; use rand::rngs::OsRng; -use sha2::{Digest, Sha256}; use uuid::Uuid; use crate::channels::web::auth::{AdminUser, AuthenticatedUser}; @@ -37,11 +36,7 @@ pub async fn invitations_create_handler( let mut token_bytes = [0u8; 32]; OsRng.fill_bytes(&mut token_bytes); let plaintext_token = hex::encode(token_bytes); - - // SHA-256 hash for storage — plaintext is never persisted. - let mut hasher = Sha256::new(); - hasher.update(token_bytes); - let hash: [u8; 32] = hasher.finalize().into(); + let hash = crate::channels::web::auth::hash_token(&plaintext_token); let invitation_id = Uuid::new_v4(); let invitation = InvitationRecord { @@ -129,15 +124,9 @@ pub async fn invitations_accept_handler( .to_string(); // Hash the provided token to look up the invitation. - let token_bytes = hex::decode(invite_token).map_err(|_| { - ( - StatusCode::BAD_REQUEST, - "Invalid invite token format".to_string(), - ) - })?; - let mut hasher = Sha256::new(); - hasher.update(&token_bytes); - let hash: [u8; 32] = hasher.finalize().into(); + // Hash the plaintext token string (not decoded bytes) — must match + // how it was hashed during invitation creation via hash_token(). + let hash = crate::channels::web::auth::hash_token(invite_token); // Look up the invitation by hash. let invitation = store @@ -187,10 +176,7 @@ pub async fn invitations_accept_handler( let mut api_token_bytes = [0u8; 32]; OsRng.fill_bytes(&mut api_token_bytes); let plaintext_api_token = hex::encode(api_token_bytes); - - let mut api_hasher = Sha256::new(); - api_hasher.update(api_token_bytes); - let api_hash: [u8; 32] = api_hasher.finalize().into(); + let api_hash = crate::channels::web::auth::hash_token(&plaintext_api_token); let api_prefix = &plaintext_api_token[..8]; diff --git a/src/channels/web/handlers/tokens.rs b/src/channels/web/handlers/tokens.rs index ad41c291..50142671 100644 --- a/src/channels/web/handlers/tokens.rs +++ b/src/channels/web/handlers/tokens.rs @@ -9,7 +9,6 @@ use axum::{ }; use rand::RngCore; use rand::rngs::OsRng; -use sha2::{Digest, Sha256}; use uuid::Uuid; use crate::channels::web::auth::AuthenticatedUser; @@ -41,14 +40,12 @@ pub async fn tokens_create_handler( expires_in_days.map(|days| chrono::Utc::now() + chrono::Duration::days(days as i64)); // Generate 32 random bytes for the token. + // Hash the hex-encoded plaintext (what the user sends as Bearer token), + // NOT the raw bytes — must match hash_token() in auth.rs. let mut token_bytes = [0u8; 32]; OsRng.fill_bytes(&mut token_bytes); let plaintext_token = hex::encode(token_bytes); - - // SHA-256 hash for storage — plaintext is never persisted. - let mut hasher = Sha256::new(); - hasher.update(token_bytes); - let hash: [u8; 32] = hasher.finalize().into(); + let hash = crate::channels::web::auth::hash_token(&plaintext_token); // First 8 chars of the hex token as a prefix for identification. let token_prefix = &plaintext_token[..8]; diff --git a/src/channels/web/handlers/users.rs b/src/channels/web/handlers/users.rs index 55feed3b..185d0bc1 100644 --- a/src/channels/web/handlers/users.rs +++ b/src/channels/web/handlers/users.rs @@ -9,7 +9,6 @@ use axum::{ }; use rand::RngCore; use rand::rngs::OsRng; -use sha2::{Digest, Sha256}; use uuid::Uuid; use crate::channels::web::auth::{AdminUser, AuthenticatedUser}; @@ -71,12 +70,12 @@ pub async fn users_create_handler( .map_err(|e| (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()))?; // Generate a first API token so the new user can authenticate immediately. + // Hash the hex-encoded plaintext (what the user sends as Bearer token), + // NOT the raw bytes — must match hash_token() in auth.rs. let mut token_bytes = [0u8; 32]; OsRng.fill_bytes(&mut token_bytes); let plaintext_token = hex::encode(token_bytes); - let mut hasher = Sha256::new(); - hasher.update(token_bytes); - let token_hash: [u8; 32] = hasher.finalize().into(); + let token_hash = crate::channels::web::auth::hash_token(&plaintext_token); let token_prefix = &plaintext_token[..8]; let _token_record = store