Split Site:Audience into Site:ExternalUrl + Site:CorsAllowedOrigins

The Site:Audience setting was conflating two distinct concepts: an OAuth
JWT audience (a single resource identifier) and a CORS allow-list (an
array of origins). Collapsing them caused several latent bugs:
- OAuth/JWT validation expected a single string while CORS WithOrigins
  accepts an array.
- Password-reset callback URLs and OAuth client RedirectUri/Origin were
  being built from what was meant to be an audience identifier, not a
  base URL.
- Yavsc.Org's main CORS policy was hardcoded to '*', with no way to
  restrict it without code changes.

Changes:
- SiteSettings.Audience (string) replaced with CorsAllowedOrigins
  (IList<string>).
- OAuth JWT Authority still reads Site:Authority; Audience now reads
  Site:ExternalUrl (Org only; Api/Blogs use ValidateAudience=false).
- MailSender and AccountController build reset-callback URLs from
  Site:ExternalUrl.
- ClientController uses Site:ExternalUrl for OAuth RedirectUri/Origin
  defaults on newly created clients.
- Yavsc.Api and Yavsc.Blogs now read CORS origins from
  Site:CorsAllowedOrigins instead of hardcoded URLs.

Add shared AddYavscCors / AddYavscJwtBearer extension methods in
Yavsc.Server/Helpers/ServiceExtensions.cs to enforce a single
configuration contract across all runtime services (Api, Blogs, Org).
Fails closed when CorsAllowedOrigins is empty; fails fast at startup
when Site:Authority is missing.

Remove obsolete ConfigurationHelpers.GetAudience (no remaining callers).

Local appsettings-*.json files (which carry deployment-specific values
and are gitignored) must be updated to add Site:CorsAllowedOrigins.
This commit is contained in:
Paul Schneider 2026-06-19 13:15:21 +01:00
commit dcf2a93ad0
11 changed files with 125 additions and 84 deletions

View file

@ -87,13 +87,13 @@ namespace Yavsc.Controllers
dbContext.ClientRedirectUris.Add(new ClientRedirectUri
{
ClientId = client.Id,
RedirectUri = siteSettings.Audience
RedirectUri = siteSettings.ExternalUrl
});
dbContext.ClientCorsOrigins.Add(new ClientCorsOrigin
{
ClientId = client.Id,
Origin = siteSettings.Audience
Origin = siteSettings.ExternalUrl
});
foreach (String credType in new String[] { "code", "client_credentials", "password" })