feat: implement argon2id and expect passwords to be pre-hashed

This commit is contained in:
Radical 2025-04-30 21:36:22 +02:00
parent 3461218025
commit 87edb9dd12
4 changed files with 86 additions and 49 deletions

View file

@ -1,4 +1,5 @@
use actix_web::{error, post, web, Error, HttpResponse};
use argon2::{Argon2, PasswordHash, PasswordVerifier};
use regex::Regex;
use serde::{Deserialize, Serialize};
use futures::StreamExt;
@ -40,15 +41,22 @@ pub async fn res(mut payload: web::Payload, data: web::Data<Data>) -> Result<Htt
// FIXME: This regex doesnt seem to be working
let username_regex = Regex::new(r"[a-zA-Z0-9.-_]").unwrap();
// Password is expected to be hashed using SHA3-384
let password_regex = Regex::new(r"/[0-9a-f]{96}/i").unwrap();
if !password_regex.is_match(&login_information.password) {
return Ok(HttpResponse::Forbidden().json(r#"{ "password_hashed": false }"#));
}
if email_regex.is_match(&login_information.username) {
if let Ok(password) = sqlx::query_scalar("SELECT password FROM users WHERE email = $1").bind(login_information.username).fetch_one(&data.pool).await {
return Ok(login(login_information.password, password))
return Ok(login(data.argon2.clone(), login_information.password, password))
}
return Ok(HttpResponse::Unauthorized().finish())
} else if username_regex.is_match(&login_information.username) {
if let Ok(password) = sqlx::query_scalar("SELECT password FROM users WHERE username = $1").bind(login_information.username).fetch_one(&data.pool).await {
return Ok(login(login_information.password, password))
return Ok(login(data.argon2.clone(), login_information.password, password))
}
return Ok(HttpResponse::Unauthorized().finish())
@ -57,14 +65,18 @@ pub async fn res(mut payload: web::Payload, data: web::Data<Data>) -> Result<Htt
Ok(HttpResponse::Unauthorized().finish())
}
fn login(request_password: String, database_password: String) -> HttpResponse {
if request_password == database_password {
return HttpResponse::Ok().json(Response {
access_token: "bogus".to_string(),
expires_in: 0,
refresh_token: "bogus".to_string(),
})
fn login(argon2: Argon2, request_password: String, database_password: String) -> HttpResponse {
if let Ok(parsed_hash) = PasswordHash::new(&database_password) {
if argon2.verify_password(request_password.as_bytes(), &parsed_hash).is_ok() {
return HttpResponse::Ok().json(Response {
access_token: "bogus".to_string(),
expires_in: 0,
refresh_token: "bogus".to_string(),
})
}
return HttpResponse::Unauthorized().finish()
}
HttpResponse::Unauthorized().finish()
HttpResponse::InternalServerError().finish()
}