1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
//! An implementation of an Ephemeral (in-memory) webauthn configuration provider
//! This stores all challenges and credentials in memory - IE they are lost on
//! service restart. It's only really useful for demo-sites, testing and as an
//! example/reference implementation of the WebauthnConfig trait.

use crate::WebauthnConfig;

/// An implementation of an Ephemeral (in-memory) webauthn configuration provider
/// This stores all challenges and credentials in memory - IE they are lost on
/// service restart. It's only really useful for demo-sites, testing and as an
/// example/reference implementation of the WebauthnConfig trait.
pub struct WebauthnEphemeralConfig {
    rp_name: String,
    rp_id: String,
    rp_origin: String,
}

impl std::fmt::Debug for WebauthnEphemeralConfig {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        write!(
            f,
            "WebauthnEphemeralConfig{{ rp_name: {:?}, rp_id: {:?}, rp_origin: {:?} }}",
            self.rp_name, self.rp_id, self.rp_origin
        )
    }
}

impl WebauthnConfig for WebauthnEphemeralConfig {
    /// Returns the relying party name. See the trait documentation for more.
    fn get_relying_party_name(&self) -> String {
        self.rp_name.clone()
    }

    /// Returns the relying party id. See the trait documentation for more.
    fn get_relying_party_id(&self) -> String {
        self.rp_id.clone()
    }

    /// Retrieve the relying party origin. See the trait documentation for more.
    fn get_origin(&self) -> &String {
        &self.rp_origin
    }

    /*
    /// Persist a challenge associated to a userId. See the trait documentation for more.
    fn persist_challenge(&mut self, userid: UserId, challenge: Challenge) -> Result<(), ()> {
        self.chals.put(userid, challenge);
        Ok(())
    }

    /// Retrieve a challenge associated to a userId. See the trait documentation for more.
    fn retrieve_challenge(&mut self, userid: &UserId) -> Option<Challenge> {
        self.chals.pop(userid)
    }

    /// Assert if a credential related to a userId exists. See the trait documentation for more.
    fn does_exist_credential(&self, userid: &UserId, cred: &Credential) -> Result<bool, ()> {
        match self.creds.get(userid) {
            Some(creds) => Ok(creds.contains_key(&cred.cred_id)),
            None => Ok(false),
        }
    }

    /// Persist a credential related to a userId. See the trait documentation for more.
    fn persist_credential(&mut self, userid: UserId, cred: Credential) -> Result<(), ()> {
        match self.creds.get_mut(&userid) {
            Some(v) => {
                let cred_id = cred.cred_id.clone();
                v.insert(cred_id, cred);
            }
            None => {
                let mut t = BTreeMap::new();
                let credential_id = cred.cred_id.clone();
                t.insert(credential_id, cred);
                self.creds.insert(userid, t);
            }
        };
        Ok(())
    }

    /// Update a credentials counter. See the trait documentation for more.
    fn credential_update_counter(
        &mut self,
        userid: &UserId,
        cred: &Credential,
        counter: u32,
    ) -> Result<(), ()> {
        match self.creds.get_mut(userid) {
            Some(v) => {
                let cred_id = cred.cred_id.clone();
                let _ = v.remove(&cred_id);
                let mut c = cred.clone();
                c.counter = counter;
                v.insert(cred_id, c);
                Ok(())
            }
            None => {
                // Invalid state but not end of world ...
                Err(())
            }
        }
    }

    /// Report an invalid credential counter. See the trait documentation for more.
    fn credential_report_invalid_counter(
        &mut self,
        userid: &UserId,
        cred: &Credential,
        _counter: u32,
    ) -> Result<(), ()> {
        match self.creds.get_mut(userid) {
            Some(v) => {
                v.remove(&cred.cred_id);
                Ok(())
            }
            None => {
                // Invalid state but not end of world ...
                Err(())
            }
        }
    }

    /// Retrieve the credentials associated to a userId. See the trait documentation for more.
    fn retrieve_credentials(&self, userid: &UserId) -> Option<Vec<&Credential>> {
        match self.creds.get(userid) {
            Some(creds) => Some(creds.iter().map(|(_, v)| v).collect()),
            None => None,
        }
    }
    */
}

impl WebauthnEphemeralConfig {
    /// Create a new Webauthn Ephemeral instance. This requires a provided relying party
    /// name, origin and id. See the trait documentation for more detail on relying party
    /// name, origin and id.
    pub fn new(rp_name: &str, rp_origin: &str, rp_id: &str) -> Self {
        WebauthnEphemeralConfig {
            rp_name: rp_name.to_string(),
            rp_id: rp_id.to_string(),
            rp_origin: rp_origin.to_string(),
        }
    }
}