From 2e47d7a119774b0a5e9114d86fe0d532a42b3b5f Mon Sep 17 00:00:00 2001 From: "Kai A. Hiller" Date: Fri, 24 Jul 2026 12:59:45 +0200 Subject: [PATCH 1/3] Add client_uri config for static clients --- crates/cli/src/sync.rs | 2 ++ crates/config/src/sections/clients.rs | 14 +++++++++++ ...baf6096d3278bd3bafed9fb65c72c714e88cf.json | 25 +++++++++++++++++++ ...f91ac0b326dd751c0d374d6ef4d19f671d22e.json | 24 ------------------ crates/storage-pg/src/oauth2/client.rs | 6 ++++- crates/storage/src/oauth2/client.rs | 4 +++ 6 files changed, 50 insertions(+), 25 deletions(-) create mode 100644 crates/storage-pg/.sqlx/query-3e4b44a429aff8d45bc3c044c67baf6096d3278bd3bafed9fb65c72c714e88cf.json delete mode 100644 crates/storage-pg/.sqlx/query-da02f93d7346992a9795f12b900f91ac0b326dd751c0d374d6ef4d19f671d22e.json diff --git a/crates/cli/src/sync.rs b/crates/cli/src/sync.rs index 044a11076..93048638d 100644 --- a/crates/cli/src/sync.rs +++ b/crates/cli/src/sync.rs @@ -416,6 +416,7 @@ pub async fn config_sync( let client_secret = client.client_secret().await?; let client_name = client.client_name.as_ref(); + let client_uri = client.client_uri.as_ref(); let client_auth_method = client.client_auth_method(); let jwks = client.jwks.as_ref(); let jwks_uri = client.jwks_uri.as_ref(); @@ -429,6 +430,7 @@ pub async fn config_sync( .upsert_static( client.client_id, client_name.cloned(), + client_uri.cloned(), client_auth_method, encrypted_client_secret, jwks.cloned(), diff --git a/crates/config/src/sections/clients.rs b/crates/config/src/sections/clients.rs index a69ce0f97..1520d5315 100644 --- a/crates/config/src/sections/clients.rs +++ b/crates/config/src/sections/clients.rs @@ -72,6 +72,10 @@ pub struct ClientConfig { #[serde(skip_serializing_if = "Option::is_none")] pub client_name: Option, + /// Client URL for user-facing information about the client + #[serde(skip_serializing_if = "Option::is_none")] + pub client_uri: Option, + /// The client secret, used by the `client_secret_basic`, /// `client_secret_post` and `client_secret_jwt` authentication methods #[schemars(with = "ClientSecretRaw")] @@ -281,6 +285,8 @@ mod tests { r#" clients: - client_id: 01GFWR28C4KNE04WG3HKXB7C9R + client_name: Testing Triceratops + client_uri: https://testing.example.org client_auth_method: none redirect_uris: - https://exemple.fr/callback @@ -328,6 +334,14 @@ mod tests { config.0[0].client_id, Ulid::from_str("01GFWR28C4KNE04WG3HKXB7C9R").unwrap() ); + assert_eq!( + config.0[0].client_name, + Some("Testing Triceratops".to_string()) + ); + assert_eq!( + config.0[0].client_uri, + Some(Url::from_str("https://testing.example.org").unwrap()) + ); assert_eq!( config.0[0].redirect_uris, vec!["https://exemple.fr/callback".parse().unwrap()] diff --git a/crates/storage-pg/.sqlx/query-3e4b44a429aff8d45bc3c044c67baf6096d3278bd3bafed9fb65c72c714e88cf.json b/crates/storage-pg/.sqlx/query-3e4b44a429aff8d45bc3c044c67baf6096d3278bd3bafed9fb65c72c714e88cf.json new file mode 100644 index 000000000..4fa0b4e48 --- /dev/null +++ b/crates/storage-pg/.sqlx/query-3e4b44a429aff8d45bc3c044c67baf6096d3278bd3bafed9fb65c72c714e88cf.json @@ -0,0 +1,25 @@ +{ + "db_name": "PostgreSQL", + "query": "\n INSERT INTO oauth2_clients\n ( oauth2_client_id\n , encrypted_client_secret\n , redirect_uris\n , grant_type_authorization_code\n , grant_type_refresh_token\n , grant_type_client_credentials\n , grant_type_device_code\n , token_endpoint_auth_method\n , jwks\n , client_name\n , client_uri\n , jwks_uri\n , is_static\n )\n VALUES\n ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, TRUE)\n ON CONFLICT (oauth2_client_id)\n DO\n UPDATE SET encrypted_client_secret = EXCLUDED.encrypted_client_secret\n , redirect_uris = EXCLUDED.redirect_uris\n , grant_type_authorization_code = EXCLUDED.grant_type_authorization_code\n , grant_type_refresh_token = EXCLUDED.grant_type_refresh_token\n , grant_type_client_credentials = EXCLUDED.grant_type_client_credentials\n , grant_type_device_code = EXCLUDED.grant_type_device_code\n , token_endpoint_auth_method = EXCLUDED.token_endpoint_auth_method\n , jwks = EXCLUDED.jwks\n , client_name = EXCLUDED.client_name\n , client_uri = EXCLUDED.client_uri\n , jwks_uri = EXCLUDED.jwks_uri\n , is_static = TRUE\n ", + "describe": { + "columns": [], + "parameters": { + "Left": [ + "Uuid", + "Text", + "TextArray", + "Bool", + "Bool", + "Bool", + "Bool", + "Text", + "Jsonb", + "Text", + "Text", + "Text" + ] + }, + "nullable": [] + }, + "hash": "3e4b44a429aff8d45bc3c044c67baf6096d3278bd3bafed9fb65c72c714e88cf" +} diff --git a/crates/storage-pg/.sqlx/query-da02f93d7346992a9795f12b900f91ac0b326dd751c0d374d6ef4d19f671d22e.json b/crates/storage-pg/.sqlx/query-da02f93d7346992a9795f12b900f91ac0b326dd751c0d374d6ef4d19f671d22e.json deleted file mode 100644 index 378ca2d78..000000000 --- a/crates/storage-pg/.sqlx/query-da02f93d7346992a9795f12b900f91ac0b326dd751c0d374d6ef4d19f671d22e.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "db_name": "PostgreSQL", - "query": "\n INSERT INTO oauth2_clients\n ( oauth2_client_id\n , encrypted_client_secret\n , redirect_uris\n , grant_type_authorization_code\n , grant_type_refresh_token\n , grant_type_client_credentials\n , grant_type_device_code\n , token_endpoint_auth_method\n , jwks\n , client_name\n , jwks_uri\n , is_static\n )\n VALUES\n ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, TRUE)\n ON CONFLICT (oauth2_client_id)\n DO\n UPDATE SET encrypted_client_secret = EXCLUDED.encrypted_client_secret\n , redirect_uris = EXCLUDED.redirect_uris\n , grant_type_authorization_code = EXCLUDED.grant_type_authorization_code\n , grant_type_refresh_token = EXCLUDED.grant_type_refresh_token\n , grant_type_client_credentials = EXCLUDED.grant_type_client_credentials\n , grant_type_device_code = EXCLUDED.grant_type_device_code\n , token_endpoint_auth_method = EXCLUDED.token_endpoint_auth_method\n , jwks = EXCLUDED.jwks\n , client_name = EXCLUDED.client_name\n , jwks_uri = EXCLUDED.jwks_uri\n , is_static = TRUE\n ", - "describe": { - "columns": [], - "parameters": { - "Left": [ - "Uuid", - "Text", - "TextArray", - "Bool", - "Bool", - "Bool", - "Bool", - "Text", - "Jsonb", - "Text", - "Text" - ] - }, - "nullable": [] - }, - "hash": "da02f93d7346992a9795f12b900f91ac0b326dd751c0d374d6ef4d19f671d22e" -} diff --git a/crates/storage-pg/src/oauth2/client.rs b/crates/storage-pg/src/oauth2/client.rs index f7a0d04ad..7cc49367e 100644 --- a/crates/storage-pg/src/oauth2/client.rs +++ b/crates/storage-pg/src/oauth2/client.rs @@ -629,6 +629,7 @@ impl OAuth2ClientRepository for PgOAuth2ClientRepository<'_> { &mut self, client_id: Ulid, client_name: Option, + client_uri: Option, client_auth_method: OAuthClientAuthenticationMethod, encrypted_client_secret: Option, jwks: Option, @@ -657,11 +658,12 @@ impl OAuth2ClientRepository for PgOAuth2ClientRepository<'_> { , token_endpoint_auth_method , jwks , client_name + , client_uri , jwks_uri , is_static ) VALUES - ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, TRUE) + ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, TRUE) ON CONFLICT (oauth2_client_id) DO UPDATE SET encrypted_client_secret = EXCLUDED.encrypted_client_secret @@ -673,6 +675,7 @@ impl OAuth2ClientRepository for PgOAuth2ClientRepository<'_> { , token_endpoint_auth_method = EXCLUDED.token_endpoint_auth_method , jwks = EXCLUDED.jwks , client_name = EXCLUDED.client_name + , client_uri = EXCLUDED.client_uri , jwks_uri = EXCLUDED.jwks_uri , is_static = TRUE "#, @@ -686,6 +689,7 @@ impl OAuth2ClientRepository for PgOAuth2ClientRepository<'_> { client_auth_method, jwks_json, client_name, + client_uri.as_ref().map(Url::as_str), jwks_uri.as_ref().map(Url::as_str), ) .traced() diff --git a/crates/storage/src/oauth2/client.rs b/crates/storage/src/oauth2/client.rs index 3a2073e42..b1e6017d8 100644 --- a/crates/storage/src/oauth2/client.rs +++ b/crates/storage/src/oauth2/client.rs @@ -260,6 +260,8 @@ pub trait OAuth2ClientRepository: Send + Sync { /// # Parameters /// /// * `client_id`: The client ID + /// * `client_name`: Name of the `OAuth2` client + /// * `client_uri`: User-facing information about the client /// * `client_auth_method`: The authentication method this client uses /// * `encrypted_client_secret`: The encrypted client secret, if any /// * `jwks`: The client JWKS, if any @@ -274,6 +276,7 @@ pub trait OAuth2ClientRepository: Send + Sync { &mut self, client_id: Ulid, client_name: Option, + client_uri: Option, client_auth_method: OAuthClientAuthenticationMethod, encrypted_client_secret: Option, jwks: Option, @@ -382,6 +385,7 @@ repository_impl!(OAuth2ClientRepository: &mut self, client_id: Ulid, client_name: Option, + client_uri: Option, client_auth_method: OAuthClientAuthenticationMethod, encrypted_client_secret: Option, jwks: Option, From 02a216d0714905c649823cdebb019146c3446322 Mon Sep 17 00:00:00 2001 From: "Kai A. Hiller" Date: Fri, 24 Jul 2026 13:27:11 +0200 Subject: [PATCH 2/3] Update schema --- docs/config.schema.json | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/docs/config.schema.json b/docs/config.schema.json index f680383d5..fa3cc3b54 100644 --- a/docs/config.schema.json +++ b/docs/config.schema.json @@ -258,6 +258,14 @@ "null" ] }, + "client_uri": { + "description": "Client URL for user-facing information about the client", + "type": [ + "string", + "null" + ], + "format": "uri" + }, "client_secret_file": { "description": "Path to the file containing the client secret. The client secret is used\nby the `client_secret_basic`, `client_secret_post` and\n`client_secret_jwt` authentication methods.", "type": [ From afe299dc90a389ccc59e078610139f5f44f1b312 Mon Sep 17 00:00:00 2001 From: "Kai A. Hiller" Date: Fri, 24 Jul 2026 13:27:36 +0200 Subject: [PATCH 3/3] Fix method calls --- crates/handlers/src/admin/v1/oauth2_clients/list.rs | 1 + crates/storage-pg/src/oauth2/mod.rs | 1 + 2 files changed, 2 insertions(+) diff --git a/crates/handlers/src/admin/v1/oauth2_clients/list.rs b/crates/handlers/src/admin/v1/oauth2_clients/list.rs index 127a7cc8d..5f59222ce 100644 --- a/crates/handlers/src/admin/v1/oauth2_clients/list.rs +++ b/crates/handlers/src/admin/v1/oauth2_clients/list.rs @@ -308,6 +308,7 @@ mod tests { .upsert_static( static_id, Some("Static Client".to_owned()), + None, OAuthClientAuthenticationMethod::None, None, None, diff --git a/crates/storage-pg/src/oauth2/mod.rs b/crates/storage-pg/src/oauth2/mod.rs index 6ba0baa69..0bdaf3f4a 100644 --- a/crates/storage-pg/src/oauth2/mod.rs +++ b/crates/storage-pg/src/oauth2/mod.rs @@ -1282,6 +1282,7 @@ mod tests { .upsert_static( static_id, Some("Static client".to_owned()), + None, OAuthClientAuthenticationMethod::None, None, None,