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