auth_framework/server/oauth/
oauth2.rs

1//! OAuth 2.0 Server Module
2//!
3//! This module provides a clean interface to the OAuth 2.0 server implementation,
4//! wrapping the core oauth2_server functionality with proper server integration.
5
6use crate::errors::Result;
7use crate::server::core::client_registry::{ClientConfig, ClientRegistry};
8use crate::storage::core::AuthStorage;
9use serde::{Deserialize, Serialize};
10use std::sync::Arc;
11
12/// OAuth 2.0 Server Configuration
13#[derive(Debug, Clone, Serialize, Deserialize)]
14pub struct OAuth2ServerConfig {
15    /// Server issuer URL
16    pub issuer: String,
17    /// Supported scopes
18    pub supported_scopes: Vec<String>,
19    /// Supported response types
20    pub supported_response_types: Vec<String>,
21    /// Supported grant types
22    pub supported_grant_types: Vec<String>,
23}
24
25impl Default for OAuth2ServerConfig {
26    fn default() -> Self {
27        Self {
28            issuer: "https://auth.example.com".to_string(), // Should be configured in production
29            supported_scopes: vec![
30                "openid".to_string(),
31                "profile".to_string(),
32                "email".to_string(),
33                "address".to_string(),
34                "phone".to_string(),
35                "offline_access".to_string(),
36            ],
37            supported_response_types: vec![
38                "code".to_string(),
39                "token".to_string(),
40                "id_token".to_string(),
41                "code token".to_string(),
42                "code id_token".to_string(),
43                "token id_token".to_string(),
44                "code token id_token".to_string(),
45            ],
46            supported_grant_types: vec![
47                "authorization_code".to_string(),
48                "implicit".to_string(),
49                "password".to_string(),
50                "client_credentials".to_string(),
51                "refresh_token".to_string(),
52                "urn:ietf:params:oauth:grant-type:device_code".to_string(),
53                "urn:ietf:params:oauth:grant-type:token-exchange".to_string(),
54            ],
55        }
56    }
57}
58
59/// OAuth 2.0 Server with integrated client registry
60#[derive(Clone)]
61pub struct OAuth2Server {
62    /// Server configuration
63    config: OAuth2ServerConfig,
64    /// Client registry for managing OAuth clients
65    client_registry: Arc<ClientRegistry>,
66}
67
68impl OAuth2Server {
69    /// Create a new OAuth 2.0 server
70    pub async fn new(storage: Arc<dyn AuthStorage>) -> Result<Self> {
71        let client_registry = Arc::new(ClientRegistry::new(storage).await?);
72        let config = OAuth2ServerConfig::default();
73
74        Ok(Self {
75            config,
76            client_registry,
77        })
78    }
79
80    /// Create a new OAuth 2.0 server with custom configuration
81    pub async fn new_with_config(
82        storage: Arc<dyn AuthStorage>,
83        config: OAuth2ServerConfig,
84    ) -> Result<Self> {
85        let client_registry = Arc::new(ClientRegistry::new(storage).await?);
86
87        Ok(Self {
88            config,
89            client_registry,
90        })
91    }
92
93    /// Register a new OAuth 2.0 client
94    pub async fn register_client(&self, config: ClientConfig) -> Result<ClientConfig> {
95        self.client_registry.register_client(config).await
96    }
97
98    /// Get a client by ID
99    pub async fn get_client(&self, client_id: &str) -> Result<Option<ClientConfig>> {
100        self.client_registry.get_client(client_id).await
101    }
102
103    /// Update a client configuration
104    pub async fn update_client(&self, client_id: &str, config: ClientConfig) -> Result<()> {
105        self.client_registry.update_client(client_id, config).await
106    }
107
108    /// Delete a client
109    pub async fn delete_client(&self, client_id: &str) -> Result<()> {
110        self.client_registry.delete_client(client_id).await
111    }
112
113    /// Get server configuration for discovery
114    pub async fn get_server_configuration(&self) -> Result<serde_json::Value> {
115        // OAuth 2.0 Authorization Server Metadata (RFC 8414)
116        // Use configured issuer instead of hardcoded value
117        let issuer = &self.config.issuer;
118        let config = serde_json::json!({
119            "issuer": issuer,
120            "authorization_endpoint": format!("{}/oauth/authorize", issuer),
121            "token_endpoint": format!("{}/oauth/token", issuer),
122            "scopes_supported": self.config.supported_scopes,
123            "response_types_supported": self.config.supported_response_types,
124            "grant_types_supported": self.config.supported_grant_types,
125            "revocation_endpoint": format!("{}/oauth/revoke", issuer),
126            "introspection_endpoint": format!("{}/oauth/introspect", issuer)
127        });
128
129        Ok(config)
130    }
131}
132
133#[cfg(test)]
134mod tests {
135    use super::*;
136    use crate::server::core::client_registry::{ClientConfig, ClientType};
137    use crate::storage::memory::InMemoryStorage;
138
139    #[tokio::test]
140    async fn test_oauth2_server_creation() {
141        let storage = Arc::new(InMemoryStorage::new());
142        let server = OAuth2Server::new(storage).await.unwrap();
143
144        // Test client registration
145        let client_config = ClientConfig {
146            client_id: "test_client".to_string(),
147            client_type: ClientType::Public,
148            redirect_uris: vec!["https://example.com/callback".to_string()],
149            ..Default::default()
150        };
151
152        let registered_client = server.register_client(client_config).await.unwrap();
153        assert_eq!(registered_client.client_id, "test_client");
154
155        // Test client retrieval
156        let retrieved_client = server.get_client("test_client").await.unwrap().unwrap();
157        assert_eq!(retrieved_client.client_id, "test_client");
158    }
159}
160
161