lib_client_google_auth/
credentials.rs

1use serde::{Deserialize, Serialize};
2
3/// Google service account credentials from JSON key file.
4#[derive(Debug, Clone, Serialize, Deserialize)]
5pub struct ServiceAccountCredentials {
6    /// Service account type (should be "service_account").
7    #[serde(rename = "type")]
8    pub account_type: String,
9
10    /// Project ID.
11    pub project_id: String,
12
13    /// Private key ID.
14    pub private_key_id: String,
15
16    /// Private key in PEM format.
17    pub private_key: String,
18
19    /// Service account email.
20    pub client_email: String,
21
22    /// Client ID.
23    pub client_id: String,
24
25    /// Auth URI.
26    pub auth_uri: String,
27
28    /// Token URI.
29    pub token_uri: String,
30
31    /// Auth provider certificate URL.
32    pub auth_provider_x509_cert_url: String,
33
34    /// Client certificate URL.
35    pub client_x509_cert_url: String,
36
37    /// Universe domain.
38    #[serde(default = "default_universe_domain")]
39    pub universe_domain: String,
40}
41
42fn default_universe_domain() -> String {
43    "googleapis.com".to_string()
44}
45
46impl ServiceAccountCredentials {
47    /// Load credentials from a JSON file.
48    pub async fn from_file(path: &str) -> crate::Result<Self> {
49        let content = tokio::fs::read_to_string(path).await?;
50        Self::from_json(&content)
51    }
52
53    /// Parse credentials from JSON string.
54    pub fn from_json(json: &str) -> crate::Result<Self> {
55        let creds: Self = serde_json::from_str(json)?;
56        if creds.account_type != "service_account" {
57            return Err(crate::Error::InvalidCredentials(format!(
58                "Expected type 'service_account', got '{}'",
59                creds.account_type
60            )));
61        }
62        Ok(creds)
63    }
64}
65
66/// Unified credentials type for Google authentication.
67#[derive(Debug, Clone)]
68pub enum Credentials {
69    /// API key authentication.
70    ApiKey(String),
71
72    /// Service account credentials.
73    ServiceAccount(ServiceAccountCredentials),
74
75    /// OAuth2 credentials (client ID + secret).
76    OAuth2 {
77        client_id: String,
78        client_secret: String,
79        refresh_token: Option<String>,
80    },
81}
82
83impl Credentials {
84    /// Create API key credentials.
85    pub fn api_key(key: impl Into<String>) -> Self {
86        Self::ApiKey(key.into())
87    }
88
89    /// Create service account credentials from JSON.
90    pub fn service_account(creds: ServiceAccountCredentials) -> Self {
91        Self::ServiceAccount(creds)
92    }
93
94    /// Create OAuth2 credentials.
95    pub fn oauth2(client_id: impl Into<String>, client_secret: impl Into<String>) -> Self {
96        Self::OAuth2 {
97            client_id: client_id.into(),
98            client_secret: client_secret.into(),
99            refresh_token: None,
100        }
101    }
102
103    /// Create OAuth2 credentials with refresh token.
104    pub fn oauth2_with_refresh(
105        client_id: impl Into<String>,
106        client_secret: impl Into<String>,
107        refresh_token: impl Into<String>,
108    ) -> Self {
109        Self::OAuth2 {
110            client_id: client_id.into(),
111            client_secret: client_secret.into(),
112            refresh_token: Some(refresh_token.into()),
113        }
114    }
115}