Skip to content

Commit 7fd3448

Browse files
committed
fix(auth): use datumctl-cli client_id for device-code grant
Our own OIDC client (datum-desktop-app, configured in datum-cloud/infra apps/datum-iam-system/.../zitadel-setup/pulumi/index.ts) has only AUTHORIZATION_CODE + REFRESH_TOKEN in its allow-listed grantTypes. Zitadel correctly rejects the device-code grant against it: unauthorized_client: grant_type "...device_code" not allowed datumctl-cli (a sibling OIDC app in the same Zitadel project) already has DEVICE_CODE in its grantTypes and has stable, well-known IDs in datumctl's source: Staging: 325848904128073754 Production: 328728232771788043 Borrow them for the --no-browser path until the planned datumctl connect plugin ships with its own properly-scoped client. Tokens are minted by Zitadel against the same project, so downstream Datum API calls don't care which client minted them. The audience verifier on id_token_verifier already allows any audience. Regular `auth login` (browser flow) is unchanged — it stays on the datum-desktop-app client.
1 parent e0ce7c0 commit 7fd3448

3 files changed

Lines changed: 20 additions & 3 deletions

File tree

Cargo.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

cli/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "datum-connect"
3-
version = "0.2.0"
3+
version = "0.2.1"
44
edition = "2024"
55

66
[dependencies]

lib/src/datum_cloud/auth.rs

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -305,15 +305,32 @@ impl StatelessClient {
305305
// typestate prevents mutating the cached `self.oidc` in place,
306306
// and the discovery the constructor performs is cheap enough to
307307
// accept the duplication.
308+
//
309+
// HACK: borrow datumctl's OIDC client_id for the device-flow
310+
// path. Our own client (the `datum-desktop-app` Zitadel app —
311+
// see datum-cloud/infra apps/datum-iam-system/.../zitadel-setup
312+
// /pulumi/index.ts) is allow-listed only for AUTHORIZATION_CODE
313+
// and REFRESH_TOKEN grants, and Zitadel responds with
314+
// `unauthorized_client: grant_type "...device_code" not allowed`
315+
// for it. `datumctl-cli` already has DEVICE_CODE in its
316+
// grantTypes, so we reuse its client_id strictly for the device
317+
// flow until the planned datumctl-connect plugin lands (which
318+
// will own its own properly-scoped OIDC client). Token issued
319+
// is still scoped to the same Zitadel project; downstream API
320+
// calls don't care which client minted it.
308321
let provider = self.env.auth_provider();
322+
let device_client_id = match self.env {
323+
ApiEnv::Staging => "325848904128073754",
324+
ApiEnv::Production => "328728232771788043",
325+
};
309326
let issuer = IssuerUrl::new(provider.issuer_url.clone())
310327
.std_context("Invalid OIDC provider issuer URL")?;
311328
let metadata = CoreProviderMetadata::discover_async(issuer, &self.http)
312329
.await
313330
.std_context("Failed to discover OIDC provider metadata")?;
314331
let oidc = CoreClient::from_provider_metadata(
315332
metadata,
316-
ClientId::new(provider.client_id),
333+
ClientId::new(device_client_id.to_string()),
317334
provider.client_secret.clone().map(ClientSecret::new),
318335
)
319336
.set_device_authorization_url(

0 commit comments

Comments
 (0)