- error.rs: AuthError with proper HTTP status mapping - service/password.rs: Argon2 hash/verify with tests - service/token_service.rs: JWT sign/validate, token DB storage with SHA-256 hash - service/auth_service.rs: login/refresh/logout flows with event publishing - service/user_service.rs: user CRUD with soft delete and tenant isolation - Added sha2 dependency to workspace for token hashing
57 lines
1.7 KiB
Rust
57 lines
1.7 KiB
Rust
use argon2::{
|
|
password_hash::{rand_core::OsRng, PasswordHash, PasswordHasher, PasswordVerifier, SaltString},
|
|
Argon2,
|
|
};
|
|
|
|
use crate::error::{AuthError, AuthResult};
|
|
|
|
/// Hash a plaintext password using Argon2 with a random salt.
|
|
///
|
|
/// Returns a PHC-format string suitable for database storage.
|
|
pub fn hash_password(plain: &str) -> AuthResult<String> {
|
|
let salt = SaltString::generate(&mut OsRng);
|
|
let argon2 = Argon2::default();
|
|
let hash = argon2
|
|
.hash_password(plain.as_bytes(), &salt)
|
|
.map_err(|e| AuthError::HashError(e.to_string()))?;
|
|
Ok(hash.to_string())
|
|
}
|
|
|
|
/// Verify a plaintext password against a stored PHC-format hash.
|
|
///
|
|
/// Returns `Ok(true)` if the password matches, `Ok(false)` if not.
|
|
pub fn verify_password(plain: &str, hash: &str) -> AuthResult<bool> {
|
|
let parsed = PasswordHash::new(hash).map_err(|e| AuthError::HashError(e.to_string()))?;
|
|
Ok(Argon2::default()
|
|
.verify_password(plain.as_bytes(), &parsed)
|
|
.is_ok())
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::*;
|
|
|
|
#[test]
|
|
fn test_hash_and_verify() {
|
|
let hash = hash_password("test123").unwrap();
|
|
assert!(
|
|
verify_password("test123", &hash).unwrap(),
|
|
"Correct password should verify"
|
|
);
|
|
assert!(
|
|
!verify_password("wrong", &hash).unwrap(),
|
|
"Wrong password should not verify"
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn test_hash_is_unique() {
|
|
let hash1 = hash_password("same_password").unwrap();
|
|
let hash2 = hash_password("same_password").unwrap();
|
|
assert_ne!(
|
|
hash1, hash2,
|
|
"Two hashes of the same password should differ (different salts)"
|
|
);
|
|
}
|
|
}
|