different-ai/openwork · error · ProbeFailure
AUTH_ISSUER_DISCOVERY
AUTH_ISSUER_DISCOVERY
Error message
Protected-resource metadata had no authorization server
What it means
The protected-resource metadata must list at least one authorization_servers entry; the probe takes the first one to discover the issuer's OAuth metadata. An empty or missing authorization_servers array leaves the client with no authorization server to authenticate against, so the probe fails in AUTH_ISSUER_DISCOVERY with subcode oauth_discovery_issuer.
Source
Thrown at packages/enterprise-mcp-mock-server/src/testing/probe.ts:554
await fetchStep(resourceMetadataUrl, undefined, "AUTH_RESOURCE_DISCOVERY", overallDeadline),
"AUTH_RESOURCE_DISCOVERY",
)
const resourceMetadata = parseAt(
protectedResourceMetadataSchema,
await parseJson(resourceResponse, "AUTH_RESOURCE_DISCOVERY", "oauth_discovery_resource"),
"AUTH_RESOURCE_DISCOVERY",
"oauth_discovery_resource",
"Protected-resource metadata did not match the required shape",
)
if (resourceMetadata.resource !== mcpUrl) {
throw new ProbeFailure("AUTH_RESOURCE_DISCOVERY", "oauth_discovery_resource", "Protected-resource metadata did not identify this MCP endpoint")
}
recordPassed(phases, "AUTH_RESOURCE_DISCOVERY", startedAt, "Protected-resource metadata is coherent")
startedAt = Date.now()
const authorizationServerValue = resourceMetadata.authorization_servers[0]
if (!authorizationServerValue) {
throw new ProbeFailure("AUTH_ISSUER_DISCOVERY", "oauth_discovery_issuer", "Protected-resource metadata had no authorization server")
}
const issuerMetadataResponse = await expectOk(
await fetchStep(
new URL("/.well-known/oauth-authorization-server", assertPinnedOrigin(authorizationServerValue, baseUrl, "AUTH_ISSUER_DISCOVERY")),
undefined,
"AUTH_ISSUER_DISCOVERY",
overallDeadline,
),
"AUTH_ISSUER_DISCOVERY",
)
const issuerMetadata = parseAt(
authorizationServerMetadataSchema,
await parseJson(issuerMetadataResponse, "AUTH_ISSUER_DISCOVERY", "oauth_discovery_issuer"),
"AUTH_ISSUER_DISCOVERY",
"oauth_discovery_issuer",
"Authorization-server metadata did not match the required shape",
)
if (issuerMetadata.issuer !== baseUrl.href.replace(/\/$/, "")) {View on GitHub (pinned to 2b7df46e8a)
Solutions
- Add "authorization_servers": ["<issuer-url>"] to the protected-resource metadata document.
- Wire the MCP server's OAuth configuration so it knows and advertises its authorization server.
- If generating metadata dynamically, guard against emitting an empty array when the AS config is missing.
Example fix
// before
{ "resource": mcpUrl }
// after
{ "resource": mcpUrl, "authorization_servers": ["https://localhost:3000/"] } Defensive patterns
Strategy: validation
Validate before calling
const md = await (await fetch(metadataUrl)).json()
if (!Array.isArray(md.authorization_servers) || md.authorization_servers.length === 0) {
throw new Error("authorization_servers must list at least one issuer URL")
} Type guard
function hasAuthorizationServers(md: unknown): md is { authorization_servers: [string, ...string[]] } & Record<string, unknown> {
return typeof md === "object" && md !== null &&
Array.isArray((md as { authorization_servers?: unknown }).authorization_servers) &&
(md as { authorization_servers: unknown[] }).authorization_servers.length > 0
} Try / catch
try {
await probeEnterpriseMcpMockServer({ baseUrl })
} catch (e) {
if (e instanceof ProbeFailure && e.phase === "AUTH_ISSUER_DISCOVERY" && e.message.includes("no authorization server")) {
console.error("Add authorization_servers to the protected-resource metadata")
} else throw e
} Prevention
- Always include authorization_servers in protected-resource metadata fixtures
- Fail fast at server startup if OAuth AS config is missing rather than emitting empty arrays
- Validate metadata documents against the RFC 9728 schema in tests
When it happens
Trigger: The parsed metadata document has no authorization_servers key or an empty array (resourceMetadata.authorization_servers[0] is undefined).
Common situations: Hand-written metadata fixture omitting the field, a server emitting authorization_servers: [] when its OAuth deployment is not wired up, or a shape-validation pass that allows an empty array.
Related errors
- AUTH_RESOURCE_DISCOVERY
- oauth_token_exchange_failed
- Failed to sign in to OpenWork Cloud.
- desktop_signup_deprecated
- t("providers.removal_unsupported")
AI-assisted analysis of different-ai/openwork@2b7df46e8a (2026-09-01).
Data as JSON: /api/errors/40d580a18e6617db.
Report an issue: GitHub.