Skip to content

Commit e89ea92

Browse files
committed
check passwords in a real non-blocking way
1 parent 1a6f409 commit e89ea92

File tree

1 file changed

+26
-24
lines changed

1 file changed

+26
-24
lines changed

src/render.rs

Lines changed: 26 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ impl<W: std::io::Write> HeaderContext<W> {
5151
Some("redirect") => self.redirect(&data).map(PageContext::Close),
5252
Some("json") => self.json(&data).map(PageContext::Close),
5353
Some("cookie") => self.add_cookie(&data).map(PageContext::Header),
54-
Some("authentication") => self.authentication(&data).await,
54+
Some("authentication") => self.authentication(data).await,
5555
_ => self.start_body(data).await,
5656
}
5757
}
@@ -167,27 +167,19 @@ impl<W: std::io::Write> HeaderContext<W> {
167167
Ok(self.response.body(json_response))
168168
}
169169

170-
async fn authentication(mut self, data: &JsonValue) -> anyhow::Result<PageContext<W>> {
171-
let password_hash = get_object_str(data, "password_hash");
172-
let password = get_object_str(data, "password");
170+
async fn authentication(mut self, mut data: JsonValue) -> anyhow::Result<PageContext<W>> {
171+
let password_hash = take_object_str(&mut data, "password_hash");
172+
let password = take_object_str(&mut data, "password");
173173
if let (Some(password), Some(password_hash)) = (password, password_hash) {
174-
log::debug!(
175-
"Authenticating user with password_hash = {:?}",
176-
password_hash
177-
);
178-
let verif_result =
179-
tokio::task::block_in_place(move || verify_password_sync(password_hash, password))?;
180-
match verif_result {
174+
log::debug!("Authentication with password_hash = {:?}", password_hash);
175+
match verify_password_async(password_hash, password).await? {
181176
Ok(()) => return Ok(PageContext::Header(self)),
182-
Err(e) => log::info!("User authentication failed: {}", e),
177+
Err(e) => log::info!("Password didn't match: {}", e),
183178
}
184179
}
185-
log::debug!(
186-
"Authentication failed with password_hash = {:?}",
187-
password_hash
188-
);
180+
log::debug!("Authentication failed");
189181
// The authentication failed
190-
if let Some(link) = get_object_str(data, "link") {
182+
if let Some(link) = get_object_str(&data, "link") {
191183
self.response.status(StatusCode::FOUND);
192184
self.response.insert_header((header::LOCATION, link));
193185
self.has_status = true;
@@ -218,14 +210,17 @@ impl<W: std::io::Write> HeaderContext<W> {
218210
}
219211
}
220212

221-
fn verify_password_sync(
222-
password_hash: &str,
223-
password: &str,
213+
async fn verify_password_async(
214+
password_hash: String,
215+
password: String,
224216
) -> Result<Result<(), password_hash::Error>, anyhow::Error> {
225-
let hash = password_hash::PasswordHash::new(password_hash)
226-
.map_err(|e| anyhow::anyhow!("invalid value for the password_hash property: {}", e))?;
227-
let phfs = &[&argon2::Argon2::default() as &dyn password_hash::PasswordVerifier];
228-
Ok(hash.verify_password(phfs, password))
217+
tokio::task::spawn_blocking(move || {
218+
let hash = password_hash::PasswordHash::new(&password_hash)
219+
.map_err(|e| anyhow::anyhow!("invalid value for the password_hash property: {}", e))?;
220+
let phfs = &[&argon2::Argon2::default() as &dyn password_hash::PasswordVerifier];
221+
Ok(hash.verify_password(phfs, password))
222+
})
223+
.await?
229224
}
230225

231226
fn get_backtrace(error: &anyhow::Error) -> Vec<String> {
@@ -244,6 +239,13 @@ fn get_object_str<'a>(json: &'a JsonValue, key: &str) -> Option<&'a str> {
244239
.and_then(JsonValue::as_str)
245240
}
246241

242+
fn take_object_str(json: &mut JsonValue, key: &str) -> Option<String> {
243+
match json.get_mut(key)?.take() {
244+
JsonValue::String(s) => Some(s),
245+
_ => None,
246+
}
247+
}
248+
247249
#[allow(clippy::module_name_repetitions)]
248250
pub struct RenderContext<W: std::io::Write> {
249251
app_state: Arc<AppState>,

0 commit comments

Comments
 (0)