Skip to main content

systemprompt_security/session/
generator.rs

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