systemprompt_agent/services/shared/
auth.rs1use crate::services::shared::error::{AgentServiceError, Result};
2use jsonwebtoken::{decode, DecodingKey, Validation};
3pub use systemprompt_models::auth::JwtClaims;
4use systemprompt_traits::AgentJwtClaims;
5
6pub struct JwtValidator {
7 decoding_key: DecodingKey,
8 validation: Validation,
9}
10
11impl std::fmt::Debug for JwtValidator {
12 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
13 f.debug_struct("JwtValidator")
14 .field("validation", &self.validation)
15 .field("decoding_key", &"<decoding_key>")
16 .finish()
17 }
18}
19
20impl JwtValidator {
21 pub fn new(secret: String) -> Self {
22 Self {
23 decoding_key: DecodingKey::from_secret(secret.as_ref()),
24 validation: Validation::default(),
25 }
26 }
27
28 pub fn validate_token(&self, token: &str) -> Result<JwtClaims> {
29 decode::<JwtClaims>(token, &self.decoding_key, &self.validation)
30 .map(|data| data.claims)
31 .map_err(|e| AgentServiceError::Authentication(format!("invalid token: {e}")))
32 }
33}
34
35pub fn extract_bearer_token(authorization_header: &str) -> Result<&str> {
36 authorization_header.strip_prefix("Bearer ").ok_or_else(|| {
37 AgentServiceError::Authentication("invalid authorization header format".to_string())
38 })
39}
40
41#[derive(Debug, Clone)]
42pub struct AgentSessionUser {
43 pub id: String,
44 pub username: String,
45 pub user_type: String,
46 pub roles: Vec<String>,
47}
48
49impl AgentSessionUser {
50 pub fn from_jwt_claims(claims: AgentJwtClaims) -> Self {
51 Self {
52 id: claims.subject,
53 username: claims.username,
54 user_type: claims.user_type,
55 roles: claims.permissions,
56 }
57 }
58}
59
60impl From<JwtClaims> for AgentSessionUser {
61 fn from(claims: JwtClaims) -> Self {
62 Self {
63 id: claims.sub.clone(),
64 username: claims.username.clone(),
65 user_type: claims.user_type.to_string(),
66 roles: claims.get_scopes(),
67 }
68 }
69}