systemprompt_traits/
jwt.rs1use std::sync::Arc;
2use systemprompt_identifiers::SessionId;
3
4pub type JwtResult<T> = Result<T, JwtProviderError>;
5
6#[derive(Debug, thiserror::Error)]
7#[non_exhaustive]
8pub enum JwtProviderError {
9 #[error("Invalid token")]
10 InvalidToken,
11
12 #[error("Token expired")]
13 TokenExpired,
14
15 #[error("Missing audience: {0}")]
16 MissingAudience(String),
17
18 #[error("Configuration error: {0}")]
19 ConfigurationError(String),
20
21 #[error("Internal error: {0}")]
22 Internal(String),
23}
24
25impl From<anyhow::Error> for JwtProviderError {
26 fn from(err: anyhow::Error) -> Self {
27 Self::Internal(err.to_string())
28 }
29}
30
31#[derive(Debug, Clone)]
32pub struct AgentJwtClaims {
33 pub subject: String,
34 pub username: String,
35 pub user_type: String,
36 pub audiences: Vec<String>,
37 pub permissions: Vec<String>,
38 pub is_admin: bool,
39 pub expires_at: i64,
40 pub issued_at: i64,
41}
42
43impl AgentJwtClaims {
44 #[must_use]
45 pub fn has_audience(&self, audience: &str) -> bool {
46 self.audiences.iter().any(|a| a == audience)
47 }
48
49 #[must_use]
50 pub fn has_permission(&self, permission: &str) -> bool {
51 self.permissions.iter().any(|p| p == permission)
52 }
53}
54
55#[derive(Debug, Clone)]
56pub struct GenerateTokenParams {
57 pub user_id: String,
58 pub username: String,
59 pub user_type: String,
60 pub permissions: Vec<String>,
61 pub audiences: Vec<String>,
62 pub session_id: SessionId,
63 pub expires_in_hours: Option<u32>,
64}
65
66impl GenerateTokenParams {
67 #[must_use]
68 pub fn new(
69 user_id: impl Into<String>,
70 username: impl Into<String>,
71 session_id: SessionId,
72 ) -> Self {
73 Self {
74 user_id: user_id.into(),
75 username: username.into(),
76 user_type: "user".to_string(),
77 permissions: Vec::new(),
78 audiences: Vec::new(),
79 session_id,
80 expires_in_hours: None,
81 }
82 }
83
84 #[must_use]
85 pub fn with_user_type(mut self, user_type: impl Into<String>) -> Self {
86 self.user_type = user_type.into();
87 self
88 }
89
90 #[must_use]
91 pub fn with_permissions(mut self, permissions: Vec<String>) -> Self {
92 self.permissions = permissions;
93 self
94 }
95
96 #[must_use]
97 pub fn with_audiences(mut self, audiences: Vec<String>) -> Self {
98 self.audiences = audiences;
99 self
100 }
101
102 #[must_use]
103 pub const fn with_expires_in_hours(mut self, hours: u32) -> Self {
104 self.expires_in_hours = Some(hours);
105 self
106 }
107}
108
109pub trait JwtValidationProvider: Send + Sync {
110 fn validate_token(&self, token: &str) -> JwtResult<AgentJwtClaims>;
111
112 fn generate_token(&self, params: GenerateTokenParams) -> JwtResult<String>;
113
114 fn generate_secure_token(&self, prefix: &str) -> String;
115}
116
117pub type DynJwtValidationProvider = Arc<dyn JwtValidationProvider>;