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 (35315B)


      1 use crate::{
      2     api::{EmptyResult, JsonResult, PasswordOrOtpData},
      3     auth::{self, Headers},
      4     config,
      5     db::{
      6         DbConn,
      7         models::{WebAuthn, WebAuthnInfo},
      8     },
      9     error::Error,
     10 };
     11 use data_encoding::{BASE64, BASE64URL_NOPAD};
     12 use rocket::Route;
     13 use rocket::serde::json::Json;
     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     AggErr,
     19     request::{
     20         InsertResult,
     21         auth::NonDiscoverableCredentialRequestOptions,
     22         register::{
     23             Nickname, PublicKeyCredentialCreationOptions, PublicKeyCredentialUserEntity,
     24             UserHandle16, Username,
     25         },
     26     },
     27     response::{
     28         AuthTransports, AuthenticatorAttachment, CollectedClientData, CredentialId,
     29         auth::NonDiscoverableAuthentication16,
     30         register::{AuthenticatorAttestation, Registration},
     31     },
     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 = UserHandle16::from(uuid);
     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: &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 Visitor<'_> 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 Visitor<'_> 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 Visitor<'_> 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 Visitor<'_> for AuthFieldVisitor {
    234                                             type Value = AuthField;
    235                                             fn expecting(
    236                                                 &self,
    237                                                 formatter: &mut Formatter<'_>,
    238                                             ) -> fmt::Result
    239                                             {
    240                                                 write!(
    241                                                     formatter,
    242                                                     "'{ATTESTATION_OBJECT}' or '{CLIENT_DATA_JSON}'"
    243                                                 )
    244                                             }
    245                                             fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
    246                                             where
    247                                                 E: SerdeErr,
    248                                             {
    249                                                 match v {
    250                                                     ATTESTATION_OBJECT => {
    251                                                         Ok(AuthField::AttestationObject)
    252                                                     }
    253                                                     CLIENT_DATA_JSON => {
    254                                                         Ok(AuthField::ClientDataJson)
    255                                                     }
    256                                                     _ => Err(E::unknown_field(v, AUTH_FIELDS)),
    257                                                 }
    258                                             }
    259                                         }
    260                                         deserializer.deserialize_identifier(AuthFieldVisitor)
    261                                     }
    262                                 }
    263                                 struct Base64(Vec<u8>);
    264                                 impl<'g> Deserialize<'g> for Base64 {
    265                                     fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    266                                     where
    267                                         D: Deserializer<'g>,
    268                                     {
    269                                         struct Base64Visitor;
    270                                         impl Visitor<'_> for Base64Visitor {
    271                                             type Value = Base64;
    272                                             fn expecting(
    273                                                 &self,
    274                                                 formatter: &mut Formatter<'_>,
    275                                             ) -> fmt::Result
    276                                             {
    277                                                 formatter.write_str("base64-encoded value")
    278                                             }
    279                                             fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
    280                                             where
    281                                                 E: SerdeErr,
    282                                             {
    283                                                 BASE64
    284                                                     .decode(v.as_bytes())
    285                                                     .map_err(E::custom)
    286                                                     .map(Base64)
    287                                             }
    288                                         }
    289                                         deserializer.deserialize_str(Base64Visitor)
    290                                     }
    291                                 }
    292                                 let mut att_obj = None;
    293                                 let mut client_data = None;
    294                                 while let Some(key) = map.next_key()? {
    295                                     match key {
    296                                         AuthField::AttestationObject => {
    297                                             if att_obj.is_some() {
    298                                                 return Err(SerdeErr::duplicate_field(
    299                                                     ATTESTATION_OBJECT,
    300                                                 ));
    301                                             }
    302                                             att_obj = map
    303                                                 .next_value::<Base64>()
    304                                                 .map(|base64| Some(base64.0))?;
    305                                         }
    306                                         AuthField::ClientDataJson => {
    307                                             if client_data.is_some() {
    308                                                 return Err(SerdeErr::duplicate_field(
    309                                                     CLIENT_DATA_JSON,
    310                                                 ));
    311                                             }
    312                                             client_data = map
    313                                                 .next_value::<Base64>()
    314                                                 .map(|base64| Some(base64.0))?;
    315                                         }
    316                                     }
    317                                 }
    318                                 att_obj
    319                                     .ok_or_else(|| SerdeErr::missing_field(ATTESTATION_OBJECT))
    320                                     .and_then(|attestation_object| {
    321                                         client_data
    322                                             .ok_or_else(|| {
    323                                                 SerdeErr::missing_field(CLIENT_DATA_JSON)
    324                                             })
    325                                             .map(|client_data_json| {
    326                                                 AuthAttestWrapper(AuthenticatorAttestation::new(
    327                                                     client_data_json,
    328                                                     attestation_object,
    329                                                     AuthTransports::NONE,
    330                                                 ))
    331                                             })
    332                                     })
    333                             }
    334                         }
    335                         const ATTESTATION_OBJECT: &str = "attestationObject";
    336                         const CLIENT_DATA_JSON: &str = "clientDataJSON";
    337                         const AUTH_FIELDS: &[&str; 2] = &[ATTESTATION_OBJECT, CLIENT_DATA_JSON];
    338                         deserializer.deserialize_struct(
    339                             "AuthAttestWrapper",
    340                             AUTH_FIELDS,
    341                             AuthAttestVisitor,
    342                         )
    343                     }
    344                 }
    345                 let mut id = None;
    346                 let mut raw_id = None;
    347                 let mut response = None;
    348                 let mut extensions = None;
    349                 let mut typ = false;
    350                 while let Some(key) = map.next_key()? {
    351                     match key {
    352                         Field::Id => {
    353                             if id.is_some() {
    354                                 return Err(SerdeErr::duplicate_field(ID));
    355                             }
    356                             id = map.next_value::<CredentialId<Vec<u8>>>().map(Some)?;
    357                         }
    358                         Field::RawId => {
    359                             if raw_id.is_some() {
    360                                 return Err(SerdeErr::duplicate_field(RAW_ID));
    361                             }
    362                             raw_id = map.next_value::<RawId>().map(Some)?;
    363                         }
    364                         Field::Response => {
    365                             if response.is_some() {
    366                                 return Err(SerdeErr::duplicate_field(RESPONSE));
    367                             }
    368                             response = map
    369                                 .next_value::<AuthAttestWrapper>()
    370                                 .map(|attest| Some(attest.0))?;
    371                         }
    372                         Field::Extensions => {
    373                             if extensions.is_some() {
    374                                 return Err(SerdeErr::duplicate_field(EXTENSIONS));
    375                             }
    376                             extensions = map.next_value().map(Some)?;
    377                         }
    378                         Field::Type => {
    379                             if typ {
    380                                 return Err(SerdeErr::duplicate_field(TYPE));
    381                             }
    382                             typ = map.next_value::<Type>().map(|_| true)?;
    383                         }
    384                     }
    385                 }
    386                 id.ok_or_else(|| SerdeErr::missing_field(ID)).and_then(|i| {
    387                     raw_id
    388                         .ok_or_else(|| SerdeErr::missing_field(RAW_ID))
    389                         .and_then(|r| {
    390                             if i == r.0 {
    391                                 response
    392                                     .ok_or_else(|| SerdeErr::missing_field(RESPONSE))
    393                                     .and_then(|resp| {
    394                                         extensions
    395                                             .ok_or_else(|| SerdeErr::missing_field(EXTENSIONS))
    396                                             .and_then(|ext| {
    397                                                 if typ {
    398                                                     Ok(RegistrationWrapper(Registration::new(
    399                                                         resp,
    400                                                         AuthenticatorAttachment::None,
    401                                                         ext,
    402                                                     )))
    403                                                 } else {
    404                                                     Err(SerdeErr::missing_field(TYPE))
    405                                                 }
    406                                             })
    407                                     })
    408                             } else {
    409                                 Err(SerdeErr::invalid_value(
    410                                     Unexpected::Bytes(r.0.as_ref()),
    411                                     &format!("id: {:?} to match rawId", i.as_ref()).as_str(),
    412                                 ))
    413                             }
    414                         })
    415                 })
    416             }
    417         }
    418         const ID: &str = "id";
    419         const RAW_ID: &str = "rawId";
    420         const RESPONSE: &str = "response";
    421         const EXTENSIONS: &str = "extensions";
    422         const TYPE: &str = "type";
    423         const FIELDS: &[&str; 5] = &[ID, RAW_ID, RESPONSE, EXTENSIONS, TYPE];
    424         deserializer.deserialize_struct("RegistrationWrapper", FIELDS, RegistrationVisitor)
    425     }
    426 }
    427 
    428 #[derive(Deserialize)]
    429 #[serde(rename_all = "camelCase")]
    430 struct EnableWebauthnData {
    431     id: i64,
    432     name: String,
    433     device_response: RegistrationWrapper,
    434     master_password_hash: String,
    435 }
    436 
    437 #[post("/two-factor/webauthn", data = "<data>")]
    438 async fn activate_webauthn(
    439     data: Json<EnableWebauthnData>,
    440     headers: Headers,
    441     conn: DbConn,
    442 ) -> JsonResult {
    443     let data = data.into_inner();
    444     let user = headers.user;
    445     PasswordOrOtpData {
    446         master_password_hash: Some(data.master_password_hash),
    447         otp: None,
    448     }
    449     .validate(&user)?;
    450     let cred = auth::get_reg_ceremonies()
    451         .take(
    452             &CollectedClientData::from_client_data_json_relaxed::<true>(
    453                 data.device_response.0.response().client_data_json(),
    454             )
    455             .map_err(AggErr::SerdeJson)?
    456             .challenge,
    457         )
    458         .ok_or_else(|| Error::from(String::from("missing registration challenge")))?
    459         .verify(
    460             &config::get_config().rp_id,
    461             &data.device_response.0,
    462             auth::get_reg_options(),
    463         )
    464         .map_err(AggErr::RegCeremony)?;
    465     WebAuthn::new(&cred, user.uuid.clone(), data.id, data.name)?
    466         .insert(&conn)
    467         .await?;
    468     let keys = WebAuthnInfo::get_all_by_user(user.uuid.as_str(), &conn).await?;
    469     Ok(Json(json!({
    470         "enabled": !keys.is_empty(),
    471         "keys": keys,
    472         "object": "twoFactorWebAuthn"
    473     })))
    474 }
    475 
    476 #[put("/two-factor/webauthn", data = "<data>")]
    477 async fn activate_webauthn_put(
    478     data: Json<EnableWebauthnData>,
    479     headers: Headers,
    480     conn: DbConn,
    481 ) -> JsonResult {
    482     activate_webauthn(data, headers, conn).await
    483 }
    484 
    485 #[derive(Deserialize)]
    486 #[serde(rename_all = "camelCase")]
    487 struct DeleteU2FData {
    488     id: i64,
    489     master_password_hash: String,
    490 }
    491 
    492 #[delete("/two-factor/webauthn", data = "<data>")]
    493 async fn delete_webauthn(data: Json<DeleteU2FData>, headers: Headers, conn: DbConn) -> JsonResult {
    494     if !headers
    495         .user
    496         .check_valid_password(&data.master_password_hash)
    497     {
    498         err!("Invalid password");
    499     }
    500     WebAuthn::delete_by_user_uuid_and_id(&headers.user.uuid, data.id, &conn).await?;
    501     let keys = WebAuthnInfo::get_all_by_user(&headers.user.uuid, &conn).await?;
    502     Ok(Json(json!({
    503         "enabled": !keys.is_empty(),
    504         "keys": keys,
    505         "object": "twoFactorWebAuthn"
    506     })))
    507 }
    508 
    509 pub async fn generate_webauthn_login(user_uuid: &str, conn: &DbConn) -> JsonResult {
    510     let creds = WebAuthn::get_allowed_creds(user_uuid, conn).await?;
    511     let (server, client) =
    512         NonDiscoverableCredentialRequestOptions::second_factor(&config::get_config().rp_id, creds)
    513             .map_err(AggErr::SecondFactor)?
    514             .start_ceremony()
    515             .map_err(AggErr::RequestOptions)?;
    516     match auth::get_auth_ceremonies().insert_or_replace_all_expired(server) {
    517         InsertResult::Success => Ok(Json(serde_json::to_value(client)?)),
    518         InsertResult::CapacityFull => Err(Error::from(String::from(
    519             "too many active ceremonies. try again later",
    520         ))),
    521         InsertResult::Duplicate => Err(Error::from(String::from("duplicate webauthn challenge"))),
    522     }
    523 }
    524 struct AuthenticationWrapper(NonDiscoverableAuthentication16);
    525 impl<'de> Deserialize<'de> for AuthenticationWrapper {
    526     fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    527     where
    528         D: Deserializer<'de>,
    529     {
    530         struct AuthenticationVisitor;
    531         impl<'d> Visitor<'d> for AuthenticationVisitor {
    532             type Value = AuthenticationWrapper;
    533             fn expecting(&self, formatter: &mut Formatter<'_>) -> fmt::Result {
    534                 formatter.write_str("AuthenticationWrapper")
    535             }
    536             fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
    537             where
    538                 A: MapAccess<'d>,
    539             {
    540                 enum Field {
    541                     Id,
    542                     RawId,
    543                     Response,
    544                     Extensions,
    545                     Type,
    546                 }
    547                 impl<'e> Deserialize<'e> for Field {
    548                     fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    549                     where
    550                         D: Deserializer<'e>,
    551                     {
    552                         struct FieldVisitor;
    553                         impl Visitor<'_> for FieldVisitor {
    554                             type Value = Field;
    555                             fn expecting(&self, formatter: &mut Formatter<'_>) -> fmt::Result {
    556                                 write!(
    557                                     formatter,
    558                                     "'{ID}', '{RAW_ID}', '{RESPONSE}', '{EXTENSIONS}', or '{TYPE}'"
    559                                 )
    560                             }
    561                             fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
    562                             where
    563                                 E: SerdeErr,
    564                             {
    565                                 match v {
    566                                     ID => Ok(Field::Id),
    567                                     RAW_ID => Ok(Field::RawId),
    568                                     RESPONSE => Ok(Field::Response),
    569                                     EXTENSIONS => Ok(Field::Extensions),
    570                                     TYPE => Ok(Field::Type),
    571                                     _ => Err(E::unknown_field(v, FIELDS)),
    572                                 }
    573                             }
    574                         }
    575                         deserializer.deserialize_identifier(FieldVisitor)
    576                     }
    577                 }
    578                 struct Extensions;
    579                 impl<'e> Deserialize<'e> for Extensions {
    580                     fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    581                     where
    582                         D: Deserializer<'e>,
    583                     {
    584                         struct ExtensionsVisitor;
    585                         impl<'f> Visitor<'f> for ExtensionsVisitor {
    586                             type Value = Extensions;
    587                             fn expecting(&self, formatter: &mut Formatter<'_>) -> fmt::Result {
    588                                 formatter.write_str("Extensions")
    589                             }
    590                             fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
    591                             where
    592                                 A: MapAccess<'f>,
    593                             {
    594                                 struct Field;
    595                                 impl<'g> Deserialize<'g> for Field {
    596                                     fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    597                                     where
    598                                         D: Deserializer<'g>,
    599                                     {
    600                                         struct FieldVisitor;
    601                                         impl Visitor<'_> for FieldVisitor {
    602                                             type Value = Field;
    603                                             fn expecting(
    604                                                 &self,
    605                                                 formatter: &mut Formatter<'_>,
    606                                             ) -> fmt::Result
    607                                             {
    608                                                 write!(formatter, "'{APPID}'")
    609                                             }
    610                                             fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
    611                                             where
    612                                                 E: SerdeErr,
    613                                             {
    614                                                 if v == APPID {
    615                                                     Ok(Field)
    616                                                 } else {
    617                                                     Err(E::unknown_field(v, FIELDS))
    618                                                 }
    619                                             }
    620                                         }
    621                                         deserializer.deserialize_identifier(FieldVisitor)
    622                                     }
    623                                 }
    624                                 let mut appid = false;
    625                                 while map.next_key::<Field>()?.is_some() {
    626                                     if appid {
    627                                         return Err(SerdeErr::duplicate_field(APPID));
    628                                     }
    629                                     appid = map.next_value::<bool>().and_then(|v| {
    630                                         if v {
    631                                             Err(SerdeErr::invalid_value(
    632                                                 Unexpected::Bool(true),
    633                                                 &"appid to be false",
    634                                             ))
    635                                         } else {
    636                                             Ok(true)
    637                                         }
    638                                     })?;
    639                                 }
    640                                 Ok(Extensions)
    641                             }
    642                         }
    643                         const APPID: &str = "appid";
    644                         const FIELDS: &[&str; 1] = &[APPID];
    645                         deserializer.deserialize_struct(
    646                             "EmptyExtensions",
    647                             FIELDS,
    648                             ExtensionsVisitor,
    649                         )
    650                     }
    651                 }
    652                 let mut id = None;
    653                 let mut raw_id = None;
    654                 let mut response = None;
    655                 let mut extensions = false;
    656                 let mut typ = false;
    657                 while let Some(key) = map.next_key()? {
    658                     match key {
    659                         Field::Id => {
    660                             if id.is_some() {
    661                                 return Err(SerdeErr::duplicate_field(ID));
    662                             }
    663                             id = map.next_value::<CredentialId<Vec<u8>>>().map(Some)?;
    664                         }
    665                         Field::RawId => {
    666                             if raw_id.is_some() {
    667                                 return Err(SerdeErr::duplicate_field(RAW_ID));
    668                             }
    669                             raw_id = map.next_value::<CredentialId<Vec<u8>>>().map(Some)?;
    670                         }
    671                         Field::Response => {
    672                             if response.is_some() {
    673                                 return Err(SerdeErr::duplicate_field(RESPONSE));
    674                             }
    675                             response = map.next_value().map(Some)?;
    676                         }
    677                         Field::Extensions => {
    678                             if extensions {
    679                                 return Err(SerdeErr::duplicate_field(EXTENSIONS));
    680                             }
    681                             extensions = map.next_value::<Extensions>().map(|_| true)?;
    682                         }
    683                         Field::Type => {
    684                             if typ {
    685                                 return Err(SerdeErr::duplicate_field(TYPE));
    686                             }
    687                             typ = map.next_value::<Type>().map(|_| true)?;
    688                         }
    689                     }
    690                 }
    691                 id.ok_or_else(|| SerdeErr::missing_field(ID)).and_then(|i| {
    692                     raw_id
    693                         .ok_or_else(|| SerdeErr::missing_field(RAW_ID))
    694                         .and_then(|r| {
    695                             if i == r {
    696                                 response
    697                                     .ok_or_else(|| SerdeErr::missing_field(RESPONSE))
    698                                     .and_then(|resp| {
    699                                         if extensions {
    700                                             if typ {
    701                                                 Ok(AuthenticationWrapper(
    702                                                     NonDiscoverableAuthentication16::new(
    703                                                         r,
    704                                                         resp,
    705                                                         AuthenticatorAttachment::None,
    706                                                     ),
    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 = UserHandle16::from(uuid);
    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 }