From b1f537a433c424c565a266675f2b5b4115d5fdbe Mon Sep 17 00:00:00 2001 From: Rodrigo Rodriguez Date: Thu, 23 Apr 2026 22:40:38 +0000 Subject: [PATCH] fix: Use management v1 API for Zitadel user search (PAT token compat) The v2 user search API rejects PAT tokens (returns Token.Invalid). The management v1 API accepts PAT tokens correctly. Also adds fallback for user ID field (id vs userId) in login response. --- botserver/src/directory/auth_routes.rs | 4 ++-- botserver/src/directory/client.rs | 7 ++++--- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/botserver/src/directory/auth_routes.rs b/botserver/src/directory/auth_routes.rs index 3ac8196e..09f59442 100644 --- a/botserver/src/directory/auth_routes.rs +++ b/botserver/src/directory/auth_routes.rs @@ -174,7 +174,7 @@ pub async fn login( admin_token }; - let search_url = format!("{}/v2/users", client.api_url()); + let search_url = format!("{}/management/v1/users/_search", client.api_url()); let search_body = serde_json::json!({ "queries": [{ "emailQuery": { @@ -228,7 +228,7 @@ pub async fn login( .get("result") .and_then(|r| r.as_array()) .and_then(|arr| arr.first()) - .and_then(|u| u.get("userId")) + .and_then(|u| u.get("id").or_else(|| u.get("userId"))) .and_then(|v| v.as_str()) .map(String::from); diff --git a/botserver/src/directory/client.rs b/botserver/src/directory/client.rs index a2759867..c3b15b2c 100644 --- a/botserver/src/directory/client.rs +++ b/botserver/src/directory/client.rs @@ -257,14 +257,15 @@ impl ZitadelClient { pub async fn list_users(&self, limit: u32, offset: u32) -> Result> { let token = self.get_access_token().await?; let url = format!( - "{}/v2/users?limit={}&offset={}", + "{}/management/v1/users/_search?limit={}&offset={}", self.config.api_url, limit, offset ); let response = self .http_client - .get(&url) + .post(&url) .bearer_auth(&token) + .json(&serde_json::json!({})) .send() .await .map_err(|e| anyhow!("Failed to list users: {}", e))?; @@ -290,7 +291,7 @@ impl ZitadelClient { pub async fn search_users(&self, query: &str) -> Result> { let token = self.get_access_token().await?; - let url = format!("{}/v2/users/_search", self.config.api_url); + let url = format!("{}/management/v1/users/_search", self.config.api_url); let body = serde_json::json!({ "queries": [{