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