Skip to content

Commit 5d93e26

Browse files
authored
Load default credentials from right path on Windows (#112)
Load default credentials from right path on Windows On Windows, the default credentials file is located in the `%APPDATA%\gcloud\application_default_credentials.json`. The existing implementation was looking for credentials in `$HOME/.config/gcloud/application_default_credentials.json`, which only works on MacOS and Linux. This change creates a `get_user_credentials_path()` function that has different implementations for Linux/MacOS and Windows platforms.
1 parent b9e924f commit 5d93e26

File tree

1 file changed

+35
-6
lines changed

1 file changed

+35
-6
lines changed

src/config_default_credentials.rs

Lines changed: 35 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use std::path::PathBuf;
12
use std::sync::Arc;
23

34
use async_trait::async_trait;
@@ -14,7 +15,10 @@ use crate::{Error, TokenProvider};
1415

1516
/// A token provider that uses the default user credentials
1617
///
17-
/// Reads credentials from `.config/gcloud/application_default_credentials.json`.
18+
/// Reads credentials from `.config/gcloud/application_default_credentials.json` on Linux and MacOS
19+
/// or from `%APPDATA%/gcloud/application_default_credentials.json` on Windows.
20+
/// See [GCloud Application Default Credentials](https://cloud.google.com/docs/authentication/application-default-credentials#personal)
21+
/// for details.
1822
#[derive(Debug)]
1923
pub struct ConfigDefaultCredentials {
2024
client: HttpClient,
@@ -30,11 +34,12 @@ impl ConfigDefaultCredentials {
3034
}
3135

3236
pub(crate) async fn with_client(client: &HttpClient) -> Result<Self, Error> {
33-
debug!("try to load credentials from {}", USER_CREDENTIALS_PATH);
34-
let mut home = home::home_dir().ok_or(Error::Str("home directory not found"))?;
35-
home.push(USER_CREDENTIALS_PATH);
37+
debug!("try to load credentials from configuration");
38+
let mut config_path = config_dir()?;
39+
config_path.push(USER_CREDENTIALS_PATH);
40+
debug!(config = config_path.to_str(), "reading configuration file");
3641

37-
let credentials = AuthorizedUserRefreshToken::from_file(&home)?;
42+
let credentials = AuthorizedUserRefreshToken::from_file(&config_path)?;
3843
debug!(project = ?credentials.quota_project_id, client = credentials.client_id, "found user credentials");
3944

4045
Ok(Self {
@@ -103,5 +108,29 @@ struct RefreshRequest<'a> {
103108
refresh_token: &'a str,
104109
}
105110

111+
#[cfg(any(target_os = "linux", target_os = "macos"))]
112+
fn config_dir() -> Result<PathBuf, Error> {
113+
let mut home = home::home_dir().ok_or(Error::Str("home directory not found"))?;
114+
home.push(CONFIG_DIR);
115+
Ok(home)
116+
}
117+
118+
#[cfg(target_os = "windows")]
119+
fn config_dir() -> Result<PathBuf, Error> {
120+
let app_data = std::env::var(ENV_APPDATA)
121+
.map_err(|_| Error::Str("APPDATA environment variable not found"))?;
122+
let config_path = PathBuf::from(app_data);
123+
match config_path.exists() {
124+
true => Ok(config_path),
125+
false => Err(Error::Str("APPDATA directory not found")),
126+
}
127+
}
128+
106129
const DEFAULT_TOKEN_GCP_URI: &str = "https://accounts.google.com/o/oauth2/token";
107-
const USER_CREDENTIALS_PATH: &str = ".config/gcloud/application_default_credentials.json";
130+
const USER_CREDENTIALS_PATH: &str = "gcloud/application_default_credentials.json";
131+
132+
#[cfg(any(target_os = "linux", target_os = "macos"))]
133+
const CONFIG_DIR: &str = ".config";
134+
135+
#[cfg(target_os = "windows")]
136+
const ENV_APPDATA: &str = "APPDATA";

0 commit comments

Comments
 (0)