mirror of
https://github.com/dani-garcia/vaultwarden.git
synced 2026-03-22 01:39:21 -07:00
Merge commit from fork
* Fix WebAuthn backup flag update before signature verification * fix format rust file * Add test for migration update * Remove webauthn test
This commit is contained in:
@@ -438,7 +438,7 @@ pub async fn validate_webauthn_login(user_id: &UserId, response: &str, conn: &Db
|
|||||||
// We need to check for and update the backup_eligible flag when needed.
|
// We need to check for and update the backup_eligible flag when needed.
|
||||||
// Vaultwarden did not have knowledge of this flag prior to migrating to webauthn-rs v0.5.x
|
// Vaultwarden did not have knowledge of this flag prior to migrating to webauthn-rs v0.5.x
|
||||||
// Because of this we check the flag at runtime and update the registrations and state when needed
|
// Because of this we check the flag at runtime and update the registrations and state when needed
|
||||||
check_and_update_backup_eligible(user_id, &rsp, &mut registrations, &mut state, conn).await?;
|
let backup_flags_updated = check_and_update_backup_eligible(&rsp, &mut registrations, &mut state)?;
|
||||||
|
|
||||||
let authentication_result = WEBAUTHN.finish_passkey_authentication(&rsp, &state)?;
|
let authentication_result = WEBAUTHN.finish_passkey_authentication(&rsp, &state)?;
|
||||||
|
|
||||||
@@ -446,7 +446,8 @@ pub async fn validate_webauthn_login(user_id: &UserId, response: &str, conn: &Db
|
|||||||
if ct_eq(reg.credential.cred_id(), authentication_result.cred_id()) {
|
if ct_eq(reg.credential.cred_id(), authentication_result.cred_id()) {
|
||||||
// If the cred id matches and the credential is updated, Some(true) is returned
|
// If the cred id matches and the credential is updated, Some(true) is returned
|
||||||
// In those cases, update the record, else leave it alone
|
// In those cases, update the record, else leave it alone
|
||||||
if reg.credential.update_credential(&authentication_result) == Some(true) {
|
let credential_updated = reg.credential.update_credential(&authentication_result) == Some(true);
|
||||||
|
if credential_updated || backup_flags_updated {
|
||||||
TwoFactor::new(user_id.clone(), TwoFactorType::Webauthn, serde_json::to_string(®istrations)?)
|
TwoFactor::new(user_id.clone(), TwoFactorType::Webauthn, serde_json::to_string(®istrations)?)
|
||||||
.save(conn)
|
.save(conn)
|
||||||
.await?;
|
.await?;
|
||||||
@@ -463,13 +464,11 @@ pub async fn validate_webauthn_login(user_id: &UserId, response: &str, conn: &Db
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn check_and_update_backup_eligible(
|
fn check_and_update_backup_eligible(
|
||||||
user_id: &UserId,
|
|
||||||
rsp: &PublicKeyCredential,
|
rsp: &PublicKeyCredential,
|
||||||
registrations: &mut Vec<WebauthnRegistration>,
|
registrations: &mut Vec<WebauthnRegistration>,
|
||||||
state: &mut PasskeyAuthentication,
|
state: &mut PasskeyAuthentication,
|
||||||
conn: &DbConn,
|
) -> Result<bool, Error> {
|
||||||
) -> EmptyResult {
|
|
||||||
// The feature flags from the response
|
// The feature flags from the response
|
||||||
// For details see: https://www.w3.org/TR/webauthn-3/#sctn-authenticator-data
|
// For details see: https://www.w3.org/TR/webauthn-3/#sctn-authenticator-data
|
||||||
const FLAG_BACKUP_ELIGIBLE: u8 = 0b0000_1000;
|
const FLAG_BACKUP_ELIGIBLE: u8 = 0b0000_1000;
|
||||||
@@ -486,16 +485,7 @@ async fn check_and_update_backup_eligible(
|
|||||||
let rsp_id = rsp.raw_id.as_slice();
|
let rsp_id = rsp.raw_id.as_slice();
|
||||||
for reg in &mut *registrations {
|
for reg in &mut *registrations {
|
||||||
if ct_eq(reg.credential.cred_id().as_slice(), rsp_id) {
|
if ct_eq(reg.credential.cred_id().as_slice(), rsp_id) {
|
||||||
// Try to update the key, and if needed also update the database, before the actual state check is done
|
|
||||||
if reg.set_backup_eligible(backup_eligible, backup_state) {
|
if reg.set_backup_eligible(backup_eligible, backup_state) {
|
||||||
TwoFactor::new(
|
|
||||||
user_id.clone(),
|
|
||||||
TwoFactorType::Webauthn,
|
|
||||||
serde_json::to_string(®istrations)?,
|
|
||||||
)
|
|
||||||
.save(conn)
|
|
||||||
.await?;
|
|
||||||
|
|
||||||
// We also need to adjust the current state which holds the challenge used to start the authentication verification
|
// We also need to adjust the current state which holds the challenge used to start the authentication verification
|
||||||
// Because Vaultwarden supports multiple keys, we need to loop through the deserialized state and check which key to update
|
// Because Vaultwarden supports multiple keys, we need to loop through the deserialized state and check which key to update
|
||||||
let mut raw_state = serde_json::to_value(&state)?;
|
let mut raw_state = serde_json::to_value(&state)?;
|
||||||
@@ -517,11 +507,12 @@ async fn check_and_update_backup_eligible(
|
|||||||
}
|
}
|
||||||
|
|
||||||
*state = serde_json::from_value(raw_state)?;
|
*state = serde_json::from_value(raw_state)?;
|
||||||
|
return Ok(true);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(false)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user