wae_authentication/jwt/
claims.rs1use chrono::{DateTime, Utc};
4use serde::{Deserialize, Serialize};
5use std::collections::HashMap;
6
7#[derive(Debug, Clone, Serialize, Deserialize)]
9pub struct JwtClaims {
10 #[serde(skip_serializing_if = "Option::is_none")]
12 pub iss: Option<String>,
13
14 #[serde(skip_serializing_if = "Option::is_none")]
16 pub aud: Option<String>,
17
18 pub sub: String,
20
21 #[serde(skip_serializing_if = "Option::is_none")]
23 pub jti: Option<String>,
24
25 pub iat: i64,
27
28 pub exp: i64,
30
31 #[serde(skip_serializing_if = "Option::is_none")]
33 pub nbf: Option<i64>,
34
35 #[serde(flatten)]
37 pub custom: HashMap<String, serde_json::Value>,
38}
39
40impl JwtClaims {
41 pub fn new(subject: impl Into<String>, expires_in_seconds: i64) -> Self {
47 let now = Utc::now().timestamp();
48 Self {
49 iss: None,
50 aud: None,
51 sub: subject.into(),
52 jti: Some(uuid::Uuid::new_v4().to_string()),
53 iat: now,
54 exp: now + expires_in_seconds,
55 nbf: None,
56 custom: HashMap::new(),
57 }
58 }
59
60 pub fn with_issuer(mut self, issuer: impl Into<String>) -> Self {
62 self.iss = Some(issuer.into());
63 self
64 }
65
66 pub fn with_audience(mut self, audience: impl Into<String>) -> Self {
68 self.aud = Some(audience.into());
69 self
70 }
71
72 pub fn with_not_before(mut self, nbf: i64) -> Self {
74 self.nbf = Some(nbf);
75 self
76 }
77
78 pub fn with_custom_claim(mut self, key: impl Into<String>, value: serde_json::Value) -> Self {
80 self.custom.insert(key.into(), value);
81 self
82 }
83
84 pub fn is_expired(&self) -> bool {
86 Utc::now().timestamp() > self.exp
87 }
88
89 pub fn is_valid_now(&self) -> bool {
91 let now = Utc::now().timestamp();
92 if self.is_expired() {
93 return false;
94 }
95 if let Some(nbf) = self.nbf {
96 if now < nbf {
97 return false;
98 }
99 }
100 true
101 }
102
103 pub fn expires_at(&self) -> DateTime<Utc> {
105 DateTime::from_timestamp(self.exp, 0).unwrap_or_default()
106 }
107
108 pub fn issued_at(&self) -> DateTime<Utc> {
110 DateTime::from_timestamp(self.iat, 0).unwrap_or_default()
111 }
112}
113
114#[derive(Debug, Clone, Serialize, Deserialize)]
116pub struct AccessTokenClaims {
117 pub user_id: String,
119
120 #[serde(skip_serializing_if = "Option::is_none")]
122 pub username: Option<String>,
123
124 #[serde(skip_serializing_if = "Vec::is_empty")]
126 pub roles: Vec<String>,
127
128 #[serde(skip_serializing_if = "Vec::is_empty")]
130 pub permissions: Vec<String>,
131
132 #[serde(skip_serializing_if = "Option::is_none")]
134 pub session_id: Option<String>,
135}
136
137impl AccessTokenClaims {
138 pub fn new(user_id: impl Into<String>) -> Self {
140 Self { user_id: user_id.into(), username: None, roles: Vec::new(), permissions: Vec::new(), session_id: None }
141 }
142
143 pub fn with_username(mut self, username: impl Into<String>) -> Self {
145 self.username = Some(username.into());
146 self
147 }
148
149 pub fn with_roles(mut self, roles: Vec<String>) -> Self {
151 self.roles = roles;
152 self
153 }
154
155 pub fn with_permissions(mut self, permissions: Vec<String>) -> Self {
157 self.permissions = permissions;
158 self
159 }
160
161 pub fn with_session_id(mut self, session_id: impl Into<String>) -> Self {
163 self.session_id = Some(session_id.into());
164 self
165 }
166}
167
168#[derive(Debug, Clone, Serialize, Deserialize)]
170pub struct RefreshTokenClaims {
171 pub user_id: String,
173
174 pub session_id: String,
176
177 pub version: u32,
179}
180
181impl RefreshTokenClaims {
182 pub fn new(user_id: impl Into<String>, session_id: impl Into<String>) -> Self {
184 Self { user_id: user_id.into(), session_id: session_id.into(), version: 0 }
185 }
186
187 pub fn with_version(mut self, version: u32) -> Self {
189 self.version = version;
190 self
191 }
192}