cratestack_cose/auth/
signer_member.rs1use std::sync::Arc;
13
14use cratestack_auth::DeviceKeyResolver;
15use cratestack_core::{
16 AuthProvider, CratestackContext, CratestackError, Credential, RequestContext, VerifiedSigner,
17};
18
19use super::signer_principal::{SignerRegistries, authenticated};
20use crate::keys::CoseVerifierResolver;
21
22#[derive(Clone)]
27pub struct CoseSignerProvider {
28 registries: SignerRegistries,
29}
30
31impl CoseSignerProvider {
32 pub fn new(devices: Arc<dyn DeviceKeyResolver>) -> Self {
35 Self {
36 registries: SignerRegistries::new(devices),
37 }
38 }
39
40 pub fn authenticate_devices(mut self, enabled: bool) -> Self {
42 self.registries = self.registries.with_devices_enabled(enabled);
43 self
44 }
45
46 pub fn with_service_keys(mut self, services: Arc<dyn CoseVerifierResolver>) -> Self {
48 self.registries = self.registries.with_services(services);
49 self
50 }
51}
52
53impl std::fmt::Debug for CoseSignerProvider {
54 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
55 f.debug_struct("CoseSignerProvider").finish_non_exhaustive()
56 }
57}
58
59impl AuthProvider for CoseSignerProvider {
60 type Error = CratestackError;
61
62 async fn authenticate(
63 &self,
64 request: &RequestContext<'_>,
65 ) -> Result<CratestackContext, CratestackError> {
66 let Some(signer) = request.extensions.get::<VerifiedSigner>() else {
67 return Ok(CratestackContext::anonymous());
68 };
69 Ok(match self.registries.vouch(signer).await? {
70 Some(kind) => authenticated(signer, kind),
71 None => CratestackContext::anonymous(),
72 })
73 }
74
75 fn credential<'r>(&self, request: &RequestContext<'r>) -> Credential<'r> {
78 if request.extensions.get::<VerifiedSigner>().is_some() {
79 Credential::Present { redact: None }
80 } else {
81 Credential::Absent
82 }
83 }
84}