diff --git a/src/cliAgent.ts b/src/cliAgent.ts index 02e74c2c..93cec759 100644 --- a/src/cliAgent.ts +++ b/src/cliAgent.ts @@ -29,6 +29,7 @@ import { LogLevel, Agent, X509Module, + X509ModuleConfig, JwkDidRegistrar, JwkDidResolver, SdJwtVcModule, @@ -309,8 +310,19 @@ const getModules = ( return await getX509CertsByClientToken(tenantId, certificateChain) } - // NoAuth: return all certs from the static trust list URL - return await getX509CertsByUrl() + // NoAuth: return all certs from the static trust list URL. + // Locally the trust list service is often unreachable (placeholder URL), + // so fall back to the certificates explicitly marked as trusted on this + // agent (e.g. added through POST /x509/trusted). + try { + return await getX509CertsByUrl() + } catch (error) { + const agentTrustedCertificates = agentContext.dependencyManager.resolve(X509ModuleConfig).trustedCertificates + if (agentTrustedCertificates && agentTrustedCertificates.length > 0) { + return agentTrustedCertificates + } + throw error + } }, }), } diff --git a/src/utils/oid4vc-agent.ts b/src/utils/oid4vc-agent.ts index 73b9951d..49737731 100644 --- a/src/utils/oid4vc-agent.ts +++ b/src/utils/oid4vc-agent.ts @@ -262,27 +262,31 @@ export async function getX509CertsByClientToken( return certificateChain.map((cert) => cert.toString('pem')) } -export async function getX509CertsByUrl(): Promise { +export async function getX509CertsByUrl(signal?: AbortSignal): Promise { const trustListUrl = process.env.TRUST_LIST_URL if (!trustListUrl) throw new Error('[getX509CertsByUrl] TRUST_LIST_URL is not configured') - logger.info(`[getX509CertsByUrl] fetching trust list from: ${trustListUrl}`) + const controller = new AbortController() + const timeout = setTimeout(() => controller.abort(), 5000) + try { + logger.info(`[getX509CertsByUrl] fetching trust list from: ${trustListUrl}`) + const response = await fetch(trustListUrl, { signal: signal ?? controller.signal }) - const response = await fetch(trustListUrl) + if (!response.ok) { + throw new Error(`[getX509CertsByUrl] failed to fetch trust list: HTTP ${response.status}`) + } - if (!response.ok) { - throw new Error(`[getX509CertsByUrl] failed to fetch trust list: HTTP ${response.status}`) - } + const data = await response.json() - const data = await response.json() + if (!Array.isArray(data) || data.length === 0) { + throw new Error('[getX509CertsByUrl] trust list is empty or invalid') + } - if (!Array.isArray(data) || data.length === 0) { - throw new Error('[getX509CertsByUrl] trust list is empty or invalid') + logger.info(`[getX509CertsByUrl] fetched certificates count: ${data.length}`) + return data as string[] + } finally { + clearTimeout(timeout) } - - logger.info(`[getX509CertsByUrl] fetched certificates count: ${data.length}`) - - return data as string[] } function handlePresentationAuthorization(