mirror of
https://github.com/dani-garcia/vaultwarden.git
synced 2025-07-03 19:15:00 +00:00
fix: clippy warnings and formatting
This commit is contained in:
parent
3d4b29ff6b
commit
257e20b971
4 changed files with 72 additions and 42 deletions
|
@ -1,15 +1,3 @@
|
|||
use std::str::FromStr;
|
||||
use std::sync::Arc;
|
||||
use std::time::Duration;
|
||||
use once_cell::sync::Lazy;
|
||||
use rocket::serde::json::Json;
|
||||
use rocket::Route;
|
||||
use serde_json::Value;
|
||||
use url::Url;
|
||||
use uuid::Uuid;
|
||||
use webauthn_rs::{Webauthn, WebauthnBuilder};
|
||||
use webauthn_rs::prelude::{Base64UrlSafeData, Passkey, PasskeyAuthentication, PasskeyRegistration};
|
||||
use webauthn_rs_proto::{AuthenticationExtensionsClientOutputs, AuthenticatorAssertionResponseRaw, AuthenticatorAttestationResponseRaw, PublicKeyCredential, RegisterPublicKeyCredential, RegistrationExtensionsClientOutputs, RequestAuthenticationExtensions, UserVerificationPolicy};
|
||||
use crate::{
|
||||
api::{
|
||||
core::{log_user_event, two_factor::_generate_recover_code},
|
||||
|
@ -24,6 +12,22 @@ use crate::{
|
|||
util::NumberOrString,
|
||||
CONFIG,
|
||||
};
|
||||
use once_cell::sync::Lazy;
|
||||
use rocket::serde::json::Json;
|
||||
use rocket::Route;
|
||||
use serde_json::Value;
|
||||
use std::str::FromStr;
|
||||
use std::sync::Arc;
|
||||
use std::time::Duration;
|
||||
use url::Url;
|
||||
use uuid::Uuid;
|
||||
use webauthn_rs::prelude::{Base64UrlSafeData, Passkey, PasskeyAuthentication, PasskeyRegistration};
|
||||
use webauthn_rs::{Webauthn, WebauthnBuilder};
|
||||
use webauthn_rs_proto::{
|
||||
AuthenticationExtensionsClientOutputs, AuthenticatorAssertionResponseRaw, AuthenticatorAttestationResponseRaw,
|
||||
PublicKeyCredential, RegisterPublicKeyCredential, RegistrationExtensionsClientOutputs,
|
||||
RequestAuthenticationExtensions, UserVerificationPolicy,
|
||||
};
|
||||
|
||||
pub static WEBAUTHN_2FA_CONFIG: Lazy<Arc<Webauthn>> = Lazy::new(|| {
|
||||
let domain = CONFIG.domain();
|
||||
|
@ -31,10 +35,8 @@ pub static WEBAUTHN_2FA_CONFIG: Lazy<Arc<Webauthn>> = Lazy::new(|| {
|
|||
let rp_id = Url::parse(&domain).map(|u| u.domain().map(str::to_owned)).ok().flatten().unwrap_or_default();
|
||||
let rp_origin = Url::parse(&domain_origin).unwrap();
|
||||
|
||||
let webauthn = WebauthnBuilder::new(
|
||||
&rp_id,
|
||||
&rp_origin,
|
||||
).expect("Creating WebauthnBuilder failed")
|
||||
let webauthn = WebauthnBuilder::new(&rp_id, &rp_origin)
|
||||
.expect("Creating WebauthnBuilder failed")
|
||||
.rp_name(&domain)
|
||||
.timeout(Duration::from_millis(60000));
|
||||
|
||||
|
@ -110,7 +112,12 @@ async fn get_webauthn(data: Json<PasswordOrOtpData>, headers: Headers, mut conn:
|
|||
}
|
||||
|
||||
#[post("/two-factor/get-webauthn-challenge", data = "<data>")]
|
||||
async fn generate_webauthn_challenge(data: Json<PasswordOrOtpData>, headers: Headers, webauthn: Webauthn2FaConfig<'_>, mut conn: DbConn) -> JsonResult {
|
||||
async fn generate_webauthn_challenge(
|
||||
data: Json<PasswordOrOtpData>,
|
||||
headers: Headers,
|
||||
webauthn: Webauthn2FaConfig<'_>,
|
||||
mut conn: DbConn,
|
||||
) -> JsonResult {
|
||||
let data: PasswordOrOtpData = data.into_inner();
|
||||
let user = headers.user;
|
||||
|
||||
|
@ -233,7 +240,12 @@ impl From<PublicKeyCredentialCopy> for PublicKeyCredential {
|
|||
}
|
||||
|
||||
#[post("/two-factor/webauthn", data = "<data>")]
|
||||
async fn activate_webauthn(data: Json<EnableWebauthnData>, headers: Headers, webauthn: Webauthn2FaConfig<'_>, mut conn: DbConn) -> JsonResult {
|
||||
async fn activate_webauthn(
|
||||
data: Json<EnableWebauthnData>,
|
||||
headers: Headers,
|
||||
webauthn: Webauthn2FaConfig<'_>,
|
||||
mut conn: DbConn,
|
||||
) -> JsonResult {
|
||||
let data: EnableWebauthnData = data.into_inner();
|
||||
let mut user = headers.user;
|
||||
|
||||
|
@ -256,8 +268,7 @@ async fn activate_webauthn(data: Json<EnableWebauthnData>, headers: Headers, web
|
|||
};
|
||||
|
||||
// Verify the credentials with the saved state
|
||||
let credential = webauthn
|
||||
.finish_passkey_registration(&data.device_response.into(), &state)?;
|
||||
let credential = webauthn.finish_passkey_registration(&data.device_response.into(), &state)?;
|
||||
|
||||
let mut registrations: Vec<_> = get_webauthn_registrations(&user.uuid, &mut conn).await?.1;
|
||||
// TODO: Check for repeated ID's
|
||||
|
@ -286,7 +297,12 @@ async fn activate_webauthn(data: Json<EnableWebauthnData>, headers: Headers, web
|
|||
}
|
||||
|
||||
#[put("/two-factor/webauthn", data = "<data>")]
|
||||
async fn activate_webauthn_put(data: Json<EnableWebauthnData>, headers: Headers, webauthn: Webauthn2FaConfig<'_>, conn: DbConn) -> JsonResult {
|
||||
async fn activate_webauthn_put(
|
||||
data: Json<EnableWebauthnData>,
|
||||
headers: Headers,
|
||||
webauthn: Webauthn2FaConfig<'_>,
|
||||
conn: DbConn,
|
||||
) -> JsonResult {
|
||||
activate_webauthn(data, headers, webauthn, conn).await
|
||||
}
|
||||
|
||||
|
@ -357,10 +373,13 @@ pub async fn get_webauthn_registrations(
|
|||
}
|
||||
}
|
||||
|
||||
pub async fn generate_webauthn_login(user_id: &UserId, webauthn: Webauthn2FaConfig<'_>, conn: &mut DbConn) -> JsonResult {
|
||||
pub async fn generate_webauthn_login(
|
||||
user_id: &UserId,
|
||||
webauthn: Webauthn2FaConfig<'_>,
|
||||
conn: &mut DbConn,
|
||||
) -> JsonResult {
|
||||
// Load saved credentials
|
||||
let creds: Vec<_> =
|
||||
get_webauthn_registrations(user_id, conn).await?.1.into_iter().map(|r| r.credential).collect();
|
||||
let creds: Vec<_> = get_webauthn_registrations(user_id, conn).await?.1.into_iter().map(|r| r.credential).collect();
|
||||
|
||||
if creds.is_empty() {
|
||||
err!("No Webauthn devices registered")
|
||||
|
@ -377,11 +396,15 @@ pub async fn generate_webauthn_login(user_id: &UserId, webauthn: Webauthn2FaConf
|
|||
// Add appid
|
||||
let app_id = format!("{}/app-id.json", &CONFIG.domain());
|
||||
state["ast"]["appid"] = Value::String(app_id.clone());
|
||||
response.public_key.extensions.get_or_insert_with(|| RequestAuthenticationExtensions {
|
||||
appid: None,
|
||||
uvm: None,
|
||||
hmac_get_secret: None,
|
||||
}).appid = Some(app_id);
|
||||
response
|
||||
.public_key
|
||||
.extensions
|
||||
.get_or_insert(RequestAuthenticationExtensions {
|
||||
appid: None,
|
||||
uvm: None,
|
||||
hmac_get_secret: None,
|
||||
})
|
||||
.appid = Some(app_id);
|
||||
|
||||
// Save the challenge state for later validation
|
||||
TwoFactor::new(user_id.clone(), TwoFactorType::WebauthnLoginChallenge, serde_json::to_string(&state)?)
|
||||
|
@ -392,7 +415,12 @@ pub async fn generate_webauthn_login(user_id: &UserId, webauthn: Webauthn2FaConf
|
|||
Ok(Json(serde_json::to_value(response.public_key)?))
|
||||
}
|
||||
|
||||
pub async fn validate_webauthn_login(user_id: &UserId, response: &str, webauthn: Webauthn2FaConfig<'_>, conn: &mut DbConn) -> EmptyResult {
|
||||
pub async fn validate_webauthn_login(
|
||||
user_id: &UserId,
|
||||
response: &str,
|
||||
webauthn: Webauthn2FaConfig<'_>,
|
||||
conn: &mut DbConn,
|
||||
) -> EmptyResult {
|
||||
let type_ = TwoFactorType::WebauthnLoginChallenge as i32;
|
||||
let state = match TwoFactor::find_by_user_and_type(user_id, type_, conn).await {
|
||||
Some(tf) => {
|
||||
|
|
|
@ -7,6 +7,7 @@ use rocket::{
|
|||
};
|
||||
use serde_json::Value;
|
||||
|
||||
use crate::api::core::two_factor::webauthn::Webauthn2FaConfig;
|
||||
use crate::{
|
||||
api::{
|
||||
core::{
|
||||
|
@ -23,7 +24,6 @@ use crate::{
|
|||
error::MapResult,
|
||||
mail, util, CONFIG,
|
||||
};
|
||||
use crate::api::core::two_factor::webauthn::Webauthn2FaConfig;
|
||||
|
||||
pub fn routes() -> Vec<Route> {
|
||||
routes![login, prelogin, identity_register, register_verification_email, register_finish]
|
||||
|
@ -528,7 +528,9 @@ async fn twofactor_auth(
|
|||
Some(TwoFactorType::Authenticator) => {
|
||||
authenticator::validate_totp_code_str(&user.uuid, twofactor_code, &selected_data?, ip, conn).await?
|
||||
}
|
||||
Some(TwoFactorType::Webauthn) => webauthn::validate_webauthn_login(&user.uuid, twofactor_code, webauthn, conn).await?,
|
||||
Some(TwoFactorType::Webauthn) => {
|
||||
webauthn::validate_webauthn_login(&user.uuid, twofactor_code, webauthn, conn).await?
|
||||
}
|
||||
Some(TwoFactorType::YubiKey) => yubikey::validate_yubikey_login(twofactor_code, &selected_data?).await?,
|
||||
Some(TwoFactorType::Duo) => {
|
||||
match CONFIG.duo_use_iframe() {
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
use super::UserId;
|
||||
use crate::api::core::two_factor::webauthn::WebauthnRegistration;
|
||||
use crate::{api::EmptyResult, db::DbConn, error::MapResult};
|
||||
use serde_json::Value;
|
||||
use webauthn_rs::prelude::{Credential, ParsedAttestation};
|
||||
use webauthn_rs_proto::{AttestationFormat, RegisteredExtensions};
|
||||
use super::UserId;
|
||||
use crate::{api::EmptyResult, db::DbConn, error::MapResult};
|
||||
use crate::api::core::two_factor::webauthn::WebauthnRegistration;
|
||||
|
||||
db_object! {
|
||||
#[derive(Identifiable, Queryable, Insertable, AsChangeset)]
|
||||
|
@ -333,7 +333,8 @@ impl TwoFactor {
|
|||
extensions: RegisteredExtensions::none(),
|
||||
attestation: ParsedAttestation::default(),
|
||||
attestation_format: AttestationFormat::None,
|
||||
}.into(),
|
||||
}
|
||||
.into(),
|
||||
};
|
||||
|
||||
webauthn_regs.push(new_reg);
|
||||
|
@ -364,19 +365,18 @@ impl TwoFactor {
|
|||
for webauthn_factor in webauthn_factors {
|
||||
// assume that a failure to parse into the old struct, means that it was already converted
|
||||
// alternatively this could also be checked via an extra field in the db
|
||||
let Ok(regs) = serde_json::from_str::<Vec<webauthn_0_3::WebauthnRegistration>>(&webauthn_factor.data) else {
|
||||
let Ok(regs) = serde_json::from_str::<Vec<webauthn_0_3::WebauthnRegistration>>(&webauthn_factor.data)
|
||||
else {
|
||||
continue;
|
||||
};
|
||||
|
||||
let regs = regs.into_iter()
|
||||
.map(|r| r.into())
|
||||
.collect::<Vec<WebauthnRegistration>>();
|
||||
let regs = regs.into_iter().map(|r| r.into()).collect::<Vec<WebauthnRegistration>>();
|
||||
|
||||
TwoFactor::new(webauthn_factor.user_uuid.clone(), TwoFactorType::Webauthn, serde_json::to_string(®s)?)
|
||||
.save(conn)
|
||||
.await?;
|
||||
}
|
||||
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -59,6 +59,7 @@ mod ratelimit;
|
|||
mod util;
|
||||
|
||||
use crate::api::core::two_factor::duo_oidc::purge_duo_contexts;
|
||||
use crate::api::core::two_factor::webauthn::WEBAUTHN_2FA_CONFIG;
|
||||
use crate::api::purge_auth_requests;
|
||||
use crate::api::{WS_ANONYMOUS_SUBSCRIPTIONS, WS_USERS};
|
||||
pub use config::{PathType, CONFIG};
|
||||
|
@ -66,7 +67,6 @@ pub use error::{Error, MapResult};
|
|||
use rocket::data::{Limits, ToByteUnit};
|
||||
use std::sync::{atomic::Ordering, Arc};
|
||||
pub use util::is_running_in_container;
|
||||
use crate::api::core::two_factor::webauthn::WEBAUTHN_2FA_CONFIG;
|
||||
|
||||
#[rocket::main]
|
||||
async fn main() -> Result<(), Error> {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue