Skip to main content

systemprompt_security/session/
generator.rs

1use 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 rate_limit_tier: RateLimitTier,
20}
21
22#[derive(Debug)]
23pub struct SessionGenerator {
24    jwt_secret: String,
25    issuer: String,
26}
27
28impl SessionGenerator {
29    pub fn new(jwt_secret: impl Into<String>, issuer: impl Into<String>) -> Self {
30        Self {
31            jwt_secret: jwt_secret.into(),
32            issuer: issuer.into(),
33        }
34    }
35
36    pub fn generate(&self, params: &SessionParams<'_>) -> JwtResult<SessionToken> {
37        let now = Utc::now();
38        let expiry = now + params.duration;
39
40        let claims = JwtClaims {
41            sub: params.user_id.to_string(),
42            iat: now.timestamp(),
43            exp: expiry.timestamp(),
44            iss: self.issuer.clone(),
45            aud: JwtAudience::standard(),
46            jti: uuid::Uuid::new_v4().to_string(),
47            scope: params.permissions.clone(),
48            username: params.email.to_string(),
49            email: params.email.to_string(),
50            user_type: params.user_type,
51            roles: params.roles.clone(),
52            client_id: None,
53            token_type: TokenType::Bearer,
54            auth_time: now.timestamp(),
55            session_id: Some(params.session_id.to_string()),
56            rate_limit_tier: Some(params.rate_limit_tier),
57        };
58
59        let header = Header::new(Algorithm::HS256);
60        let token = encode(
61            &header,
62            &claims,
63            &EncodingKey::from_secret(self.jwt_secret.as_bytes()),
64        )
65        .map_err(JwtError::from)?;
66
67        Ok(SessionToken::new(token))
68    }
69}