use std::collections::HashMap;
use async_trait::async_trait;
use arcp_core::auth::{AuthOutcome, Authenticator};
use arcp_core::error::ARCPError;
use arcp_core::messages::{AuthScheme, Capabilities, ClientIdentity, Credentials};
#[derive(Debug, Default)]
pub struct BearerAuthenticator {
tokens: HashMap<String, String>,
}
impl BearerAuthenticator {
#[must_use]
pub fn new() -> Self {
Self::default()
}
#[must_use]
pub fn with_token(mut self, token: impl Into<String>, principal: impl Into<String>) -> Self {
self.tokens.insert(token.into(), principal.into());
self
}
}
#[async_trait]
impl Authenticator for BearerAuthenticator {
fn scheme(&self) -> AuthScheme {
AuthScheme::Bearer
}
async fn authenticate(
&self,
creds: &Credentials,
_client: &ClientIdentity,
_negotiated: &Capabilities,
) -> Result<AuthOutcome, ARCPError> {
let Some(token) = &creds.token else {
return Ok(AuthOutcome::Reject {
reason: "bearer scheme requires a token".into(),
});
};
Ok(self.tokens.get(token).map_or_else(
|| AuthOutcome::Reject {
reason: "unknown bearer token".into(),
},
|principal| AuthOutcome::Accept {
principal: principal.clone(),
},
))
}
}