Skip to main content

claw10_auth/
credential.rs

1use chrono::Utc;
2use uuid::Uuid;
3
4use claw10_domain::{Credential, CredentialId, CredentialKind, IdentityId};
5
6use crate::error::AuthError;
7
8pub struct CredentialService;
9
10impl CredentialService {
11    #[must_use]
12    pub fn issue_credential(
13        identity_id: IdentityId,
14        kind: CredentialKind,
15        scope: String,
16        ttl_seconds: i64,
17    ) -> Credential {
18        let now = Utc::now();
19        Credential {
20            id: CredentialId(Uuid::now_v7()),
21            identity_id,
22            kind,
23            scope,
24            issued_at: now,
25            expires_at: now + chrono::Duration::seconds(ttl_seconds),
26            revoked_at: None,
27        }
28    }
29
30    pub fn verify_credential(
31        credential: &Credential,
32        required_scope: &str,
33    ) -> Result<(), AuthError> {
34        if credential.revoked_at.is_some() {
35            return Err(AuthError::CredentialRevoked);
36        }
37
38        if Utc::now() > credential.expires_at {
39            return Err(AuthError::CredentialExpired);
40        }
41
42        if !credential.scope.contains(required_scope) {
43            return Err(AuthError::Unauthorized(format!(
44                "credential scope '{}' does not cover '{}'",
45                credential.scope, required_scope
46            )));
47        }
48
49        Ok(())
50    }
51
52    pub fn revoke_credential(credential: &mut Credential) {
53        credential.revoked_at = Some(Utc::now());
54    }
55}