From 465cb1ff6cfe898202cea7e8cb22b9ae9f9fb840 Mon Sep 17 00:00:00 2001 From: daniel-c-harvey Date: Sun, 7 Jun 2026 16:53:49 -0400 Subject: [PATCH] feat: allow /FramePlayer to be embedded in external iframes via CORS + CSP frame-ancestors --- DeepDrftPublic/Program.cs | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/DeepDrftPublic/Program.cs b/DeepDrftPublic/Program.cs index dff19a3..695d6ed 100644 --- a/DeepDrftPublic/Program.cs +++ b/DeepDrftPublic/Program.cs @@ -24,6 +24,11 @@ Startup.ConfigureDomainServices(builder); // Add services to the container. builder.Services.AddControllers(); +builder.Services.AddCors(options => +{ + options.AddPolicy("FramePlayerEmbedPolicy", policy => + policy.AllowAnyOrigin().AllowAnyHeader().AllowAnyMethod()); +}); builder.Services.AddRazorComponents() .AddInteractiveServerComponents() .AddInteractiveWebAssemblyComponents(); @@ -72,6 +77,26 @@ else } } +app.UseCors("FramePlayerEmbedPolicy"); + +// For requests to /FramePlayer, remove any X-Frame-Options header and set a permissive +// frame-ancestors CSP so the page can be embedded in iframes on any external domain. +// OnStarting fires just before headers are flushed, ensuring this overrides headers set +// by other middleware (e.g. HSTS, reverse proxy). +app.Use(async (context, next) => +{ + if (context.Request.Path.StartsWithSegments("/FramePlayer", StringComparison.OrdinalIgnoreCase)) + { + context.Response.OnStarting(() => + { + context.Response.Headers.Remove("X-Frame-Options"); + context.Response.Headers["Content-Security-Policy"] = "frame-ancestors *"; + return Task.CompletedTask; + }); + } + await next(); +}); + // Antiforgery is required by Blazor form handling. Authentication / authorization // middleware is intentionally absent — this host is fully anonymous. app.UseAntiforgery();