Skip to content

Commit dc0aafa

Browse files
committed
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 dc0aafa

File tree

1 file changed

+34
-5
lines changed

1 file changed

+34
-5
lines changed

src/config_default_credentials.rs

Lines changed: 34 additions & 5 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,9 +34,8 @@ 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+
let home = get_user_credentials_path()?;
38+
debug!("try to load credentials from {:?}", home);
3639

3740
let credentials = AuthorizedUserRefreshToken::from_file(&home)?;
3841
debug!(project = ?credentials.quota_project_id, client = credentials.client_id, "found user credentials");
@@ -103,5 +106,31 @@ struct RefreshRequest<'a> {
103106
refresh_token: &'a str,
104107
}
105108

109+
#[cfg(any(target_os = "linux", target_os = "macos"))]
110+
fn get_user_credentials_path() -> Result<PathBuf, Error> {
111+
let mut home = home::home_dir().ok_or(Error::Str("home directory not found"));
112+
home.push(CONFIG_DIR);
113+
home.push(USER_CREDENTIALS_PATH);
114+
Ok(home)
115+
}
116+
117+
#[cfg(target_os = "windows")]
118+
fn get_user_credentials_path() -> Result<PathBuf, Error> {
119+
let app_data = std::env::var(ENV_APPDATA)
120+
.map_err(|_| Error::Str("APPDATA environment variable not found"))?;
121+
let mut home = PathBuf::from(app_data);
122+
if !home.exists() {
123+
return Err(Error::Str("APPDATA directory not found"));
124+
}
125+
home.push(USER_CREDENTIALS_PATH);
126+
Ok(home)
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)