systemprompt_security/session/
generator.rs1use chrono::{Duration, Utc};
2use jsonwebtoken::{Algorithm, EncodingKey, Header, encode};
3use systemprompt_identifiers::{SessionId, SessionToken, UserId};
4use systemprompt_models::auth::{
5 JwtAudience, JwtClaims, Permission, RateLimitTier, TokenType, UserType,
6};
7
8use crate::error::{JwtError, JwtResult};
9
10#[derive(Debug)]
11pub struct SessionParams<'a> {
12 pub user_id: &'a UserId,
13 pub session_id: &'a SessionId,
14 pub email: &'a str,
15 pub duration: Duration,
16 pub user_type: UserType,
17 pub permissions: Vec<Permission>,
18 pub roles: Vec<String>,
19 pub department: Option<String>,
20 pub rate_limit_tier: RateLimitTier,
21}
22
23#[derive(Debug)]
24pub struct SessionGenerator {
25 jwt_secret: String,
26 issuer: String,
27}
28
29impl SessionGenerator {
30 pub fn new(jwt_secret: impl Into<String>, issuer: impl Into<String>) -> Self {
31 Self {
32 jwt_secret: jwt_secret.into(),
33 issuer: issuer.into(),
34 }
35 }
36
37 pub fn generate(&self, params: &SessionParams<'_>) -> JwtResult<SessionToken> {
38 let now = Utc::now();
39 let expiry = now + params.duration;
40
41 let claims = JwtClaims {
42 sub: params.user_id.to_string(),
43 iat: now.timestamp(),
44 exp: expiry.timestamp(),
45 iss: self.issuer.clone(),
46 aud: JwtAudience::standard(),
47 jti: uuid::Uuid::new_v4().to_string(),
48 scope: params.permissions.clone(),
49 username: params.email.to_string(),
50 email: params.email.to_string(),
51 user_type: params.user_type,
52 roles: params.roles.clone(),
53 department: params.department.clone(),
54 client_id: None,
55 token_type: TokenType::Bearer,
56 auth_time: now.timestamp(),
57 session_id: Some(params.session_id.to_string()),
58 rate_limit_tier: Some(params.rate_limit_tier),
59 };
60
61 let header = Header::new(Algorithm::HS256);
62 let token = encode(
63 &header,
64 &claims,
65 &EncodingKey::from_secret(self.jwt_secret.as_bytes()),
66 )
67 .map_err(JwtError::from)?;
68
69 Ok(SessionToken::new(token))
70 }
71}