pub mod google; pub mod wechat; // not yet implemented — placeholder for future WeChat integration use serde::{Deserialize, Serialize}; /// Normalized OAuth user profile from any provider. #[derive(Debug, Clone)] pub struct OAuthUserInfo { pub provider: String, pub provider_id: String, pub email: Option, pub name: Option, pub avatar_url: Option, } /// OAuth provider configuration. #[derive(Clone, Debug, Deserialize, Serialize)] pub struct OAuthConfig { pub client_id: String, pub client_secret: String, pub redirect_uri: String, } /// Build the Google authorization URL. pub fn google_auth_url(config: &OAuthConfig, state: &str) -> String { format!( "https://accounts.google.com/o/oauth2/v2/auth\ ?client_id={}\ &redirect_uri={}\ &response_type=code\ &scope=openid%20email%20profile\ &state={}\ &access_type=offline", urlencoding::encode(&config.client_id), urlencoding::encode(&config.redirect_uri), urlencoding::encode(state), ) } pub fn random_state() -> String { use rand::RngExt; let mut bytes = [0u8; 16]; rand::rng().fill(&mut bytes); bytes.iter().map(|b| format!("{:02x}", b)).collect() }