systemprompt_models/auth/
token_authority.rs1use chrono::Duration;
15use systemprompt_identifiers::{AccessTokenId, ClientId, PluginId, SessionId};
16use systemprompt_traits::BoxedSource;
17use thiserror::Error;
18
19use super::{AuthenticatedUser, JwtAudience, JwtClaims, Permission};
20
21#[derive(Debug, Error)]
22#[non_exhaustive]
23pub enum TokenError {
24 #[error("token `kid` `{0}` does not match any known signing key")]
25 UnknownKid(String),
26
27 #[error("token signed with `{got}`; only RS256 is accepted")]
28 UnsupportedAlgorithm { got: String },
29
30 #[error("token carries no `kid` naming the active signing key")]
31 KidMismatch,
32
33 #[error("token has expired")]
34 Expired,
35
36 #[error("token signature is invalid")]
37 InvalidSignature,
38
39 #[error("token audience is not accepted")]
40 InvalidAudience,
41
42 #[error("token issuer is not this deployment")]
43 InvalidIssuer,
44
45 #[error("token is malformed: {0}")]
46 Malformed(#[source] BoxedSource),
47
48 #[error("token rejected by policy: {0}")]
49 Rejected(#[source] BoxedSource),
50
51 #[error("token lifetime of {seconds}s is outside the permitted range")]
52 InvalidLifetime { seconds: i64 },
53
54 #[error("token signing failed: {0}")]
55 Signing(#[source] BoxedSource),
56}
57
58pub type TokenResult<T> = Result<T, TokenError>;
59
60#[derive(Debug, Clone)]
61pub struct UserJwtRequest {
62 pub user: AuthenticatedUser,
63 pub session_id: SessionId,
64 pub jti: AccessTokenId,
65 pub permissions: Vec<Permission>,
66 pub audience: Vec<JwtAudience>,
67 pub ttl: Duration,
68 pub client_id: Option<ClientId>,
69 pub purpose: Option<String>,
70 pub plugin_id: Option<PluginId>,
71}
72
73pub trait TokenAuthority: Send + Sync + std::fmt::Debug {
74 fn verify_session_cookie(&self, token: &str) -> TokenResult<JwtClaims>;
75
76 fn verify_bearer(&self, token: &str, audiences: &[JwtAudience]) -> TokenResult<JwtClaims>;
77
78 fn verify_hook_token(&self, token: &str) -> TokenResult<JwtClaims>;
79
80 fn sign_claims(&self, claims: &serde_json::Value) -> TokenResult<String>;
83
84 fn mint_user_jwt(&self, req: &UserJwtRequest) -> TokenResult<String>;
85}