vw_small

Hardened fork of Vaultwarden (https://github.com/dani-garcia/vaultwarden) with fewer features.
git clone https://git.philomathiclife.com/repos/vw_small
Log | Files | Refs | README

webauthn.rs (35323B)


      1 use crate::{
      2     api::{EmptyResult, JsonResult, PasswordOrOtpData},
      3     auth::{self, Headers},
      4     config,
      5     db::{
      6         models::{WebAuthn, WebAuthnInfo},
      7         DbConn,
      8     },
      9     error::Error,
     10 };
     11 use data_encoding::{BASE64, BASE64URL_NOPAD};
     12 use rocket::serde::json::Json;
     13 use rocket::Route;
     14 use serde::de::{Deserialize, Deserializer, Error as SerdeErr, MapAccess, Unexpected, Visitor};
     15 use std::fmt::{self, Formatter};
     16 use uuid::Uuid;
     17 use webauthn_rp::{
     18     request::{
     19         auth::PublicKeyCredentialRequestOptions,
     20         register::{
     21             Nickname, PublicKeyCredentialCreationOptions, PublicKeyCredentialUserEntity,
     22             UserHandle, Username,
     23         },
     24         InsertResult,
     25     },
     26     response::{
     27         auth::Authentication,
     28         register::{AuthenticatorAttestation, Registration},
     29         AuthTransports, AuthenticatorAttachment, CollectedClientData, CredentialId,
     30     },
     31     AggErr,
     32 };
     33 
     34 pub fn routes() -> Vec<Route> {
     35     routes![
     36         activate_webauthn,
     37         activate_webauthn_put,
     38         delete_webauthn,
     39         generate_webauthn_challenge,
     40         get_webauthn,
     41     ]
     42 }
     43 #[post("/two-factor/get-webauthn", data = "<data>")]
     44 async fn get_webauthn(data: Json<PasswordOrOtpData>, headers: Headers, conn: DbConn) -> JsonResult {
     45     let data: PasswordOrOtpData = data.into_inner();
     46     let user = headers.user;
     47     data.validate(&user)?;
     48     let keys = WebAuthnInfo::get_all_by_user(&user.uuid, &conn).await?;
     49     Ok(Json(json!({
     50         "enabled": !keys.is_empty(),
     51         "keys": keys,
     52         "object": "twoFactorWebAuthn"
     53     })))
     54 }
     55 #[post("/two-factor/get-webauthn-challenge", data = "<data>")]
     56 async fn generate_webauthn_challenge(
     57     data: Json<PasswordOrOtpData>,
     58     headers: Headers,
     59     conn: DbConn,
     60 ) -> JsonResult {
     61     let data: PasswordOrOtpData = data.into_inner();
     62     let user = headers.user;
     63     data.validate(&user)?;
     64     let name = Username::try_from(user.email.as_str()).map_err(AggErr::Username)?;
     65     let uuid = Uuid::parse_str(user.uuid.as_str())
     66         .map_err(|e| Error::from(e.to_string()))?
     67         .into_bytes();
     68     let id = UserHandle::try_from(uuid.as_slice()).map_err(AggErr::UserHandle)?;
     69     let display_name = Some(Nickname::try_from(user.name.as_str()).map_err(AggErr::Nickname)?);
     70     let (server, client) = PublicKeyCredentialCreationOptions::second_factor(
     71         &config::get_config().rp_id,
     72         PublicKeyCredentialUserEntity {
     73             name,
     74             id,
     75             display_name,
     76         },
     77         WebAuthn::get_registered_creds(user.uuid.as_str(), &conn).await?,
     78     )
     79     .start_ceremony()
     80     .map_err(AggErr::CreationOptions)?;
     81     match auth::get_reg_ceremonies().insert_or_replace_all_expired(server) {
     82         InsertResult::Success => {
     83             let mut challenge_value = serde_json::to_value(client)?;
     84             challenge_value["status"] = "ok".into();
     85             challenge_value["errorMessage"] = "".into();
     86             Ok(Json(challenge_value))
     87         }
     88         InsertResult::CapacityFull => Err(Error::from(String::from(
     89             "too many active ceremonies. try again later",
     90         ))),
     91         InsertResult::Duplicate => Err(Error::from(String::from("duplicate webauthn challenge"))),
     92     }
     93 }
     94 struct Type;
     95 impl<'e> Deserialize<'e> for Type {
     96     fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
     97     where
     98         D: Deserializer<'e>,
     99     {
    100         struct TypeVisitor;
    101         impl<'f> Visitor<'f> for TypeVisitor {
    102             type Value = Type;
    103             fn expecting(&self, formatter: &mut Formatter<'_>) -> fmt::Result {
    104                 formatter.write_str("public-key")
    105             }
    106             fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
    107             where
    108                 E: SerdeErr,
    109             {
    110                 if v == "public-key" {
    111                     Ok(Type)
    112                 } else {
    113                     Err(E::invalid_value(Unexpected::Str(v), &"public-key"))
    114                 }
    115             }
    116         }
    117         deserializer.deserialize_str(TypeVisitor)
    118     }
    119 }
    120 struct RegistrationWrapper(Registration);
    121 impl<'de> Deserialize<'de> for RegistrationWrapper {
    122     fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    123     where
    124         D: Deserializer<'de>,
    125     {
    126         struct RegistrationVisitor;
    127         impl<'d> Visitor<'d> for RegistrationVisitor {
    128             type Value = RegistrationWrapper;
    129             fn expecting(&self, formatter: &mut Formatter<'_>) -> fmt::Result {
    130                 formatter.write_str("RegistrationWrapper")
    131             }
    132             fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
    133             where
    134                 A: MapAccess<'d>,
    135             {
    136                 enum Field {
    137                     Id,
    138                     RawId,
    139                     Response,
    140                     Extensions,
    141                     Type,
    142                 }
    143                 impl<'e> Deserialize<'e> for Field {
    144                     fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    145                     where
    146                         D: Deserializer<'e>,
    147                     {
    148                         struct FieldVisitor;
    149                         impl<'f> Visitor<'f> for FieldVisitor {
    150                             type Value = Field;
    151                             fn expecting(&self, formatter: &mut Formatter<'_>) -> fmt::Result {
    152                                 write!(
    153                                     formatter,
    154                                     "'{ID}', '{RAW_ID}', '{RESPONSE}', '{EXTENSIONS}', or '{TYPE}'"
    155                                 )
    156                             }
    157                             fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
    158                             where
    159                                 E: SerdeErr,
    160                             {
    161                                 match v {
    162                                     ID => Ok(Field::Id),
    163                                     RAW_ID => Ok(Field::RawId),
    164                                     RESPONSE => Ok(Field::Response),
    165                                     EXTENSIONS => Ok(Field::Extensions),
    166                                     TYPE => Ok(Field::Type),
    167                                     _ => Err(E::unknown_field(v, FIELDS)),
    168                                 }
    169                             }
    170                         }
    171                         deserializer.deserialize_identifier(FieldVisitor)
    172                     }
    173                 }
    174                 struct RawId(CredentialId<Vec<u8>>);
    175                 impl<'e> Deserialize<'e> for RawId {
    176                     fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    177                     where
    178                         D: Deserializer<'e>,
    179                     {
    180                         struct RawIdVisitor;
    181                         impl<'f> Visitor<'f> for RawIdVisitor {
    182                             type Value = RawId;
    183                             fn expecting(&self, formatter: &mut Formatter<'_>) -> fmt::Result {
    184                                 formatter.write_str("RawId")
    185                             }
    186                             fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
    187                             where
    188                                 E: SerdeErr,
    189                             {
    190                                 BASE64.decode(v.as_bytes()).map_err(E::custom).and_then(
    191                                     |base64url| {
    192                                         BASE64URL_NOPAD
    193                                             .decode(base64url.as_slice())
    194                                             .map_err(E::custom)
    195                                             .and_then(|cred_id| {
    196                                                 CredentialId::try_from(cred_id)
    197                                                     .map_err(E::custom)
    198                                                     .map(RawId)
    199                                             })
    200                                     },
    201                                 )
    202                             }
    203                         }
    204                         deserializer.deserialize_str(RawIdVisitor)
    205                     }
    206                 }
    207                 struct AuthAttestWrapper(AuthenticatorAttestation);
    208                 impl<'e> Deserialize<'e> for AuthAttestWrapper {
    209                     fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    210                     where
    211                         D: Deserializer<'e>,
    212                     {
    213                         struct AuthAttestVisitor;
    214                         impl<'f> Visitor<'f> for AuthAttestVisitor {
    215                             type Value = AuthAttestWrapper;
    216                             fn expecting(&self, formatter: &mut Formatter<'_>) -> fmt::Result {
    217                                 formatter.write_str("AuthAttestWrapper")
    218                             }
    219                             fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
    220                             where
    221                                 A: MapAccess<'f>,
    222                             {
    223                                 enum AuthField {
    224                                     AttestationObject,
    225                                     ClientDataJson,
    226                                 }
    227                                 impl<'g> Deserialize<'g> for AuthField {
    228                                     fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    229                                     where
    230                                         D: Deserializer<'g>,
    231                                     {
    232                                         struct AuthFieldVisitor;
    233                                         impl<'h> Visitor<'h> for AuthFieldVisitor {
    234                                             type Value = AuthField;
    235                                             fn expecting(
    236                                                 &self,
    237                                                 formatter: &mut Formatter<'_>,
    238                                             ) -> fmt::Result
    239                                             {
    240                                                 write!(formatter, "'{ATTESTATION_OBJECT}' or '{CLIENT_DATA_JSON}'")
    241                                             }
    242                                             fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
    243                                             where
    244                                                 E: SerdeErr,
    245                                             {
    246                                                 match v {
    247                                                     ATTESTATION_OBJECT => {
    248                                                         Ok(AuthField::AttestationObject)
    249                                                     }
    250                                                     CLIENT_DATA_JSON => {
    251                                                         Ok(AuthField::ClientDataJson)
    252                                                     }
    253                                                     _ => Err(E::unknown_field(v, AUTH_FIELDS)),
    254                                                 }
    255                                             }
    256                                         }
    257                                         deserializer.deserialize_identifier(AuthFieldVisitor)
    258                                     }
    259                                 }
    260                                 struct Base64(Vec<u8>);
    261                                 impl<'g> Deserialize<'g> for Base64 {
    262                                     fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    263                                     where
    264                                         D: Deserializer<'g>,
    265                                     {
    266                                         struct Base64Visitor;
    267                                         impl<'h> Visitor<'h> for Base64Visitor {
    268                                             type Value = Base64;
    269                                             fn expecting(
    270                                                 &self,
    271                                                 formatter: &mut Formatter<'_>,
    272                                             ) -> fmt::Result
    273                                             {
    274                                                 formatter.write_str("base64-encoded value")
    275                                             }
    276                                             fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
    277                                             where
    278                                                 E: SerdeErr,
    279                                             {
    280                                                 BASE64
    281                                                     .decode(v.as_bytes())
    282                                                     .map_err(E::custom)
    283                                                     .map(Base64)
    284                                             }
    285                                         }
    286                                         deserializer.deserialize_str(Base64Visitor)
    287                                     }
    288                                 }
    289                                 let mut att_obj = None;
    290                                 let mut client_data = None;
    291                                 while let Some(key) = map.next_key()? {
    292                                     match key {
    293                                         AuthField::AttestationObject => {
    294                                             if att_obj.is_some() {
    295                                                 return Err(SerdeErr::duplicate_field(
    296                                                     ATTESTATION_OBJECT,
    297                                                 ));
    298                                             }
    299                                             att_obj = map
    300                                                 .next_value::<Base64>()
    301                                                 .map(|base64| Some(base64.0))?;
    302                                         }
    303                                         AuthField::ClientDataJson => {
    304                                             if client_data.is_some() {
    305                                                 return Err(SerdeErr::duplicate_field(
    306                                                     CLIENT_DATA_JSON,
    307                                                 ));
    308                                             }
    309                                             client_data = map
    310                                                 .next_value::<Base64>()
    311                                                 .map(|base64| Some(base64.0))?;
    312                                         }
    313                                     }
    314                                 }
    315                                 att_obj
    316                                     .ok_or_else(|| SerdeErr::missing_field(ATTESTATION_OBJECT))
    317                                     .and_then(|attestation_object| {
    318                                         client_data
    319                                             .ok_or_else(|| {
    320                                                 SerdeErr::missing_field(CLIENT_DATA_JSON)
    321                                             })
    322                                             .map(|client_data_json| {
    323                                                 AuthAttestWrapper(AuthenticatorAttestation::new(
    324                                                     client_data_json,
    325                                                     attestation_object,
    326                                                     AuthTransports::NONE,
    327                                                 ))
    328                                             })
    329                                     })
    330                             }
    331                         }
    332                         const ATTESTATION_OBJECT: &str = "attestationObject";
    333                         const CLIENT_DATA_JSON: &str = "clientDataJSON";
    334                         const AUTH_FIELDS: &[&str; 2] = &[ATTESTATION_OBJECT, CLIENT_DATA_JSON];
    335                         deserializer.deserialize_struct(
    336                             "AuthAttestWrapper",
    337                             AUTH_FIELDS,
    338                             AuthAttestVisitor,
    339                         )
    340                     }
    341                 }
    342                 let mut id = None;
    343                 let mut raw_id = None;
    344                 let mut response = None;
    345                 let mut extensions = None;
    346                 let mut typ = false;
    347                 while let Some(key) = map.next_key()? {
    348                     match key {
    349                         Field::Id => {
    350                             if id.is_some() {
    351                                 return Err(SerdeErr::duplicate_field(ID));
    352                             }
    353                             id = map.next_value::<CredentialId<Vec<u8>>>().map(Some)?;
    354                         }
    355                         Field::RawId => {
    356                             if raw_id.is_some() {
    357                                 return Err(SerdeErr::duplicate_field(RAW_ID));
    358                             }
    359                             raw_id = map.next_value::<RawId>().map(Some)?;
    360                         }
    361                         Field::Response => {
    362                             if response.is_some() {
    363                                 return Err(SerdeErr::duplicate_field(RESPONSE));
    364                             }
    365                             response = map
    366                                 .next_value::<AuthAttestWrapper>()
    367                                 .map(|attest| Some(attest.0))?;
    368                         }
    369                         Field::Extensions => {
    370                             if extensions.is_some() {
    371                                 return Err(SerdeErr::duplicate_field(EXTENSIONS));
    372                             }
    373                             extensions = map.next_value().map(Some)?;
    374                         }
    375                         Field::Type => {
    376                             if typ {
    377                                 return Err(SerdeErr::duplicate_field(TYPE));
    378                             }
    379                             typ = map.next_value::<Type>().map(|_| true)?;
    380                         }
    381                     }
    382                 }
    383                 id.ok_or_else(|| SerdeErr::missing_field(ID)).and_then(|i| {
    384                     raw_id
    385                         .ok_or_else(|| SerdeErr::missing_field(RAW_ID))
    386                         .and_then(|r| {
    387                             if i == r.0 {
    388                                 response
    389                                     .ok_or_else(|| SerdeErr::missing_field(RESPONSE))
    390                                     .and_then(|resp| {
    391                                         extensions
    392                                             .ok_or_else(|| SerdeErr::missing_field(EXTENSIONS))
    393                                             .and_then(|ext| {
    394                                                 if typ {
    395                                                     Ok(RegistrationWrapper(Registration::new(
    396                                                         resp,
    397                                                         AuthenticatorAttachment::None,
    398                                                         ext,
    399                                                     )))
    400                                                 } else {
    401                                                     Err(SerdeErr::missing_field(TYPE))
    402                                                 }
    403                                             })
    404                                     })
    405                             } else {
    406                                 Err(SerdeErr::invalid_value(
    407                                     Unexpected::Bytes(r.0.as_ref()),
    408                                     &format!("id: {:?} to match rawId", i.as_ref()).as_str(),
    409                                 ))
    410                             }
    411                         })
    412                 })
    413             }
    414         }
    415         const ID: &str = "id";
    416         const RAW_ID: &str = "rawId";
    417         const RESPONSE: &str = "response";
    418         const EXTENSIONS: &str = "extensions";
    419         const TYPE: &str = "type";
    420         const FIELDS: &[&str; 5] = &[ID, RAW_ID, RESPONSE, EXTENSIONS, TYPE];
    421         deserializer.deserialize_struct("RegistrationWrapper", FIELDS, RegistrationVisitor)
    422     }
    423 }
    424 
    425 #[derive(Deserialize)]
    426 #[serde(rename_all = "camelCase")]
    427 struct EnableWebauthnData {
    428     id: i64,
    429     name: String,
    430     device_response: RegistrationWrapper,
    431     master_password_hash: String,
    432 }
    433 
    434 #[post("/two-factor/webauthn", data = "<data>")]
    435 async fn activate_webauthn(
    436     data: Json<EnableWebauthnData>,
    437     headers: Headers,
    438     conn: DbConn,
    439 ) -> JsonResult {
    440     let data = data.into_inner();
    441     let user = headers.user;
    442     PasswordOrOtpData {
    443         master_password_hash: Some(data.master_password_hash),
    444         otp: None,
    445     }
    446     .validate(&user)?;
    447     let uuid = Uuid::parse_str(user.uuid.as_str())
    448         .map_err(|e| Error::from(e.to_string()))?
    449         .into_bytes();
    450     let user_handle = UserHandle::try_from(uuid.as_slice()).map_err(AggErr::UserHandle)?;
    451     let cred = auth::get_reg_ceremonies()
    452         .take(
    453             &CollectedClientData::from_client_data_json_relaxed::<true>(
    454                 data.device_response.0.response().client_data_json(),
    455             )
    456             .map_err(AggErr::SerdeJson)?
    457             .challenge,
    458         )
    459         .ok_or_else(|| Error::from(String::from("missing registration challenge")))?
    460         .verify(
    461             &config::get_config().rp_id,
    462             user_handle,
    463             &data.device_response.0,
    464             auth::get_reg_options(),
    465         )
    466         .map_err(AggErr::RegCeremony)?;
    467     WebAuthn::new(&cred, user.uuid.clone(), data.id, data.name)?
    468         .insert(&conn)
    469         .await?;
    470     let keys = WebAuthnInfo::get_all_by_user(user.uuid.as_str(), &conn).await?;
    471     Ok(Json(json!({
    472         "enabled": !keys.is_empty(),
    473         "keys": keys,
    474         "object": "twoFactorWebAuthn"
    475     })))
    476 }
    477 
    478 #[put("/two-factor/webauthn", data = "<data>")]
    479 async fn activate_webauthn_put(
    480     data: Json<EnableWebauthnData>,
    481     headers: Headers,
    482     conn: DbConn,
    483 ) -> JsonResult {
    484     activate_webauthn(data, headers, conn).await
    485 }
    486 
    487 #[derive(Deserialize)]
    488 #[serde(rename_all = "camelCase")]
    489 struct DeleteU2FData {
    490     id: i64,
    491     master_password_hash: String,
    492 }
    493 
    494 #[delete("/two-factor/webauthn", data = "<data>")]
    495 async fn delete_webauthn(data: Json<DeleteU2FData>, headers: Headers, conn: DbConn) -> JsonResult {
    496     if !headers
    497         .user
    498         .check_valid_password(&data.master_password_hash)
    499     {
    500         err!("Invalid password");
    501     }
    502     WebAuthn::delete_by_user_uuid_and_id(&headers.user.uuid, data.id, &conn).await?;
    503     let keys = WebAuthnInfo::get_all_by_user(&headers.user.uuid, &conn).await?;
    504     Ok(Json(json!({
    505         "enabled": !keys.is_empty(),
    506         "keys": keys,
    507         "object": "twoFactorWebAuthn"
    508     })))
    509 }
    510 
    511 pub async fn generate_webauthn_login(user_uuid: &str, conn: &DbConn) -> JsonResult {
    512     let creds = WebAuthn::get_allowed_creds(user_uuid, conn).await?;
    513     let (server, client) =
    514         PublicKeyCredentialRequestOptions::second_factor(&config::get_config().rp_id, creds)
    515             .map_err(AggErr::SecondFactor)?
    516             .start_ceremony()
    517             .map_err(AggErr::RequestOptions)?;
    518     match auth::get_auth_ceremonies().insert_or_replace_all_expired(server) {
    519         InsertResult::Success => Ok(Json(serde_json::to_value(client)?)),
    520         InsertResult::CapacityFull => Err(Error::from(String::from(
    521             "too many active ceremonies. try again later",
    522         ))),
    523         InsertResult::Duplicate => Err(Error::from(String::from("duplicate webauthn challenge"))),
    524     }
    525 }
    526 struct AuthenticationWrapper(Authentication);
    527 impl<'de> Deserialize<'de> for AuthenticationWrapper {
    528     fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    529     where
    530         D: Deserializer<'de>,
    531     {
    532         struct AuthenticationVisitor;
    533         impl<'d> Visitor<'d> for AuthenticationVisitor {
    534             type Value = AuthenticationWrapper;
    535             fn expecting(&self, formatter: &mut Formatter<'_>) -> fmt::Result {
    536                 formatter.write_str("AuthenticationWrapper")
    537             }
    538             fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
    539             where
    540                 A: MapAccess<'d>,
    541             {
    542                 enum Field {
    543                     Id,
    544                     RawId,
    545                     Response,
    546                     Extensions,
    547                     Type,
    548                 }
    549                 impl<'e> Deserialize<'e> for Field {
    550                     fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    551                     where
    552                         D: Deserializer<'e>,
    553                     {
    554                         struct FieldVisitor;
    555                         impl<'f> Visitor<'f> for FieldVisitor {
    556                             type Value = Field;
    557                             fn expecting(&self, formatter: &mut Formatter<'_>) -> fmt::Result {
    558                                 write!(
    559                                     formatter,
    560                                     "'{ID}', '{RAW_ID}', '{RESPONSE}', '{EXTENSIONS}', or '{TYPE}'"
    561                                 )
    562                             }
    563                             fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
    564                             where
    565                                 E: SerdeErr,
    566                             {
    567                                 match v {
    568                                     ID => Ok(Field::Id),
    569                                     RAW_ID => Ok(Field::RawId),
    570                                     RESPONSE => Ok(Field::Response),
    571                                     EXTENSIONS => Ok(Field::Extensions),
    572                                     TYPE => Ok(Field::Type),
    573                                     _ => Err(E::unknown_field(v, FIELDS)),
    574                                 }
    575                             }
    576                         }
    577                         deserializer.deserialize_identifier(FieldVisitor)
    578                     }
    579                 }
    580                 struct Extensions;
    581                 impl<'e> Deserialize<'e> for Extensions {
    582                     fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    583                     where
    584                         D: Deserializer<'e>,
    585                     {
    586                         struct ExtensionsVisitor;
    587                         impl<'f> Visitor<'f> for ExtensionsVisitor {
    588                             type Value = Extensions;
    589                             fn expecting(&self, formatter: &mut Formatter<'_>) -> fmt::Result {
    590                                 formatter.write_str("Extensions")
    591                             }
    592                             fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
    593                             where
    594                                 A: MapAccess<'f>,
    595                             {
    596                                 struct Field;
    597                                 impl<'g> Deserialize<'g> for Field {
    598                                     fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    599                                     where
    600                                         D: Deserializer<'g>,
    601                                     {
    602                                         struct FieldVisitor;
    603                                         impl<'h> Visitor<'h> for FieldVisitor {
    604                                             type Value = Field;
    605                                             fn expecting(
    606                                                 &self,
    607                                                 formatter: &mut Formatter<'_>,
    608                                             ) -> fmt::Result
    609                                             {
    610                                                 write!(formatter, "'{APPID}'")
    611                                             }
    612                                             fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
    613                                             where
    614                                                 E: SerdeErr,
    615                                             {
    616                                                 if v == APPID {
    617                                                     Ok(Field)
    618                                                 } else {
    619                                                     Err(E::unknown_field(v, FIELDS))
    620                                                 }
    621                                             }
    622                                         }
    623                                         deserializer.deserialize_identifier(FieldVisitor)
    624                                     }
    625                                 }
    626                                 let mut appid = false;
    627                                 while map.next_key::<Field>()?.is_some() {
    628                                     if appid {
    629                                         return Err(SerdeErr::duplicate_field(APPID));
    630                                     }
    631                                     appid = map.next_value::<bool>().and_then(|v| {
    632                                         if v {
    633                                             Err(SerdeErr::invalid_value(
    634                                                 Unexpected::Bool(true),
    635                                                 &"appid to be false",
    636                                             ))
    637                                         } else {
    638                                             Ok(true)
    639                                         }
    640                                     })?;
    641                                 }
    642                                 Ok(Extensions)
    643                             }
    644                         }
    645                         const APPID: &str = "appid";
    646                         const FIELDS: &[&str; 1] = &[APPID];
    647                         deserializer.deserialize_struct(
    648                             "EmptyExtensions",
    649                             FIELDS,
    650                             ExtensionsVisitor,
    651                         )
    652                     }
    653                 }
    654                 let mut id = None;
    655                 let mut raw_id = None;
    656                 let mut response = None;
    657                 let mut extensions = false;
    658                 let mut typ = false;
    659                 while let Some(key) = map.next_key()? {
    660                     match key {
    661                         Field::Id => {
    662                             if id.is_some() {
    663                                 return Err(SerdeErr::duplicate_field(ID));
    664                             }
    665                             id = map.next_value::<CredentialId<Vec<u8>>>().map(Some)?;
    666                         }
    667                         Field::RawId => {
    668                             if raw_id.is_some() {
    669                                 return Err(SerdeErr::duplicate_field(RAW_ID));
    670                             }
    671                             raw_id = map.next_value::<CredentialId<Vec<u8>>>().map(Some)?;
    672                         }
    673                         Field::Response => {
    674                             if response.is_some() {
    675                                 return Err(SerdeErr::duplicate_field(RESPONSE));
    676                             }
    677                             response = map.next_value().map(Some)?;
    678                         }
    679                         Field::Extensions => {
    680                             if extensions {
    681                                 return Err(SerdeErr::duplicate_field(EXTENSIONS));
    682                             }
    683                             extensions = map.next_value::<Extensions>().map(|_| true)?;
    684                         }
    685                         Field::Type => {
    686                             if typ {
    687                                 return Err(SerdeErr::duplicate_field(TYPE));
    688                             }
    689                             typ = map.next_value::<Type>().map(|_| true)?;
    690                         }
    691                     }
    692                 }
    693                 id.ok_or_else(|| SerdeErr::missing_field(ID)).and_then(|i| {
    694                     raw_id
    695                         .ok_or_else(|| SerdeErr::missing_field(RAW_ID))
    696                         .and_then(|r| {
    697                             if i == r {
    698                                 response
    699                                     .ok_or_else(|| SerdeErr::missing_field(RESPONSE))
    700                                     .and_then(|resp| {
    701                                         if extensions {
    702                                             if typ {
    703                                                 Ok(AuthenticationWrapper(Authentication::new(
    704                                                     r,
    705                                                     resp,
    706                                                     AuthenticatorAttachment::None,
    707                                                 )))
    708                                             } else {
    709                                                 Err(SerdeErr::missing_field(TYPE))
    710                                             }
    711                                         } else {
    712                                             Err(SerdeErr::missing_field(EXTENSIONS))
    713                                         }
    714                                     })
    715                             } else {
    716                                 Err(SerdeErr::invalid_value(
    717                                     Unexpected::Bytes(r.as_ref()),
    718                                     &format!("id: {:?} to match rawId", i.as_ref()).as_str(),
    719                                 ))
    720                             }
    721                         })
    722                 })
    723             }
    724         }
    725         const ID: &str = "id";
    726         const RAW_ID: &str = "rawId";
    727         const RESPONSE: &str = "response";
    728         const EXTENSIONS: &str = "extensions";
    729         const TYPE: &str = "type";
    730         const FIELDS: &[&str; 5] = &[ID, RAW_ID, RESPONSE, EXTENSIONS, TYPE];
    731         deserializer.deserialize_struct("RegistrationWrapper", FIELDS, AuthenticationVisitor)
    732     }
    733 }
    734 pub async fn validate_webauthn_login(
    735     user_uuid: &str,
    736     response: &str,
    737     conn: &DbConn,
    738 ) -> EmptyResult {
    739     let auth = serde_json::from_str::<AuthenticationWrapper>(response)?.0;
    740     let uuid = Uuid::parse_str(user_uuid)
    741         .map_err(|e| Error::from(e.to_string()))?
    742         .into_bytes();
    743     let user_handle = UserHandle::try_from(uuid.as_slice()).map_err(AggErr::UserHandle)?;
    744     let mut cred = WebAuthn::get_credential(auth.raw_id(), user_uuid, user_handle, conn)
    745         .await?
    746         .ok_or_else(|| Error::from(String::from("credential does not exist")))?;
    747     if auth::get_auth_ceremonies()
    748         .take(
    749             &CollectedClientData::from_client_data_json_relaxed::<false>(
    750                 auth.response().client_data_json(),
    751             )
    752             .map_err(AggErr::SerdeJson)?
    753             .challenge,
    754         )
    755         .ok_or_else(|| Error::from(String::from("no authentication challenge")))?
    756         .verify(
    757             &config::get_config().rp_id,
    758             &auth,
    759             &mut cred,
    760             &auth::get_auth_options(),
    761         )
    762         .map_err(AggErr::AuthCeremony)?
    763     {
    764         WebAuthn::update(auth.raw_id(), cred.dynamic_state(), conn).await
    765     } else {
    766         Ok(())
    767     }
    768 }