aboutsummaryrefslogtreecommitdiffstats
path: root/src/locked.rs
diff options
context:
space:
mode:
authorJesse Luehrs <doy@tozt.net>2021-10-27 05:38:03 -0400
committerJesse Luehrs <doy@tozt.net>2021-10-27 05:44:08 -0400
commit9acabc3a7497e3eb3536992212d34f77a649ae16 (patch)
treee1433fe36c6768704ea63443910731c4ad7fbcc1 /src/locked.rs
parenteb5e4ea7bcc3008a8d06da6884ee9713f8df0034 (diff)
downloadrbw-9acabc3a7497e3eb3536992212d34f77a649ae16.tar.gz
rbw-9acabc3a7497e3eb3536992212d34f77a649ae16.zip
start working on apikey authentication
not entirely working yet, because api keys aren't allowed to use the offline_access scope which provides access to the oauth refresh token. we will probably need to move to using stable device identifiers (should be able to generate one when the config is first created) and move this logic to a separate "rbw register" command which just does an apikey login but doesn't try to store any data, and then use the normal login flow after that
Diffstat (limited to 'src/locked.rs')
-rw-r--r--src/locked.rs79
1 files changed, 79 insertions, 0 deletions
diff --git a/src/locked.rs b/src/locked.rs
index 96bb846..4008912 100644
--- a/src/locked.rs
+++ b/src/locked.rs
@@ -1,3 +1,5 @@
+use crate::prelude::*;
+
use zeroize::Zeroize;
const LEN: usize = 4096;
@@ -51,6 +53,15 @@ impl Drop for Vec {
}
}
+impl Clone for Vec {
+ fn clone(&self) -> Self {
+ let mut new_vec = Self::new();
+ new_vec.extend(self.data().iter().copied());
+ new_vec
+ }
+}
+
+#[derive(Clone)]
pub struct Password {
password: Vec,
}
@@ -65,6 +76,7 @@ impl Password {
}
}
+#[derive(Clone)]
pub struct Keys {
keys: Vec,
}
@@ -83,6 +95,7 @@ impl Keys {
}
}
+#[derive(Clone)]
pub struct PasswordHash {
hash: Vec,
}
@@ -97,6 +110,7 @@ impl PasswordHash {
}
}
+#[derive(Clone)]
pub struct PrivateKey {
private_key: Vec,
}
@@ -110,3 +124,68 @@ impl PrivateKey {
self.private_key.data()
}
}
+
+#[derive(Clone)]
+pub struct ApiKey {
+ client_id: Password,
+ client_secret: Password,
+}
+
+impl ApiKey {
+ pub fn new(client_id: Password, client_secret: Password) -> Self {
+ Self {
+ client_id,
+ client_secret,
+ }
+ }
+
+ pub fn client_id(&self) -> &[u8] {
+ self.client_id.password()
+ }
+
+ pub fn client_secret(&self) -> &[u8] {
+ self.client_secret.password()
+ }
+}
+
+#[derive(Clone)]
+pub enum LoginCredentials {
+ Password { password: Password },
+ ApiKey { apikey: ApiKey },
+}
+
+impl LoginCredentials {
+ pub fn from_password(password: Password) -> Self {
+ Self::Password { password }
+ }
+
+ pub fn from_apikey(apikey: ApiKey) -> Self {
+ Self::ApiKey { apikey }
+ }
+
+ pub fn to_hashed(
+ self,
+ email: &str,
+ iterations: u32,
+ ) -> Result<HashedLoginCredentials> {
+ match self {
+ Self::Password { password } => {
+ let identity = crate::identity::Identity::new(
+ email, &password, iterations,
+ )?;
+ Ok(HashedLoginCredentials::Password {
+ password_hash: identity.master_password_hash,
+ })
+ }
+ Self::ApiKey { apikey } => {
+ Ok(HashedLoginCredentials::ApiKey { apikey })
+ }
+ }
+ }
+}
+
+#[derive(Clone)]
+pub enum HashedLoginCredentials {
+ Password { password_hash: PasswordHash },
+ ApiKey { apikey: ApiKey },
+}