systemprompt_security/jwt/
mint.rs1use chrono::{Duration, Utc};
8use jsonwebtoken::{Algorithm, Header, encode};
9use std::collections::BTreeMap;
10use systemprompt_identifiers::{ClientId, JwtToken, SessionId, UserId};
11use systemprompt_models::auth::{
12 JwtAudience, JwtClaims, Permission, RateLimitTier, TokenType, UserType,
13};
14
15use crate::error::{JwtError, JwtResult};
16use crate::keys::authority;
17
18#[derive(Debug)]
19pub struct AdminTokenParams<'a> {
20 pub user_id: &'a UserId,
21 pub session_id: &'a SessionId,
22 pub email: &'a str,
23 pub issuer: &'a str,
24 pub duration: Duration,
25 pub client_id: Option<&'a ClientId>,
26}
27
28#[derive(Copy, Clone, Debug)]
29pub struct JwtService;
30
31impl JwtService {
32 pub fn generate_admin_token(params: &AdminTokenParams<'_>) -> JwtResult<JwtToken> {
33 let now = Utc::now();
34 let expiry = now + params.duration;
35
36 let claims = JwtClaims {
37 sub: params.user_id.to_string(),
38 iat: now.timestamp(),
39 exp: expiry.timestamp(),
40 nbf: Some(now.timestamp()),
41 iss: params.issuer.to_owned(),
42 aud: JwtAudience::standard(),
43 jti: uuid::Uuid::new_v4().to_string(),
44 scope: vec![Permission::Admin],
45 username: params.email.to_owned(),
46 email: params.email.to_owned(),
47 user_type: UserType::Admin,
48 roles: vec!["admin".to_owned(), "user".to_owned()],
49 attributes: BTreeMap::new(),
50 client_id: params.client_id.cloned(),
51 token_type: TokenType::Bearer,
52 auth_time: now.timestamp(),
53 session_id: Some(params.session_id.clone()),
54 rate_limit_tier: Some(RateLimitTier::Admin),
55 plugin_id: None,
56 act: None,
57 };
58
59 let kid = authority::active_kid().map_err(|e| JwtError::Signing(e.to_string()))?;
60 let mut header = Header::new(Algorithm::RS256);
61 header.kid = Some(kid.to_owned());
62 let key = authority::encoding_key().map_err(|e| JwtError::Signing(e.to_string()))?;
63 let token = encode(&header, &claims, key).map_err(JwtError::from)?;
64
65 Ok(JwtToken::new(token))
66 }
67}