MCP Resource Indicators and Audience
Bind tokens to a protected resource when you need MCP-style OAuth behavior.
For normal owned-app flows, SqlOS can still fall back to the client's configured audience.
For MCP-style flows, the better model is:
resourceaud matches the resolved protected resourceThe authorization server and the protected resource need to agree on what the token is for.
If a caller asks for:
resource=https://todo.example.comthe resulting token should be usable for that resource and rejected by unrelated ones.
SqlOS supports resource indicators end to end:
/authorize accepts and normalizes resource/token checks that the exchange matches the original authorization requestaud claim becomes the resolved resource when presentIf no resource is supplied, SqlOS can preserve the client-audience fallback for non-MCP app flows.
Authorization-code requests currently bind any non-empty resource into the transaction; they do not compare it with the client's configured audience. Enforce the exact expected audience at the protected resource, and use validated identity plus FGA or application policy for tool/data authorization.
Resource indicators are enabled in the raw multi-client defaults. UseSingleApplication(...) keeps them off for the simpler one-app model unless you declare an Mcp surface (app.Mcp = "/mcp"), which turns them on together with CIMD because portable MCP clients need both. Without an MCP surface, enable them explicitly before expecting a supplied resource value to control aud.
You can configure them directly:
builder.AddSqlOS<AppDbContext>(options =>
{
options.AuthServer.ConfigureResourceIndicators(resource =>
{
resource.Enabled = true;
});
});Enabled is the runtime switch. SqlOS currently applies client-audience fallback, exact token-exchange resource matching, and refresh binding as fixed behavior rather than independently switchable policies. app.Mcp = "/mcp" turns this on together with CIMD. EnableChatGptCompatibility and EnableVsCodeCompatibility also set Enabled = true.
Your protected resource should still:
/.well-known/oauth-protected-resourceWWW-Authenticate: Bearer resource_metadata="..."Hosts using UseSingleApplication or ConfigureApplication get all three from the Api/Mcp declarations: SqlOS serves /.well-known/oauth-protected-resource for the API and /.well-known/oauth-protected-resource{Mcp} for the MCP surface, and challenges unauthenticated requests under each prefix with the matching resource_metadata. The Todo sample demonstrates the explicit version end to end.
Use this mental model:
resource and validate aud