pub struct FileAuthBackend { /* private fields */ }Expand description
File-based authentication backend supporting bcrypt and argon2id password hashing.
New password writes use whichever algorithm was selected via
FileAuthBackend::with_algorithm (default: bcrypt). Existing hashes are
auto-detected by their PHC prefix and verified with the correct algorithm,
so a deployment can migrate at any time without invalidating existing users.
Also supports storing and fetching RFC 5802 SCRAM-SHA-256 credential bundles
via an extended tab-separated format that is fully backwards-compatible with
the original two-column username:hash format.
Implementations§
Source§impl FileAuthBackend
impl FileAuthBackend
Sourcepub async fn new(file_path: impl AsRef<Path>) -> Result<Self>
pub async fn new(file_path: impl AsRef<Path>) -> Result<Self>
Create a new file-based authentication backend using the default algorithm
(HashAlgorithm::Bcrypt, for backwards compatibility).
If the file does not exist it is created (along with any missing parent directories). An existing file is loaded into memory immediately.
Sourcepub async fn with_algorithm(
file_path: impl AsRef<Path>,
algorithm: HashAlgorithm,
) -> Result<Self>
pub async fn with_algorithm( file_path: impl AsRef<Path>, algorithm: HashAlgorithm, ) -> Result<Self>
Create a new file-based authentication backend with an explicit password-hashing algorithm for new writes.
Use this constructor when the operator’s [auth.file.hash_algorithm]
config selects argon2id. Existing bcrypt hashes in the file remain
fully functional — they verify using bcrypt regardless of this setting.
Sourcepub fn algorithm(&self) -> HashAlgorithm
pub fn algorithm(&self) -> HashAlgorithm
Returns the algorithm used for new password writes.
Sourcepub async fn set_scram_credentials(
&self,
user: &str,
credentials: ScramCredentials,
) -> Result<()>
pub async fn set_scram_credentials( &self, user: &str, credentials: ScramCredentials, ) -> Result<()>
Persist RFC 5802 SCRAM-SHA-256 credentials for user.
If the user already has a SCRAM credential bundle it is replaced. The bcrypt password hash is preserved unchanged. Returns an error if the user does not exist.
This method is intentionally on FileAuthBackend directly (not on the
AuthBackend trait) because it is part of the migration/admin tooling
surface, not the per-request hot path.
Trait Implementations§
Source§impl AuthBackend for FileAuthBackend
impl AuthBackend for FileAuthBackend
Source§fn fetch_scram_credentials<'life0, 'life1, 'async_trait>(
&'life0 self,
user: &'life1 str,
) -> Pin<Box<dyn Future<Output = Result<Option<ScramCredentials>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn fetch_scram_credentials<'life0, 'life1, 'async_trait>(
&'life0 self,
user: &'life1 str,
) -> Pin<Box<dyn Future<Output = Result<Option<ScramCredentials>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
Fetch the RFC 5802 SCRAM-SHA-256 credential bundle for user.
Returns Ok(None) if no SCRAM columns are stored (old-format entry or
user was never enrolled in SCRAM).
Source§fn authenticate<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
username: &'life1 Username,
password: &'life2 str,
) -> Pin<Box<dyn Future<Output = Result<bool>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
fn authenticate<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
username: &'life1 Username,
password: &'life2 str,
) -> Pin<Box<dyn Future<Output = Result<bool>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
Source§fn verify_identity<'life0, 'life1, 'async_trait>(
&'life0 self,
username: &'life1 Username,
) -> Pin<Box<dyn Future<Output = Result<bool>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn verify_identity<'life0, 'life1, 'async_trait>(
&'life0 self,
username: &'life1 Username,
) -> Pin<Box<dyn Future<Output = Result<bool>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
Source§fn list_users<'life0, 'async_trait>(
&'life0 self,
) -> Pin<Box<dyn Future<Output = Result<Vec<Username>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn list_users<'life0, 'async_trait>(
&'life0 self,
) -> Pin<Box<dyn Future<Output = Result<Vec<Username>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
Source§fn create_user<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
username: &'life1 Username,
password: &'life2 str,
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
fn create_user<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
username: &'life1 Username,
password: &'life2 str,
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
Source§fn delete_user<'life0, 'life1, 'async_trait>(
&'life0 self,
username: &'life1 Username,
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn delete_user<'life0, 'life1, 'async_trait>(
&'life0 self,
username: &'life1 Username,
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
Source§fn change_password<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
username: &'life1 Username,
new_password: &'life2 str,
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
fn change_password<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
username: &'life1 Username,
new_password: &'life2 str,
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
Source§fn get_scram_params<'life0, 'life1, 'async_trait>(
&'life0 self,
username: &'life1 str,
) -> Pin<Box<dyn Future<Output = Result<(Vec<u8>, u32)>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn get_scram_params<'life0, 'life1, 'async_trait>(
&'life0 self,
username: &'life1 str,
) -> Pin<Box<dyn Future<Output = Result<(Vec<u8>, u32)>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
Source§fn get_scram_stored_key<'life0, 'life1, 'async_trait>(
&'life0 self,
username: &'life1 str,
) -> Pin<Box<dyn Future<Output = Result<Vec<u8>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn get_scram_stored_key<'life0, 'life1, 'async_trait>(
&'life0 self,
username: &'life1 str,
) -> Pin<Box<dyn Future<Output = Result<Vec<u8>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
Source§fn get_scram_server_key<'life0, 'life1, 'async_trait>(
&'life0 self,
username: &'life1 str,
) -> Pin<Box<dyn Future<Output = Result<Vec<u8>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn get_scram_server_key<'life0, 'life1, 'async_trait>(
&'life0 self,
username: &'life1 str,
) -> Pin<Box<dyn Future<Output = Result<Vec<u8>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
Source§fn store_scram_credentials<'life0, 'life1, 'async_trait>(
&'life0 self,
username: &'life1 Username,
salt: Vec<u8>,
iterations: u32,
stored_key: Vec<u8>,
server_key: Vec<u8>,
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn store_scram_credentials<'life0, 'life1, 'async_trait>(
&'life0 self,
username: &'life1 Username,
salt: Vec<u8>,
iterations: u32,
stored_key: Vec<u8>,
server_key: Vec<u8>,
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
Source§fn get_apop_secret<'life0, 'life1, 'async_trait>(
&'life0 self,
_username: &'life1 Username,
) -> Pin<Box<dyn Future<Output = Result<String>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn get_apop_secret<'life0, 'life1, 'async_trait>(
&'life0 self,
_username: &'life1 Username,
) -> Pin<Box<dyn Future<Output = Result<String>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
Source§fn verify_bearer_token<'life0, 'life1, 'async_trait>(
&'life0 self,
token: &'life1 str,
) -> Pin<Box<dyn Future<Output = Result<Username>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn verify_bearer_token<'life0, 'life1, 'async_trait>(
&'life0 self,
token: &'life1 str,
) -> Pin<Box<dyn Future<Output = Result<Username>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
Auto Trait Implementations§
impl Freeze for FileAuthBackend
impl !RefUnwindSafe for FileAuthBackend
impl Send for FileAuthBackend
impl Sync for FileAuthBackend
impl Unpin for FileAuthBackend
impl UnsafeUnpin for FileAuthBackend
impl !UnwindSafe for FileAuthBackend
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
Source§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more