Browse Source

implement webauthn login deletion (untested)

pull/5929/head
zUnixorn 2 months ago
parent
commit
a4b480dc9f
No known key found for this signature in database GPG Key ID: BE3A9CAE3E8D0DA
  1. 19
      src/api/core/mod.rs
  2. 2
      src/db/models/mod.rs
  3. 12
      src/db/models/web_authn_credential.rs

19
src/api/core/mod.rs

@ -10,7 +10,7 @@ pub mod two_factor;
use std::collections::HashMap; use std::collections::HashMap;
use std::sync::{Mutex, OnceLock}; use std::sync::{Mutex, OnceLock};
use crate::db::models::WebAuthnCredential; use crate::db::models::{WebAuthnCredential, WebAuthnCredentialId};
pub use accounts::purge_auth_requests; pub use accounts::purge_auth_requests;
pub use ciphers::{purge_trashed_ciphers, CipherData, CipherSyncData, CipherSyncType}; pub use ciphers::{purge_trashed_ciphers, CipherData, CipherSyncData, CipherSyncType};
pub use emergency_access::{emergency_notification_reminder_job, emergency_request_timeout_job}; pub use emergency_access::{emergency_notification_reminder_job, emergency_request_timeout_job};
@ -21,7 +21,7 @@ pub use sends::purge_sends;
pub fn routes() -> Vec<Route> { pub fn routes() -> Vec<Route> {
let mut eq_domains_routes = routes![get_eq_domains, post_eq_domains, put_eq_domains]; let mut eq_domains_routes = routes![get_eq_domains, post_eq_domains, put_eq_domains];
let mut hibp_routes = routes![hibp_breach]; let mut hibp_routes = routes![hibp_breach];
let mut meta_routes = routes![alive, now, version, config, get_api_webauthn, post_api_webauthn, post_api_webauthn_attestation_options]; let mut meta_routes = routes![alive, now, version, config, get_api_webauthn, post_api_webauthn, post_api_webauthn_attestation_options, post_api_webauthn_delete];
let mut routes = Vec::new(); let mut routes = Vec::new();
routes.append(&mut accounts::routes()); routes.append(&mut accounts::routes());
@ -192,14 +192,25 @@ fn version() -> Json<&'static str> {
Json(crate::VERSION.unwrap_or_default()) Json(crate::VERSION.unwrap_or_default())
} }
#[post("/webauthn/<uuid>/delete", data = "<data>")]
async fn post_api_webauthn_delete(data: Json<PasswordOrOtpData>, uuid: String, headers: Headers, mut conn: DbConn) -> ApiResult<Status> {
let data: PasswordOrOtpData = data.into_inner();
let user = headers.user;
data.validate(&user, false, &mut conn).await?;
WebAuthnCredential::delete_by_uuid_and_user(&WebAuthnCredentialId(uuid), &user.uuid, &mut conn).await?;
Ok(Status::Ok)
}
static WEBAUTHN_STATES: OnceLock<Mutex<HashMap<UserId, RegistrationState>>> = OnceLock::new(); static WEBAUTHN_STATES: OnceLock<Mutex<HashMap<UserId, RegistrationState>>> = OnceLock::new();
#[post("/webauthn/attestation-options", data = "<data>")] #[post("/webauthn/attestation-options", data = "<data>")]
async fn post_api_webauthn_attestation_options(data: Json<PasswordOrOtpData>, headers: Headers, mut conn: DbConn) -> JsonResult { async fn post_api_webauthn_attestation_options(data: Json<PasswordOrOtpData>, headers: Headers, mut conn: DbConn) -> JsonResult {
let data: PasswordOrOtpData = data.into_inner(); let data: PasswordOrOtpData = data.into_inner();
let user = headers.user; let user = headers.user;
// TODO what does delete_if_valid do?
data.validate(&user, false, &mut conn).await?; data.validate(&user, false, &mut conn).await?;
// C# does this check as well // C# does this check as well

2
src/db/models/mod.rs

@ -40,4 +40,4 @@ pub use self::two_factor::{TwoFactor, TwoFactorType};
pub use self::two_factor_duo_context::TwoFactorDuoContext; pub use self::two_factor_duo_context::TwoFactorDuoContext;
pub use self::two_factor_incomplete::TwoFactorIncomplete; pub use self::two_factor_incomplete::TwoFactorIncomplete;
pub use self::user::{Invitation, User, UserId, UserKdfType, UserStampException}; pub use self::user::{Invitation, User, UserId, UserKdfType, UserStampException};
pub use self::web_authn_credential::WebAuthnCredential; pub use self::web_authn_credential::{WebAuthnCredential, WebAuthnCredentialId};

12
src/db/models/web_authn_credential.rs

@ -2,6 +2,7 @@ use derive_more::{AsRef, Deref, Display, From};
use macros::UuidFromParam; use macros::UuidFromParam;
use crate::api::EmptyResult; use crate::api::EmptyResult;
use crate::db::DbConn; use crate::db::DbConn;
use crate::MapResult;
use super::UserId; use super::UserId;
db_object! { db_object! {
@ -68,6 +69,15 @@ impl WebAuthnCredential {
// TODO do not unwrap // TODO do not unwrap
}}.unwrap() }}.unwrap()
} }
pub async fn delete_by_uuid_and_user(uuid: &WebAuthnCredentialId, user_uuid: &UserId, conn: &mut DbConn) -> EmptyResult {
db_run! { conn: {
diesel::delete(web_authn_credentials::table
.filter(web_authn_credentials::uuid.eq(uuid))
.filter(web_authn_credentials::user_uuid.eq(user_uuid))
).execute(conn).map_res("Error removing web_authn_credential for user")
}}
}
} }
#[derive( #[derive(
@ -86,4 +96,4 @@ impl WebAuthnCredential {
Deserialize, Deserialize,
UuidFromParam, UuidFromParam,
)] )]
pub struct WebAuthnCredentialId(String); pub struct WebAuthnCredentialId(pub String);

Loading…
Cancel
Save