I've done some searching, and found some similar questions, but no solutions.
Prior to v9, it was possible to add a <location path="umbraco"> block to the web.config, to apply a more lax CSP to the backoffice (to avoid breaking angular, etc).
With the removal of the web.config (and all core folders from wwwroot etc), this block does not exist.
Creating a global CSP in a web.config works fine, but adding the extra location block in causes the backend to throws the error: 403.14 - Forbidden (The Web server is configured to not list the contents of this directory).
Has anyone figured out a way to have a separate CSP for the front and back end, to avoid needing unsafe-inline and unsafe-eval enabled on the front end?
Hi Bo, I'm currently struggling to get this working. If I put this code in my Startup.cs, the Configure method, the whole StartsWithSegments("/umbraco") check will just be ignored and the security headers will still be set for /umbraco. This resulting in not being able to use the backoffice.
Could you please provide a little more context as to where to place the code you mentioned and possible other code also needed to make this work?
I don't think it should make a difference, but have you tried spinning it off into a custom extension class (like the example) rather than putting the UseWhen() calls direct in Configure()?
This is the class I ended up creating (I am using the NWebSec library for building the CSP).
public static class SecurityPolicyAppBuilderExtension
{
public static IApplicationBuilder UseSecurityPolicy(this IApplicationBuilder app) => app
.UseXContentTypeOptions()
.UseXfo(o => o.SameOrigin())
.UseReferrerPolicy(o => o.StrictOrigin())
.UseXXssProtection(o => o.EnabledWithBlockMode())
.UseRedirectValidation(o => o.AllowSameHostRedirectsToHttps())
.UseWhen(x => !IsBackOffice(x), a =>
{
if (a.ApplicationServices.GetRequiredService<IRuntimeState>().EnableInstaller())
{
// Don't apply the CSP when the installer is running.
return;
}
// Security policy for the front-end goes here.
})
.UseWhen(IsBackOffice, a =>
{
// Security policy for the back-office.
a.UseCsp(o => o
.DefaultSources(s => s.Self())
.ScriptSources(s => s.Self().UnsafeInline().UnsafeEval())
.StyleSources(s => s.Self().UnsafeInline())
.ImageSources(s => s.Self().CustomSources("data:", "dashboard.umbraco.com", "our.umbraco.com"))
.ConnectSources(s => s.Self().CustomSources("our.umbraco.com"))
.ObjectSources(s => s.None())
);
});
private static bool IsBackOffice(HttpContext context) => context.Request.Path.StartsWithSegments(new PathString("/umbraco"));
}
}
Then in Startup.cs I just needed this
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app
.UseHttpsRedirection()
.UseSecurityPolicy() // This is the call to the custom middleware
.UseUmbraco()
.WithMiddleware(u =>
{
u.UseBackOffice();
u.UseWebsite();
})
.WithEndpoints(u =>
{
u.UseInstallerEndpoints();
u.UseBackOfficeEndpoints();
u.UseWebsiteEndpoints();
});
}
}
Backoffice specific CSP in v9+
I've done some searching, and found some similar questions, but no solutions.
Prior to v9, it was possible to add a
<location path="umbraco">
block to the web.config, to apply a more lax CSP to the backoffice (to avoid breaking angular, etc).With the removal of the web.config (and all core folders from wwwroot etc), this block does not exist.
Creating a global CSP in a web.config works fine, but adding the extra location block in causes the backend to throws the error: 403.14 - Forbidden (The Web server is configured to not list the contents of this directory).
Has anyone figured out a way to have a separate CSP for the front and back end, to avoid needing unsafe-inline and unsafe-eval enabled on the front end?
Hi Neil.
Yes, you can now do it in your middleware.
Hi Bo, I'm currently struggling to get this working. If I put this code in my Startup.cs, the Configure method, the whole StartsWithSegments("/umbraco") check will just be ignored and the security headers will still be set for /umbraco. This resulting in not being able to use the backoffice. Could you please provide a little more context as to where to place the code you mentioned and possible other code also needed to make this work?
Thank you in advance!
I don't think it should make a difference, but have you tried spinning it off into a custom extension class (like the example) rather than putting the UseWhen() calls direct in Configure()?
This is the class I ended up creating (I am using the NWebSec library for building the CSP).
Then in Startup.cs I just needed this
Hi Grakify
Have you by any chance changed the backoffice login path, then /umbraco will not work, because then you need to use the new path name.
Hi Neil, you're a real lifesaver! Thank you for your quick reply, your code did the trick :) You rock!
Hi Bo! No I didn't, Neil luckily just provided the code that made it work for me. Thanks anyway for your answer :)
Works perfectly, cheers :)
is working on a reply...