diff options
author | Jesse Luehrs <doy@tozt.net> | 2021-10-27 05:38:03 -0400 |
---|---|---|
committer | Jesse Luehrs <doy@tozt.net> | 2021-10-27 05:44:08 -0400 |
commit | 9acabc3a7497e3eb3536992212d34f77a649ae16 (patch) | |
tree | e1433fe36c6768704ea63443910731c4ad7fbcc1 /src/locked.rs | |
parent | eb5e4ea7bcc3008a8d06da6884ee9713f8df0034 (diff) | |
download | rbw-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.rs | 79 |
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 }, +} |