1use crate::errors::Result;
4use serde::{Deserialize, Serialize};
5use std::collections::HashMap;
6use std::time::SystemTime;
7use uuid::Uuid;
8
9#[derive(Debug, Clone, Serialize, Deserialize)]
11pub struct RefreshToken {
12 pub token_id: String,
13 pub client_id: String,
14 pub user_id: String,
15 pub scopes: Vec<String>,
16 pub issued_at: SystemTime,
17 pub expires_at: SystemTime,
18 pub is_revoked: bool,
19}
20
21impl RefreshToken {
22 pub fn new(
23 client_id: String,
24 user_id: String,
25 scopes: Vec<String>,
26 lifetime: std::time::Duration,
27 ) -> Self {
28 let now = SystemTime::now();
29 Self {
30 token_id: Uuid::new_v4().to_string(),
31 client_id,
32 user_id,
33 scopes,
34 issued_at: now,
35 expires_at: now + lifetime,
36 is_revoked: false,
37 }
38 }
39
40 pub fn is_expired(&self) -> bool {
41 SystemTime::now() > self.expires_at
42 }
43
44 pub fn is_valid(&self) -> bool {
45 !self.is_revoked && !self.is_expired()
46 }
47
48 pub fn revoke(&mut self) {
49 self.is_revoked = true;
50 }
51}
52
53#[derive(Debug, Clone, Serialize, Deserialize)]
55pub struct EnhancedAuthorizationCode {
56 pub code: String,
57 pub client_id: String,
58 pub user_id: String,
59 pub redirect_uri: String,
60 pub scopes: Vec<String>,
61 pub code_challenge: Option<String>,
62 pub code_challenge_method: Option<String>,
63 pub issued_at: SystemTime,
64 pub expires_at: SystemTime,
65 pub is_used: bool,
66}
67
68impl EnhancedAuthorizationCode {
69 pub fn new(
70 client_id: String,
71 user_id: String,
72 redirect_uri: String,
73 scopes: Vec<String>,
74 code_challenge: Option<String>,
75 code_challenge_method: Option<String>,
76 lifetime: std::time::Duration,
77 ) -> Self {
78 let now = SystemTime::now();
79 Self {
80 code: Uuid::new_v4().to_string(),
81 client_id,
82 user_id,
83 redirect_uri,
84 scopes,
85 code_challenge,
86 code_challenge_method,
87 issued_at: now,
88 expires_at: now + lifetime,
89 is_used: false,
90 }
91 }
92
93 pub fn is_expired(&self) -> bool {
94 SystemTime::now() > self.expires_at
95 }
96
97 pub fn is_valid(&self) -> bool {
98 !self.is_used && !self.is_expired()
99 }
100
101 pub fn mark_used(&mut self) {
102 self.is_used = true;
103 }
104}
105
106#[derive(Debug, Clone, Serialize, Deserialize)]
108pub struct EnhancedClientCredentials {
109 pub client_id: String,
110 pub client_secret_hash: String,
111 pub client_type: ClientType,
112 pub redirect_uris: Vec<String>,
113 pub allowed_scopes: Vec<String>,
114 pub grant_types: Vec<String>,
115 pub created_at: SystemTime,
116 pub is_active: bool,
117}
118
119#[derive(Debug, Clone, Serialize, Deserialize)]
120pub enum ClientType {
121 Confidential,
122 Public,
123}
124
125impl EnhancedClientCredentials {
126 pub fn new_confidential(
127 client_id: String,
128 client_secret: &str,
129 redirect_uris: Vec<String>,
130 allowed_scopes: Vec<String>,
131 grant_types: Vec<String>,
132 ) -> Result<Self> {
133 use crate::security::secure_utils::hash_password;
134
135 Ok(Self {
136 client_id,
137 client_secret_hash: hash_password(client_secret)?,
138 client_type: ClientType::Confidential,
139 redirect_uris,
140 allowed_scopes,
141 grant_types,
142 created_at: SystemTime::now(),
143 is_active: true,
144 })
145 }
146
147 pub fn new_public(
148 client_id: String,
149 redirect_uris: Vec<String>,
150 allowed_scopes: Vec<String>,
151 grant_types: Vec<String>,
152 ) -> Self {
153 Self {
154 client_id,
155 client_secret_hash: String::new(), client_type: ClientType::Public,
157 redirect_uris,
158 allowed_scopes,
159 grant_types,
160 created_at: SystemTime::now(),
161 is_active: true,
162 }
163 }
164
165 pub fn validate_secret(&self, provided_secret: &str) -> Result<bool> {
166 match self.client_type {
167 ClientType::Public => Ok(true), ClientType::Confidential => {
169 use crate::security::secure_utils::verify_password;
170 verify_password(provided_secret, &self.client_secret_hash)
171 }
172 }
173 }
174
175 pub fn requires_secret(&self) -> bool {
176 matches!(self.client_type, ClientType::Confidential)
177 }
178
179 pub fn has_scope(&self, scope: &str) -> bool {
180 self.allowed_scopes.contains(&scope.to_string())
181 }
182
183 pub fn supports_grant_type(&self, grant_type: &str) -> bool {
184 self.grant_types.contains(&grant_type.to_string())
185 }
186}
187
188#[derive(Debug, Clone)]
190pub struct EnhancedTokenStorage {
191 refresh_tokens: HashMap<String, RefreshToken>,
192 authorization_codes: HashMap<String, EnhancedAuthorizationCode>,
193 client_credentials: HashMap<String, EnhancedClientCredentials>,
194}
195
196impl EnhancedTokenStorage {
197 pub fn new() -> Self {
198 Self {
199 refresh_tokens: HashMap::new(),
200 authorization_codes: HashMap::new(),
201 client_credentials: HashMap::new(),
202 }
203 }
204
205 pub async fn store_refresh_token(&mut self, token: RefreshToken) -> Result<String> {
207 let token_id = token.token_id.clone();
208 self.refresh_tokens.insert(token_id.clone(), token);
209 Ok(token_id)
210 }
211
212 pub async fn get_refresh_token(&self, token_id: &str) -> Result<Option<RefreshToken>> {
213 Ok(self.refresh_tokens.get(token_id).cloned())
214 }
215
216 pub async fn validate_refresh_token(&self, token_id: &str) -> Result<bool> {
217 match self.refresh_tokens.get(token_id) {
218 Some(token) => Ok(token.is_valid()),
219 None => Ok(false),
220 }
221 }
222
223 pub async fn revoke_refresh_token(&mut self, token_id: &str) -> Result<bool> {
224 match self.refresh_tokens.get_mut(token_id) {
225 Some(token) => {
226 token.revoke();
227 Ok(true)
228 }
229 None => Ok(false),
230 }
231 }
232
233 pub async fn store_authorization_code(
235 &mut self,
236 code: EnhancedAuthorizationCode,
237 ) -> Result<String> {
238 let code_value = code.code.clone();
239 self.authorization_codes.insert(code_value.clone(), code);
240 Ok(code_value)
241 }
242
243 pub async fn get_authorization_code(
244 &self,
245 code: &str,
246 ) -> Result<Option<EnhancedAuthorizationCode>> {
247 Ok(self.authorization_codes.get(code).cloned())
248 }
249
250 pub async fn consume_authorization_code(
251 &mut self,
252 code: &str,
253 ) -> Result<Option<EnhancedAuthorizationCode>> {
254 match self.authorization_codes.get_mut(code) {
255 Some(auth_code) if auth_code.is_valid() => {
256 auth_code.mark_used();
257 Ok(Some(auth_code.clone()))
258 }
259 _ => Ok(None),
260 }
261 }
262
263 pub async fn store_client_credentials(
265 &mut self,
266 credentials: EnhancedClientCredentials,
267 ) -> Result<()> {
268 let client_id = credentials.client_id.clone();
269 self.client_credentials.insert(client_id, credentials);
270 Ok(())
271 }
272
273 pub async fn get_client_credentials(
274 &self,
275 client_id: &str,
276 ) -> Result<Option<EnhancedClientCredentials>> {
277 Ok(self.client_credentials.get(client_id).cloned())
278 }
279
280 pub async fn validate_client_credentials(
281 &self,
282 client_id: &str,
283 client_secret: Option<&str>,
284 ) -> Result<bool> {
285 match self.client_credentials.get(client_id) {
286 Some(credentials) if credentials.is_active => {
287 if credentials.requires_secret() {
288 match client_secret {
289 Some(secret) => credentials.validate_secret(secret),
290 None => Ok(false), }
292 } else {
293 Ok(true) }
295 }
296 _ => Ok(false), }
298 }
299
300 pub async fn cleanup_expired_tokens(&mut self) -> Result<usize> {
302 let initial_count = self.refresh_tokens.len() + self.authorization_codes.len();
303
304 self.refresh_tokens.retain(|_, token| token.is_valid());
306
307 self.authorization_codes.retain(|_, code| code.is_valid());
309
310 let final_count = self.refresh_tokens.len() + self.authorization_codes.len();
311 Ok(initial_count - final_count)
312 }
313
314 pub async fn get_user_credentials(&self, username: &str) -> Result<Option<UserCredentials>> {
318 let demo_users = [
321 (
322 "admin",
323 "$2b$12$UfM9FwL8dbLOFTOmL8kAVOUe8.mFYGsqtaEjpMrS6yOGhN6SHL6me", vec!["read", "write", "admin", "delete"],
325 ),
326 (
327 "user",
328 "$2b$12$3Jb05MyZ7QDS81DJkt3QLeyR9z.S9yQqULr42kZ5F5crUYbwJaXdW", vec!["read", "write"],
330 ),
331 (
332 "test",
333 "$2b$12$bM6NV4EQdo8kJHUhhZGpIuIsalt4eD9J8co0KyO6pzEPX0ClONwTy", vec!["read"],
335 ),
336 ];
337
338 for (demo_user, password_hash, demo_scopes) in &demo_users {
339 if username == *demo_user {
340 return Ok(Some(UserCredentials {
341 username: username.to_string(),
342 password_hash: password_hash.to_string(),
343 scopes: demo_scopes.iter().map(|s| s.to_string()).collect(),
344 is_active: true,
345 }));
346 }
347 }
348
349 Ok(None)
350 }
351
352 pub async fn get_user_permissions(&self, username: &str) -> Result<Option<UserPermissions>> {
354 if let Some(credentials) = self.get_user_credentials(username).await? {
356 Ok(Some(UserPermissions {
357 username: credentials.username,
358 scopes: credentials.scopes,
359 is_active: credentials.is_active,
360 }))
361 } else {
362 Ok(None)
363 }
364 }
365}
366
367#[derive(Debug, Clone, Serialize, Deserialize)]
369pub struct UserCredentials {
370 pub username: String,
371 pub password_hash: String, pub scopes: Vec<String>,
373 pub is_active: bool,
374}
375
376#[derive(Debug, Clone, Serialize, Deserialize)]
378pub struct UserPermissions {
379 pub username: String,
380 pub scopes: Vec<String>,
381 pub is_active: bool,
382}
383
384impl Default for EnhancedTokenStorage {
385 fn default() -> Self {
386 Self::new()
387 }
388}
389
390