inspector/core/client/secrets.ts
Bob Dickinson 5de4e911e3
feat(web,core): enterprise-managed authorization (EMA) (#1509) (#1512)
Adds enterprise-managed authorization (EMA): browser-side IdP login + RFC 8693 token-exchange and JWT-bearer resource-token mint, per-server EMA opt-in in Server Settings, IdP config in Client Settings, and IdP clientSecret keychain storage. Includes the v2/main merge and review follow-ups (400 on malformed client config; normalizeIdpIssuer import consolidation).
2026-06-24 22:15:12 -04:00

65 lines
1.8 KiB
TypeScript

/**
* Strip/merge install-level IdP client secrets for client.json ↔ keychain.
* Browser-safe — no Node keychain imports.
*/
import { SECRET_FIELD_IDP_CLIENT_SECRET } from "../auth/secret-fields.js";
import type { ClientConfig } from "./types.js";
/** Keychain namespace for install-level client config (not a server catalog id). */
export const CLIENT_KEYCHAIN_ID = "client";
export function hasClientPlaintextSecret(config: ClientConfig): boolean {
const secret = config.enterpriseManagedAuth?.idp?.clientSecret;
return typeof secret === "string" && secret.length > 0;
}
/**
* Lift IdP `clientSecret` off the config blob. The stripped shape is what
* lands on disk; the secret map is written to the OS keychain.
*/
export function extractSecretsFromClientConfig(config: ClientConfig): {
stripped: ClientConfig;
secrets: Record<string, string>;
} {
const secrets: Record<string, string> = {};
const ema = config.enterpriseManagedAuth;
if (!ema?.idp?.clientSecret) {
return { stripped: config, secrets };
}
const { clientSecret, ...idpRest } = ema.idp;
secrets[SECRET_FIELD_IDP_CLIENT_SECRET] = clientSecret;
return {
stripped: {
...config,
enterpriseManagedAuth: {
...ema,
idp: idpRest,
},
},
secrets,
};
}
/** Merge keychain secrets back into a stripped on-disk client config. */
export function mergeSecretsIntoClientConfig(
config: ClientConfig,
secrets: Record<string, string>,
): ClientConfig {
const idpSecret = secrets[SECRET_FIELD_IDP_CLIENT_SECRET];
const ema = config.enterpriseManagedAuth;
if (!idpSecret || !ema?.idp) {
return config;
}
return {
...config,
enterpriseManagedAuth: {
...ema,
idp: {
...ema.idp,
clientSecret: idpSecret,
},
},
};
}