Skip to content

Commit 6281288

Browse files
author
Olivier Gintrand
committed
fix(admin): preserve OAuth client_secret when editing gateways and A2A agents
When editing a gateway or A2A agent via the admin UI, the client_secret field was set to empty string in the edit form (unlike all other secret fields which use the masked placeholder). The backend then received an empty value and silently dropped the client_secret key from oauth_config, causing the existing encrypted secret to be lost on save. This fix applies two layers of defense: Backend (admin.py): - Gateway and A2A agent edit handlers now send the masked placeholder value when client_secret is empty/masked, so the service layer's protect_oauth_config_for_storage() preserves the existing encrypted secret from the database. Frontend (gateways.js, a2aAgents.js, servers.js): - Edit forms now show MASKED_AUTH_VALUE when a client_secret exists, consistent with how bearer tokens, passwords, and other secrets are handled in the UI. Signed-off-by: Olivier Gintrand <olivier.gintrand@forterro.com>
1 parent c04f65e commit 6281288

File tree

4 files changed

+23
-6
lines changed

4 files changed

+23
-6
lines changed

mcpgateway/admin.py

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12394,10 +12394,13 @@ async def admin_edit_gateway(
1239412394
oauth_config["redirect_uri"] = oauth_redirect_uri
1239512395
if oauth_client_id:
1239612396
oauth_config["client_id"] = oauth_client_id
12397-
if oauth_client_secret:
12398-
# Encrypt the client secret
12397+
if oauth_client_secret and oauth_client_secret != settings.masked_auth_value:
12398+
# Encrypt the new client secret
1239912399
encryption = get_encryption_service(settings.auth_encryption_secret)
1240012400
oauth_config["client_secret"] = await encryption.encrypt_secret_async(oauth_client_secret)
12401+
elif oauth_client_id:
12402+
# client_id present but secret left blank or masked — preserve existing secret
12403+
oauth_config["client_secret"] = settings.masked_auth_value
1240112404

1240212405
# Add username and password for password grant type
1240312406
if oauth_username:
@@ -15719,10 +15722,13 @@ async def admin_edit_a2a_agent(
1571915722
oauth_config["redirect_uri"] = oauth_redirect_uri
1572015723
if oauth_client_id:
1572115724
oauth_config["client_id"] = oauth_client_id
15722-
if oauth_client_secret:
15723-
# Encrypt the client secret
15725+
if oauth_client_secret and oauth_client_secret != settings.masked_auth_value:
15726+
# Encrypt the new client secret
1572415727
encryption = get_encryption_service(settings.auth_encryption_secret)
1572515728
oauth_config["client_secret"] = await encryption.encrypt_secret_async(oauth_client_secret)
15729+
elif oauth_client_id:
15730+
# client_id present but secret left blank or masked — preserve existing secret
15731+
oauth_config["client_secret"] = settings.masked_auth_value
1572615732

1572715733
# Add username and password for password grant type
1572815734
if oauth_username:

mcpgateway/admin_ui/a2aAgents.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -513,7 +513,7 @@ export const editA2AAgent = async function (agentId) {
513513
oauthClientIdField.value = config.client_id || "";
514514
}
515515
if (oauthClientSecretField) {
516-
oauthClientSecretField.value = ""; // Don't populate secret for security
516+
oauthClientSecretField.value = config.client_secret ? MASKED_AUTH_VALUE : "";
517517
}
518518
if (oauthTokenUrlField) {
519519
oauthTokenUrlField.value = config.token_url || "";

mcpgateway/admin_ui/gateways.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -510,7 +510,7 @@ export const editGateway = async function (gatewayId) {
510510
oauthClientIdField.value = config.client_id || "";
511511
}
512512
if (oauthClientSecretField) {
513-
oauthClientSecretField.value = ""; // Don't populate secret for security
513+
oauthClientSecretField.value = config.client_secret ? MASKED_AUTH_VALUE : "";
514514
}
515515
if (oauthTokenUrlField) {
516516
oauthTokenUrlField.value = config.token_url || "";

mcpgateway/admin_ui/servers.js

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { AppState } from "./appState.js";
22
import { getCatalogUrl } from "./configExport.js";
3+
import { MASKED_AUTH_VALUE } from "./constants.js";
34
import { toggleViewPublic } from "./filters.js";
45
import { initGatewaySelect } from "./gateways.js";
56
import { openModal } from "./modals.js";
@@ -857,6 +858,16 @@ export const editServer = async function (serverId) {
857858
if (oauthTokenEndpointField) {
858859
oauthTokenEndpointField.value = server.oauthConfig.token_endpoint || "";
859860
}
861+
862+
// Extract client_id for DCR bypass (pre-registered client)
863+
const oauthClientIdField = safeGetElement("edit-server-oauth-client-id");
864+
if (oauthClientIdField) {
865+
oauthClientIdField.value = server.oauthConfig.client_id || "";
866+
}
867+
const oauthClientSecretField = safeGetElement("edit-server-oauth-client-secret");
868+
if (oauthClientSecretField) {
869+
oauthClientSecretField.value = server.oauthConfig.client_secret ? MASKED_AUTH_VALUE : "";
870+
}
860871
} else {
861872
// Clear OAuth config fields when no config exists
862873
if (oauthAuthServerField) oauthAuthServerField.value = "";

0 commit comments

Comments
 (0)