Skip to main content

auth_framework/server/oauth/
oauth2_server.rs

1//! OAuth 2.0 Authorization Server Implementation
2//!
3//! This module provides a fully secure OAuth 2.0 authorization server implementation
4//! with all critical vulnerabilities addressed and proper validation.
5
6use crate::errors::{AuthError, Result};
7use crate::security::secure_utils::constant_time_compare;
8use crate::server::oauth::oauth2_enhanced_storage::{
9    EnhancedAuthorizationCode, EnhancedClientCredentials, EnhancedTokenStorage, RefreshToken,
10};
11use crate::tokens::{AuthToken, TokenManager};
12use crate::user_context::{SessionStore, UserContext};
13use serde::{Deserialize, Serialize};
14use sha2::{Digest, Sha256};
15use std::sync::Arc;
16use std::time::Duration;
17use tokio::sync::RwLock;
18
19/// OAuth 2.0 grant types
20#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
21pub enum GrantType {
22    AuthorizationCode,
23    RefreshToken,
24    ClientCredentials,
25    DeviceCode,
26    TokenExchange,
27}
28
29impl std::fmt::Display for GrantType {
30    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
31        match self {
32            GrantType::AuthorizationCode => write!(f, "authorization_code"),
33            GrantType::RefreshToken => write!(f, "refresh_token"),
34            GrantType::ClientCredentials => write!(f, "client_credentials"),
35            GrantType::DeviceCode => write!(f, "urn:ietf:params:oauth:grant-type:device_code"),
36            GrantType::TokenExchange => {
37                write!(f, "urn:ietf:params:oauth:grant-type:token-exchange")
38            }
39        }
40    }
41}
42
43impl std::str::FromStr for GrantType {
44    type Err = AuthError;
45
46    fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
47        match s {
48            "authorization_code" => Ok(Self::AuthorizationCode),
49            "refresh_token" => Ok(Self::RefreshToken),
50            "client_credentials" => Ok(Self::ClientCredentials),
51            "urn:ietf:params:oauth:grant-type:device_code" => Ok(Self::DeviceCode),
52            "urn:ietf:params:oauth:grant-type:token-exchange" => Ok(Self::TokenExchange),
53            other => Err(AuthError::auth_method(
54                "oauth2",
55                &format!("Unsupported grant type: {other}"),
56            )),
57        }
58    }
59}
60
61/// OAuth 2.0 response types
62#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
63pub enum ResponseType {
64    Code,
65    Token,
66    IdToken,
67}
68
69impl std::fmt::Display for ResponseType {
70    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
71        match self {
72            ResponseType::Code => write!(f, "code"),
73            ResponseType::Token => write!(f, "token"),
74            ResponseType::IdToken => write!(f, "id_token"),
75        }
76    }
77}
78
79impl std::str::FromStr for ResponseType {
80    type Err = AuthError;
81
82    fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
83        match s {
84            "code" => Ok(Self::Code),
85            "token" => Ok(Self::Token),
86            "id_token" => Ok(Self::IdToken),
87            other => Err(AuthError::auth_method(
88                "oauth2",
89                &format!("Unsupported response type: {other}"),
90            )),
91        }
92    }
93}
94
95/// OAuth 2.0 server configuration
96#[derive(Debug, Clone)]
97pub struct OAuth2Config {
98    /// Authorization server issuer identifier
99    pub issuer: String,
100    /// Authorization code lifetime
101    pub authorization_code_lifetime: Duration,
102    /// Access token lifetime
103    pub access_token_lifetime: Duration,
104    /// Refresh token lifetime
105    pub refresh_token_lifetime: Duration,
106    /// Device code lifetime
107    pub device_code_lifetime: Duration,
108    /// Default scope if none specified
109    pub default_scope: Option<String>,
110    /// Maximum scope lifetime
111    pub max_scope_lifetime: Duration,
112    /// Require PKCE for public clients
113    pub require_pkce: bool,
114    /// Enable token introspection
115    pub enable_introspection: bool,
116    /// Enable token revocation
117    pub enable_revocation: bool,
118}
119
120impl Default for OAuth2Config {
121    fn default() -> Self {
122        Self {
123            issuer: "https://auth.example.com".to_string(),
124            authorization_code_lifetime: Duration::from_secs(600), // 10 minutes
125            access_token_lifetime: Duration::from_secs(3600),      // 1 hour
126            refresh_token_lifetime: Duration::from_secs(86400 * 7), // 7 days
127            device_code_lifetime: Duration::from_secs(600),        // 10 minutes
128            default_scope: Some("read".to_string()),
129            max_scope_lifetime: Duration::from_secs(86400 * 30), // 30 days
130            require_pkce: true,
131            enable_introspection: true,
132            enable_revocation: true,
133        }
134    }
135}
136
137impl OAuth2Config {
138    /// Create a new builder for `OAuth2Config`, starting from defaults.
139    ///
140    /// # Example
141    ///
142    /// ```rust,no_run
143    /// use auth_framework::oauth2_server::OAuth2Config;
144    /// use std::time::Duration;
145    ///
146    /// let config = OAuth2Config::builder()
147    ///     .issuer("https://id.example.com")
148    ///     .access_token_lifetime(Duration::from_secs(1800))
149    ///     .require_pkce(true)
150    ///     .build();
151    /// ```
152    pub fn builder() -> OAuth2ConfigBuilder {
153        OAuth2ConfigBuilder::default()
154    }
155}
156
157/// A builder for [`OAuth2Config`].
158///
159/// Obtain via [`OAuth2Config::builder()`]. All fields start with secure
160/// defaults; override only what you need.
161#[derive(Debug, Clone)]
162pub struct OAuth2ConfigBuilder {
163    config: OAuth2Config,
164}
165
166impl Default for OAuth2ConfigBuilder {
167    fn default() -> Self {
168        Self {
169            config: OAuth2Config::default(),
170        }
171    }
172}
173
174impl OAuth2ConfigBuilder {
175    /// Set the authorization server issuer identifier.
176    pub fn issuer(mut self, issuer: impl Into<String>) -> Self {
177        self.config.issuer = issuer.into();
178        self
179    }
180
181    /// Set the authorization code lifetime.
182    pub fn authorization_code_lifetime(mut self, lifetime: Duration) -> Self {
183        self.config.authorization_code_lifetime = lifetime;
184        self
185    }
186
187    /// Set the access token lifetime.
188    pub fn access_token_lifetime(mut self, lifetime: Duration) -> Self {
189        self.config.access_token_lifetime = lifetime;
190        self
191    }
192
193    /// Set the refresh token lifetime.
194    pub fn refresh_token_lifetime(mut self, lifetime: Duration) -> Self {
195        self.config.refresh_token_lifetime = lifetime;
196        self
197    }
198
199    /// Set the device code lifetime.
200    pub fn device_code_lifetime(mut self, lifetime: Duration) -> Self {
201        self.config.device_code_lifetime = lifetime;
202        self
203    }
204
205    /// Set the default scope granted when none is specified.
206    pub fn default_scope(mut self, scope: impl Into<String>) -> Self {
207        self.config.default_scope = Some(scope.into());
208        self
209    }
210
211    /// Set the maximum scope lifetime.
212    pub fn max_scope_lifetime(mut self, lifetime: Duration) -> Self {
213        self.config.max_scope_lifetime = lifetime;
214        self
215    }
216
217    /// Set whether PKCE is required for public clients.
218    pub fn require_pkce(mut self, require: bool) -> Self {
219        self.config.require_pkce = require;
220        self
221    }
222
223    /// Enable or disable token introspection (RFC 7662).
224    pub fn enable_introspection(mut self, enable: bool) -> Self {
225        self.config.enable_introspection = enable;
226        self
227    }
228
229    /// Enable or disable token revocation (RFC 7009).
230    pub fn enable_revocation(mut self, enable: bool) -> Self {
231        self.config.enable_revocation = enable;
232        self
233    }
234
235    /// Build the [`OAuth2Config`].
236    pub fn build(self) -> OAuth2Config {
237        self.config
238    }
239}
240
241/// Token request structure
242///
243/// Use the convenience constructors for common grant types instead of filling
244/// every field manually:
245///
246/// ```rust,no_run
247/// use auth_framework::server::oauth::oauth2_server::TokenRequest;
248///
249/// // Authorization code exchange
250/// let req = TokenRequest::authorization_code("my_code")
251///     .client_id("client123")
252///     .client_secret("secret")
253///     .redirect_uri("https://app.example.com/cb")
254///     .code_verifier("pkce_verifier");
255///
256/// // Refresh token grant
257/// let req = TokenRequest::refresh("my_refresh_token");
258///
259/// // Client credentials grant
260/// let req = TokenRequest::client_credentials("client123", "secret");
261/// ```
262#[derive(Debug, Clone, Serialize, Deserialize, Default)]
263pub struct TokenRequest {
264    pub grant_type: String,
265    /// Client identifier. Optional here because HTTP clients may use HTTP Basic auth
266    /// (`Authorization: Basic …`) instead of embedding it in the request body.
267    #[serde(default)]
268    pub client_id: Option<String>,
269    pub client_secret: Option<String>,
270    pub code: Option<String>,
271    pub redirect_uri: Option<String>,
272    pub refresh_token: Option<String>,
273    pub scope: Option<String>,
274    pub code_verifier: Option<String>,
275    pub username: Option<String>,
276    pub password: Option<String>,
277    pub device_code: Option<String>,
278    /// RFC 8707 Resource Indicators — target resource URI(s).
279    #[serde(default)]
280    pub resource: Option<Vec<String>>,
281}
282
283impl TokenRequest {
284    /// Create a token request for the **authorization_code** grant.
285    pub fn authorization_code(code: impl Into<String>) -> Self {
286        Self {
287            grant_type: "authorization_code".to_string(),
288            code: Some(code.into()),
289            ..Default::default()
290        }
291    }
292
293    /// Create a token request for the **refresh_token** grant.
294    pub fn refresh(token: impl Into<String>) -> Self {
295        Self {
296            grant_type: "refresh_token".to_string(),
297            refresh_token: Some(token.into()),
298            ..Default::default()
299        }
300    }
301
302    /// Create a token request for the **client_credentials** grant.
303    pub fn client_credentials(
304        client_id: impl Into<String>,
305        client_secret: impl Into<String>,
306    ) -> Self {
307        Self {
308            grant_type: "client_credentials".to_string(),
309            client_id: Some(client_id.into()),
310            client_secret: Some(client_secret.into()),
311            ..Default::default()
312        }
313    }
314
315    /// Set the client ID.
316    pub fn client_id(mut self, id: impl Into<String>) -> Self {
317        self.client_id = Some(id.into());
318        self
319    }
320
321    /// Set the client secret.
322    pub fn client_secret(mut self, secret: impl Into<String>) -> Self {
323        self.client_secret = Some(secret.into());
324        self
325    }
326
327    /// Set the redirect URI.
328    pub fn redirect_uri(mut self, uri: impl Into<String>) -> Self {
329        self.redirect_uri = Some(uri.into());
330        self
331    }
332
333    /// Set the PKCE code verifier.
334    pub fn code_verifier(mut self, verifier: impl Into<String>) -> Self {
335        self.code_verifier = Some(verifier.into());
336        self
337    }
338
339    /// Set the requested scope.
340    pub fn scope(mut self, scope: impl Into<String>) -> Self {
341        self.scope = Some(scope.into());
342        self
343    }
344
345    /// Set RFC 8707 resource indicators.
346    pub fn resource(mut self, uris: Vec<String>) -> Self {
347        self.resource = Some(uris);
348        self
349    }
350}
351
352/// Token response structure
353#[derive(Debug, Clone, Serialize, Deserialize)]
354pub struct TokenResponse {
355    pub access_token: String,
356    pub token_type: String,
357    pub expires_in: u64,
358    pub refresh_token: Option<String>,
359    pub scope: Option<String>,
360    pub id_token: Option<String>,
361}
362
363/// Authorization request structure
364///
365/// Use [`AuthorizationRequest::new`] for a concise starting point:
366///
367/// ```rust,no_run
368/// use auth_framework::server::oauth::oauth2_server::AuthorizationRequest;
369///
370/// let req = AuthorizationRequest::new("client123", "code", "https://app.example.com/cb")
371///     .scope("openid profile")
372///     .state("random_state")
373///     .pkce("challenge", "S256");
374/// ```
375#[derive(Debug, Clone, Serialize, Deserialize)]
376pub struct AuthorizationRequest {
377    pub client_id: String,
378    pub response_type: String,
379    pub redirect_uri: String,
380    pub scope: Option<String>,
381    pub state: Option<String>,
382    pub code_challenge: Option<String>,
383    pub code_challenge_method: Option<String>,
384    pub nonce: Option<String>,
385    /// RFC 8707 Resource Indicators — target resource URI(s).
386    #[serde(default)]
387    pub resource: Option<Vec<String>>,
388}
389
390impl AuthorizationRequest {
391    /// Create a new authorization request with the required fields.
392    pub fn new(
393        client_id: impl Into<String>,
394        response_type: impl Into<String>,
395        redirect_uri: impl Into<String>,
396    ) -> Self {
397        Self {
398            client_id: client_id.into(),
399            response_type: response_type.into(),
400            redirect_uri: redirect_uri.into(),
401            scope: None,
402            state: None,
403            code_challenge: None,
404            code_challenge_method: None,
405            nonce: None,
406            resource: None,
407        }
408    }
409
410    /// Set the requested scope.
411    pub fn scope(mut self, scope: impl Into<String>) -> Self {
412        self.scope = Some(scope.into());
413        self
414    }
415
416    /// Set the OAuth state parameter.
417    pub fn state(mut self, state: impl Into<String>) -> Self {
418        self.state = Some(state.into());
419        self
420    }
421
422    /// Set the PKCE code challenge and method.
423    pub fn pkce(mut self, challenge: impl Into<String>, method: impl Into<String>) -> Self {
424        self.code_challenge = Some(challenge.into());
425        self.code_challenge_method = Some(method.into());
426        self
427    }
428
429    /// Set the nonce.
430    pub fn nonce(mut self, nonce: impl Into<String>) -> Self {
431        self.nonce = Some(nonce.into());
432        self
433    }
434
435    /// Set RFC 8707 resource indicators.
436    pub fn resource(mut self, uris: Vec<String>) -> Self {
437        self.resource = Some(uris);
438        self
439    }
440}
441
442/// OAuth 2.0 Authorization Server
443pub struct OAuth2Server {
444    config: OAuth2Config,
445    token_storage: Arc<RwLock<EnhancedTokenStorage>>,
446    session_store: Arc<RwLock<SessionStore>>,
447    token_manager: Arc<TokenManager>,
448}
449
450impl OAuth2Server {
451    pub async fn new(config: OAuth2Config, token_manager: Arc<TokenManager>) -> Result<Self> {
452        Ok(Self {
453            config,
454            token_storage: Arc::new(RwLock::new(EnhancedTokenStorage::new())),
455            session_store: Arc::new(RwLock::new(SessionStore::new())),
456            token_manager,
457        })
458    }
459
460    /// Register a confidential client with proper secret validation
461    pub async fn register_confidential_client(
462        &self,
463        client_id: String,
464        client_secret: &str,
465        redirect_uris: Vec<String>,
466        allowed_scopes: Vec<String>,
467        grant_types: Vec<String>,
468    ) -> Result<()> {
469        // Validate client secret strength
470        if client_secret.len() < 32 {
471            return Err(AuthError::auth_method(
472                "oauth2",
473                "Client secret must be at least 32 characters",
474            ));
475        }
476
477        let credentials = EnhancedClientCredentials::new_confidential(
478            client_id,
479            client_secret,
480            redirect_uris,
481            allowed_scopes,
482            grant_types,
483        )?;
484
485        let mut storage = self.token_storage.write().await;
486        storage.store_client_credentials(credentials).await?;
487
488        Ok(())
489    }
490
491    /// Register a public client (PKCE required)
492    pub async fn register_public_client(
493        &self,
494        client_id: String,
495        redirect_uris: Vec<String>,
496        allowed_scopes: Vec<String>,
497        grant_types: Vec<String>,
498    ) -> Result<()> {
499        let credentials = EnhancedClientCredentials::new_public(
500            client_id,
501            redirect_uris,
502            allowed_scopes,
503            grant_types,
504        );
505
506        let mut storage = self.token_storage.write().await;
507        storage.store_client_credentials(credentials).await?;
508
509        Ok(())
510    }
511
512    /// Create authorization code with proper user context
513    pub async fn create_authorization_code(
514        &self,
515        request: AuthorizationRequest,
516        user_context: UserContext,
517    ) -> Result<EnhancedAuthorizationCode> {
518        // Validate client exists and supports authorization code flow
519        let storage = self.token_storage.read().await;
520        let client = storage
521            .get_client_credentials(&request.client_id)
522            .await?
523            .ok_or_else(|| AuthError::auth_method("oauth2", "Invalid client_id"))?;
524
525        if !client.supports_grant_type("authorization_code") {
526            return Err(AuthError::auth_method(
527                "oauth2",
528                "Client does not support authorization code grant",
529            ));
530        }
531
532        if !client.redirect_uris.contains(&request.redirect_uri) {
533            return Err(AuthError::auth_method("oauth2", "Invalid redirect_uri"));
534        }
535
536        // Parse and validate scopes
537        let requested_scopes = self.parse_scopes(request.scope.as_deref())?;
538        let authorized_scopes = self.authorize_scopes(&client, &user_context, &requested_scopes)?;
539
540        // Create authorization code with proper user context
541        let auth_code = EnhancedAuthorizationCode::new(
542            client.client_id.clone(),
543            user_context.user_id.clone(), // FIXED: Use real user ID from context
544            request.redirect_uri,
545            authorized_scopes,
546            request.code_challenge,
547            request.code_challenge_method,
548            self.config.authorization_code_lifetime,
549        );
550
551        // Store authorization code
552        drop(storage);
553        let mut storage = self.token_storage.write().await;
554        storage.store_authorization_code(auth_code.clone()).await?;
555
556        Ok(auth_code)
557    }
558
559    /// Handle token exchange with comprehensive validation
560    pub async fn token_exchange(&self, request: TokenRequest) -> Result<TokenResponse> {
561        match request.grant_type.as_str() {
562            "authorization_code" => self.handle_authorization_code_grant(request).await,
563            "refresh_token" => self.handle_refresh_token_grant(request).await,
564            "client_credentials" => self.handle_client_credentials_grant(request).await,
565            _ => Err(AuthError::auth_method("oauth2", "Unsupported grant type")),
566        }
567    }
568
569    /// Handle authorization code grant with proper validation
570    async fn handle_authorization_code_grant(
571        &self,
572        request: TokenRequest,
573    ) -> Result<TokenResponse> {
574        let client_id = request
575            .client_id
576            .ok_or_else(|| AuthError::auth_method("oauth2", "client_id is required"))?;
577        // Validate client credentials FIRST
578        let storage = self.token_storage.read().await;
579        let _client = storage
580            .get_client_credentials(&client_id)
581            .await?
582            .ok_or_else(|| AuthError::auth_method("oauth2", "Invalid client_id"))?;
583
584        // CRITICAL FIX: Validate client secret properly
585        if !storage
586            .validate_client_credentials(&client_id, request.client_secret.as_deref())
587            .await?
588        {
589            return Err(AuthError::auth_method(
590                "oauth2",
591                "Invalid client credentials",
592            ));
593        }
594
595        // Get and validate authorization code
596        let code = request
597            .code
598            .ok_or_else(|| AuthError::auth_method("oauth2", "Missing authorization code"))?;
599
600        drop(storage);
601        let mut storage = self.token_storage.write().await;
602        let auth_code = storage
603            .consume_authorization_code(&code)
604            .await?
605            .ok_or_else(|| {
606                AuthError::auth_method("oauth2", "Invalid or expired authorization code")
607            })?;
608
609        // Validate code belongs to this client
610        if auth_code.client_id != client_id {
611            return Err(AuthError::auth_method(
612                "oauth2",
613                "Authorization code does not belong to client",
614            ));
615        }
616
617        // Validate PKCE if required
618        if let Some(challenge) = &auth_code.code_challenge {
619            let verifier = request
620                .code_verifier
621                .ok_or_else(|| AuthError::auth_method("oauth2", "PKCE code verifier required"))?;
622
623            if !self.validate_pkce_challenge(
624                challenge,
625                &verifier,
626                &auth_code.code_challenge_method,
627            )? {
628                return Err(AuthError::auth_method(
629                    "oauth2",
630                    "Invalid PKCE code verifier",
631                ));
632            }
633        }
634
635        // Generate tokens with proper user context
636        let access_token = self
637            .generate_access_token(
638                &auth_code.client_id,
639                Some(&auth_code.user_id), // FIXED: Use actual user ID from auth code
640                &auth_code.scopes,
641            )
642            .await?;
643
644        // Generate refresh token
645        let refresh_token = RefreshToken::new(
646            auth_code.client_id.clone(),
647            auth_code.user_id.clone(), // FIXED: Use actual user ID
648            auth_code.scopes.clone(),  // FIXED: Use authorized scopes from auth code
649            self.config.refresh_token_lifetime,
650        );
651
652        let refresh_token_id = storage.store_refresh_token(refresh_token).await?;
653
654        Ok(TokenResponse {
655            access_token: access_token.access_token,
656            token_type: "Bearer".to_string(),
657            expires_in: self.config.access_token_lifetime.as_secs(),
658            refresh_token: Some(refresh_token_id),
659            scope: Some(auth_code.scopes.join(" ")),
660            id_token: None,
661        })
662    }
663
664    /// Handle refresh token grant with proper validation
665    async fn handle_refresh_token_grant(&self, request: TokenRequest) -> Result<TokenResponse> {
666        let client_id = request
667            .client_id
668            .ok_or_else(|| AuthError::auth_method("oauth2", "client_id is required"))?;
669        // Validate client credentials
670        let storage = self.token_storage.read().await;
671        if !storage
672            .validate_client_credentials(&client_id, request.client_secret.as_deref())
673            .await?
674        {
675            return Err(AuthError::auth_method(
676                "oauth2",
677                "Invalid client credentials",
678            ));
679        }
680
681        // Get and validate refresh token
682        let refresh_token_id = request
683            .refresh_token
684            .ok_or_else(|| AuthError::auth_method("oauth2", "Missing refresh token"))?;
685
686        // CRITICAL FIX: Validate refresh token from storage
687        let stored_token = storage
688            .get_refresh_token(&refresh_token_id)
689            .await?
690            .ok_or_else(|| AuthError::auth_method("oauth2", "Invalid refresh token"))?;
691
692        if !stored_token.is_valid() {
693            return Err(AuthError::auth_method(
694                "oauth2",
695                "Refresh token is expired or revoked",
696            ));
697        }
698
699        // Validate token belongs to this client
700        if stored_token.client_id != client_id {
701            return Err(AuthError::auth_method(
702                "oauth2",
703                "Refresh token does not belong to client",
704            ));
705        }
706
707        // Parse requested scopes (must be subset of original)
708        let requested_scopes = self.parse_scopes(request.scope.as_deref())?;
709        let authorized_scopes = if requested_scopes.is_empty() {
710            stored_token.scopes.clone() // FIXED: Use original scopes from token
711        } else {
712            self.validate_scope_subset(&stored_token.scopes, &requested_scopes)?
713        };
714
715        drop(storage);
716
717        // Generate new access token
718        let access_token = self
719            .generate_access_token(
720                &stored_token.client_id,
721                Some(&stored_token.user_id), // FIXED: Use actual user ID from token
722                &authorized_scopes,
723            )
724            .await?;
725
726        // Generate new refresh token
727        let mut storage = self.token_storage.write().await;
728        storage.revoke_refresh_token(&refresh_token_id).await?; // Revoke old token
729
730        let new_refresh_token = RefreshToken::new(
731            stored_token.client_id.clone(),
732            stored_token.user_id.clone(),
733            authorized_scopes.clone(),
734            self.config.refresh_token_lifetime,
735        );
736
737        let new_refresh_token_id = storage.store_refresh_token(new_refresh_token).await?;
738
739        Ok(TokenResponse {
740            access_token: access_token.access_token,
741            token_type: "Bearer".to_string(),
742            expires_in: self.config.access_token_lifetime.as_secs(),
743            refresh_token: Some(new_refresh_token_id),
744            scope: Some(authorized_scopes.join(" ")),
745            id_token: None,
746        })
747    }
748
749    /// Handle client credentials grant with proper validation
750    async fn handle_client_credentials_grant(
751        &self,
752        request: TokenRequest,
753    ) -> Result<TokenResponse> {
754        let client_id = request
755            .client_id
756            .ok_or_else(|| AuthError::auth_method("oauth2", "client_id is required"))?;
757        // Validate client credentials
758        let storage = self.token_storage.read().await;
759        let client = storage
760            .get_client_credentials(&client_id)
761            .await?
762            .ok_or_else(|| AuthError::auth_method("oauth2", "Invalid client_id"))?;
763
764        // CRITICAL FIX: Validate client secret properly
765        if !storage
766            .validate_client_credentials(&client_id, request.client_secret.as_deref())
767            .await?
768        {
769            return Err(AuthError::auth_method(
770                "oauth2",
771                "Invalid client credentials",
772            ));
773        }
774
775        if !client.supports_grant_type("client_credentials") {
776            return Err(AuthError::auth_method(
777                "oauth2",
778                "Client does not support client credentials grant",
779            ));
780        }
781
782        // Parse and validate scopes
783        let requested_scopes = self.parse_scopes(request.scope.as_deref())?;
784        let authorized_scopes = requested_scopes
785            .iter()
786            .filter(|scope| client.has_scope(scope))
787            .cloned()
788            .collect::<Vec<_>>();
789
790        if authorized_scopes.is_empty() && !requested_scopes.is_empty() {
791            return Err(AuthError::auth_method("oauth2", "No authorized scopes"));
792        }
793
794        drop(storage);
795
796        // Generate access token (no user context for client credentials)
797        let access_token = self
798            .generate_access_token(&client_id, None, &authorized_scopes)
799            .await?;
800
801        Ok(TokenResponse {
802            access_token: access_token.access_token,
803            token_type: "Bearer".to_string(),
804            expires_in: self.config.access_token_lifetime.as_secs(),
805            refresh_token: None, // No refresh token for client credentials
806            scope: Some(authorized_scopes.join(" ")),
807            id_token: None,
808        })
809    }
810
811    /// Generate access token with proper validation
812    async fn generate_access_token(
813        &self,
814        client_id: &str,
815        user_id: Option<&str>,
816        scopes: &[String],
817    ) -> Result<AuthToken> {
818        let subject = user_id.unwrap_or(client_id);
819        let mut token = self.token_manager.create_auth_token(
820            subject,
821            crate::types::Scopes::from(
822                scopes
823                    .iter()
824                    .map(|s| s.to_string())
825                    .collect::<Vec<String>>(),
826            ),
827            "oauth2",
828            Some(self.config.access_token_lifetime),
829        )?;
830
831        // Add client_id claim
832        token.add_custom_claim(
833            "client_id".to_string(),
834            serde_json::Value::String(client_id.to_string()),
835        );
836
837        // Add user_id claim if present
838        if let Some(uid) = user_id {
839            token.add_custom_claim(
840                "user_id".to_string(),
841                serde_json::Value::String(uid.to_string()),
842            );
843        }
844
845        Ok(token)
846    }
847
848    /// Parse scopes from scope string
849    fn parse_scopes(&self, scope_str: Option<&str>) -> Result<Vec<String>> {
850        match scope_str {
851            Some(scopes) => Ok(scopes.split_whitespace().map(|s| s.to_string()).collect()),
852            None => match &self.config.default_scope {
853                Some(default) => Ok(vec![default.clone()]),
854                None => Ok(vec![]),
855            },
856        }
857    }
858
859    /// Authorize scopes based on client and user permissions
860    fn authorize_scopes(
861        &self,
862        client: &EnhancedClientCredentials,
863        user_context: &UserContext,
864        requested_scopes: &[String],
865    ) -> Result<Vec<String>> {
866        let mut authorized = Vec::new();
867
868        for scope in requested_scopes {
869            // Check if client is allowed this scope
870            if client.has_scope(scope) {
871                // Check if user has this scope (if applicable)
872                if user_context.has_scope(scope) {
873                    authorized.push(scope.clone());
874                }
875            }
876        }
877
878        if authorized.is_empty() && !requested_scopes.is_empty() {
879            return Err(AuthError::auth_method("oauth2", "No authorized scopes"));
880        }
881
882        Ok(authorized)
883    }
884
885    /// Validate that requested scopes are subset of original scopes
886    fn validate_scope_subset(
887        &self,
888        original_scopes: &[String],
889        requested_scopes: &[String],
890    ) -> Result<Vec<String>> {
891        let mut validated = Vec::new();
892
893        for scope in requested_scopes {
894            if original_scopes.contains(scope) {
895                validated.push(scope.clone());
896            } else {
897                return Err(AuthError::auth_method(
898                    "oauth2",
899                    format!("Requested scope '{}' not in original grant", scope),
900                ));
901            }
902        }
903
904        Ok(validated)
905    }
906
907    /// Validate PKCE code challenge
908    fn validate_pkce_challenge(
909        &self,
910        challenge: &str,
911        verifier: &str,
912        method: &Option<String>,
913    ) -> Result<bool> {
914        let method = method.as_deref().unwrap_or("plain");
915
916        match method {
917            "plain" => Ok(constant_time_compare(
918                challenge.as_bytes(),
919                verifier.as_bytes(),
920            )),
921            "S256" => {
922                use base64::{Engine, engine::general_purpose::URL_SAFE_NO_PAD};
923                use sha2::{Digest, Sha256};
924
925                let hash = Sha256::digest(verifier.as_bytes());
926                let encoded = URL_SAFE_NO_PAD.encode(hash);
927                Ok(constant_time_compare(
928                    challenge.as_bytes(),
929                    encoded.as_bytes(),
930                ))
931            }
932            _ => Err(AuthError::auth_method("oauth2", "Unsupported PKCE method")),
933        }
934    }
935
936    /// Revoke token (refresh token or access token)
937    pub async fn revoke_token(&self, token: &str, client_id: &str) -> Result<bool> {
938        let mut storage = self.token_storage.write().await;
939
940        // Validate client is authorized to revoke this token
941        if client_id.is_empty() {
942            return Err(AuthError::auth_method(
943                "oauth2",
944                "Client ID is required for token revocation",
945            ));
946        }
947
948        // Verify client exists by trying to get its credentials
949        if storage.get_client_credentials(client_id).await.is_err() {
950            return Err(AuthError::auth_method("oauth2", "Invalid client"));
951        }
952
953        // Try to revoke as refresh token first
954        if storage.validate_refresh_token(token).await? {
955            return storage.revoke_refresh_token(token).await;
956        }
957
958        // For access tokens, we would need to maintain a revocation list
959        // This is a simplified implementation
960        Ok(false)
961    }
962
963    /// Clean up expired tokens
964    pub async fn cleanup_expired_tokens(&self) -> Result<usize> {
965        let mut storage = self.token_storage.write().await;
966        storage.cleanup_expired_tokens().await
967    }
968
969    /// Add user credentials to the server's token storage.
970    ///
971    /// Use this to register users before calling `authenticate_user`.
972    /// In production this is typically called during server setup or via an
973    /// administrative API; in tests it provides a way to seed known users
974    /// without hardcoding them in the library itself.
975    pub async fn add_user_credentials(
976        &self,
977        creds: crate::server::oauth::oauth2_enhanced_storage::UserCredentials,
978    ) -> Result<()> {
979        let mut storage = self.token_storage.write().await;
980        storage.store_user_credentials(creds).await
981    }
982
983    /// Authenticate user and create session
984    pub async fn authenticate_user(
985        &self,
986        username: &str,
987        password: &str,
988        scopes: Vec<String>,
989    ) -> Result<UserContext> {
990        // CRITICAL SECURITY FIX: Validate credentials against storage
991        let storage = self.token_storage.read().await;
992
993        // Validate username exists and password is correct using storage
994        if !self
995            .validate_user_credentials_against_storage(&storage, username, password)
996            .await?
997        {
998            return Err(AuthError::auth_method(
999                "oauth2",
1000                "Invalid username or password",
1001            ));
1002        }
1003
1004        // Validate user is authorized for requested scopes
1005        let authorized_scopes = self
1006            .validate_user_scopes_against_storage(&storage, username, &scopes)
1007            .await?;
1008
1009        drop(storage);
1010
1011        // Create user context with validated information
1012        let user_context = UserContext::new(
1013            self.generate_user_id(username).await?,
1014            username.to_string(),
1015            self.get_user_email(username).await?,
1016        )
1017        .with_scopes(authorized_scopes);
1018
1019        let mut session_store = self.session_store.write().await;
1020        session_store.create_session(user_context.clone());
1021
1022        Ok(user_context)
1023    }
1024
1025    /// Validate user credentials against secure storage
1026    async fn validate_user_credentials_against_storage(
1027        &self,
1028        storage: &EnhancedTokenStorage,
1029        username: &str,
1030        password: &str,
1031    ) -> Result<bool> {
1032        // Minimum security requirements - but don't return early to prevent timing attacks
1033        let is_empty = username.is_empty() || password.is_empty();
1034        let is_too_short = password.len() < 8;
1035
1036        // Always perform the expensive bcrypt operation to prevent timing attacks
1037        match storage.get_user_credentials(username).await {
1038            Ok(Some(stored_credentials)) => {
1039                // Use bcrypt to verify password against hash
1040                use bcrypt::verify;
1041                match verify(password, &stored_credentials.password_hash) {
1042                    Ok(is_valid) => {
1043                        // Only return true if all conditions are met
1044                        Ok(is_valid && !is_empty && !is_too_short)
1045                    }
1046                    Err(_) => {
1047                        // Hash verification failed - fail securely
1048                        Ok(false)
1049                    }
1050                }
1051            }
1052            Ok(None) => {
1053                // User not found - still do dummy bcrypt operation to prevent timing attacks
1054                use bcrypt::verify;
1055                let _dummy_result = verify(
1056                    password,
1057                    "$2b$12$K2CtDP7zMH7VgxScmHTa/.EUm5nd9.xnZM8Cl/p9RMb5QZaJUHgBm",
1058                );
1059                Ok(false)
1060            }
1061            Err(_) => {
1062                // Storage error - still do dummy bcrypt operation to prevent timing attacks
1063                use bcrypt::verify;
1064                let _dummy_result = verify(
1065                    password,
1066                    "$2b$12$K2CtDP7zMH7VgxScmHTa/.EUm5nd9.xnZM8Cl/p9RMb5QZaJUHgBm",
1067                );
1068                Ok(false)
1069            }
1070        }
1071    }
1072
1073    /// Validate user is authorized for requested scopes using storage
1074    async fn validate_user_scopes_against_storage(
1075        &self,
1076        storage: &EnhancedTokenStorage,
1077        username: &str,
1078        requested_scopes: &[String],
1079    ) -> Result<Vec<String>> {
1080        // Get user permissions from storage
1081        let user_permissions = match storage.get_user_permissions(username).await {
1082            Ok(Some(permissions)) => permissions.scopes,
1083            Ok(None) => {
1084                return Err(AuthError::auth_method(
1085                    "oauth2",
1086                    "User not found in permission store",
1087                ));
1088            }
1089            Err(_) => {
1090                return Err(AuthError::auth_method(
1091                    "oauth2",
1092                    "Failed to retrieve user permissions",
1093                ));
1094            }
1095        };
1096
1097        let mut authorized = Vec::new();
1098        for scope in requested_scopes {
1099            if user_permissions.contains(scope) {
1100                authorized.push(scope.clone());
1101            }
1102        }
1103
1104        // If no scopes requested, give default read scope for valid users
1105        if authorized.is_empty() && !requested_scopes.is_empty() {
1106            return Err(AuthError::auth_method(
1107                "oauth2",
1108                "User not authorized for requested scopes",
1109            ));
1110        }
1111
1112        if authorized.is_empty() {
1113            // Check if user has at least read permission for default scope
1114            if user_permissions.contains(&"read".to_string()) {
1115                authorized.push("read".to_string());
1116            } else {
1117                return Err(AuthError::auth_method(
1118                    "oauth2",
1119                    "User has no authorized scopes",
1120                ));
1121            }
1122        }
1123
1124        Ok(authorized)
1125    }
1126
1127    /// Generate consistent user ID
1128    async fn generate_user_id(&self, username: &str) -> Result<String> {
1129        // In production, this would be the user's UUID from the database
1130        // For now, create a deterministic but unique ID
1131        let hash = Sha256::digest(format!("user_id_{}", username).as_bytes());
1132        let hash_str = format!("{:x}", hash);
1133        Ok(format!("user_{}", &hash_str[0..16]))
1134    }
1135
1136    /// Get user email from user store
1137    async fn get_user_email(&self, username: &str) -> Result<Option<String>> {
1138        let storage = self.token_storage.read().await;
1139        match storage.get_user_credentials(username).await {
1140            Ok(Some(creds)) => Ok(creds.email),
1141            // User not found or storage error — return None rather than a fabricated address.
1142            _ => Ok(None),
1143        }
1144    }
1145
1146    /// Get user context from session
1147    pub async fn get_user_context(&self, session_id: &str) -> Result<Option<UserContext>> {
1148        let session_store = self.session_store.read().await;
1149        Ok(session_store.get_session(session_id).cloned())
1150    }
1151
1152    /// Invalidate user session
1153    pub async fn invalidate_session(&self, session_id: &str) -> Result<bool> {
1154        let mut session_store = self.session_store.write().await;
1155        Ok(session_store.invalidate_session(session_id))
1156    }
1157}