fix: include client_secret in device code request and improve error guidance
- Include client_secret in the initial POST to /device/code endpoint - Add check for empty GOOGLE_CLIENT_SECRET with clear error message - Improve 'Invalid client type' error to suggest creating Desktop app OAuth client - Include error code in addition to description for better diagnostics
This commit is contained in:
@@ -72,15 +72,25 @@ impl ApiClient {
|
|||||||
pub async fn authenticate(&self) -> Result<(String, String), ApiError> {
|
pub async fn authenticate(&self) -> Result<(String, String), ApiError> {
|
||||||
if self.client_id.is_empty() {
|
if self.client_id.is_empty() {
|
||||||
return Err(ApiError::Auth(
|
return Err(ApiError::Auth(
|
||||||
"GOOGLE_CLIENT_ID not set".to_string(),
|
"GOOGLE_CLIENT_ID not set. Set both GOOGLE_CLIENT_ID and GOOGLE_CLIENT_SECRET".to_string(),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
if self.client_secret.is_empty() {
|
||||||
|
return Err(ApiError::Auth(
|
||||||
|
"GOOGLE_CLIENT_SECRET not set. Set both GOOGLE_CLIENT_ID and GOOGLE_CLIENT_SECRET".to_string(),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
let params = serde_json::json!({
|
let mut params = serde_json::json!({
|
||||||
"client_id": self.client_id,
|
"client_id": self.client_id,
|
||||||
"scope": "https://www.googleapis.com/auth/tasks",
|
"scope": "https://www.googleapis.com/auth/tasks",
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Some client types require client_secret in the initial request
|
||||||
|
if !self.client_secret.is_empty() {
|
||||||
|
params["client_secret"] = serde_json::Value::String(self.client_secret.clone());
|
||||||
|
}
|
||||||
|
|
||||||
let resp = self
|
let resp = self
|
||||||
.client
|
.client
|
||||||
.post("https://oauth2.googleapis.com/device/code")
|
.post("https://oauth2.googleapis.com/device/code")
|
||||||
@@ -96,11 +106,22 @@ impl ApiClient {
|
|||||||
.map_err(|e| ApiError::Api(format!("Invalid response (status {}): {}", status, e)))?;
|
.map_err(|e| ApiError::Api(format!("Invalid response (status {}): {}", status, e)))?;
|
||||||
|
|
||||||
if !status.is_success() {
|
if !status.is_success() {
|
||||||
|
let err_code = data["error"].as_str().unwrap_or("unknown_error");
|
||||||
let err_desc = data["error_description"]
|
let err_desc = data["error_description"]
|
||||||
.as_str()
|
.as_str()
|
||||||
.or_else(|| data["error"].as_str())
|
.unwrap_or("no description");
|
||||||
.unwrap_or("unknown error");
|
|
||||||
return Err(ApiError::Api(format!("OAuth error ({}): {}", status, err_desc)));
|
let mut msg = format!("OAuth error ({}): {} - {}", status, err_code, err_desc);
|
||||||
|
|
||||||
|
// Common fixes for known errors
|
||||||
|
if err_desc.contains("Invalid client") || err_code == "invalid_client" {
|
||||||
|
msg.push_str(
|
||||||
|
". Check that you created a 'Desktop app' OAuth 2.0 Client ID in Google Cloud Console \
|
||||||
|
(not 'Web application'). Also verify that Google Tasks API is enabled.",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Err(ApiError::Api(msg));
|
||||||
}
|
}
|
||||||
|
|
||||||
let url = data["verification_url"]
|
let url = data["verification_url"]
|
||||||
|
|||||||
Reference in New Issue
Block a user