Hi! I would like to set different Security headers (specifically different Content Security Policy headers) for the frontend of my website and the Umbraco backoffice (version 11). I however do not seem to be able to get this done with middleware, since I don't have access to the IApplicationBuilder builder to .UseSecurityHeaders() in there. I used another example from another topic here on the Umbraco forum, but this does not set the CSP headers at all :
public static IApplicationBuilder UseSecurityPolicy(this IApplicationBuilder app) => app
you don't actually appear to be setting the header anywhere (unless I'm missing something)
In ASP.NET Core, you can create middleware to set the header to http response, here is a minimal middleware to do this. You need to add this code to the Configure() method in Startup.cs before the UseEndpoints method.
Hi Huw Reddick, thank you for your quick reply. I'm using a package to set the headers (NetEscapades.AspNetCore.SecurityHeaders, https://github.com/andrewlock/NetEscapades.AspNetCore.SecurityHeaders), mainly because it was easy to create a Nonce and implement this at the frontend with a tag helper. This package sets the security headers by using the method app.UseSecurityHeaders(), possible to pass a PolicyCollection as a parameter (like I did) for custom configuration.
So with the way the package works I need to set the headers with that method on the IApplicationBuilder, and not like you directly on the context. Would it be unpossible to use this package then, if I understand it correctly from you?
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
app.UseResponseCompression();
app.UseWebP();
app.UseImageSharp();
app.UseSession();
//Custom middleware to make a distinction between /umbraco and non-/umbraco for Content Security Protocol header
**app.UseSecurityPolicy();**
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
var rewriteOptions = new RewriteOptions().AddIISUrlRewrite(env.ContentRootFileProvider, "IISUrlRewriteDev.xml");
app.UseRewriter(rewriteOptions);
}
else
{
app.UseHttpsRedirection();
app.UseHsts();
var rewriteOptions = new RewriteOptions().AddIISUrlRewrite(env.ContentRootFileProvider, "IISUrlRewrite.xml");
app.UseRewriter(rewriteOptions);
}
// This line is needed for the rewrites to take effect.
app.UseStaticFiles();
//AppDomain.CurrentDomain.SetData("HostEnvironment", env);
app.UseDownloadRequestMiddleware();
app.UseOutputCache();
app.UseResponseCaching();
app.UseUmbraco()
.WithMiddleware(u =>
{
u.UseBackOffice();
u.UseWebsite();
})
.WithEndpoints(u =>
{
u.UseCustomRoutingRules();
u.UseInstallerEndpoints();
u.UseBackOfficeEndpoints();
u.UseWebsiteEndpoints();
});
}
Sorry for the weird formatting at the start. The app.UseSecurityPolicy(); is towards the start of the code.
Again sorry for the shitty formatting. It's the public static HeaderPolicyCollection policyCollection = new HeaderPolicyCollection(); almost at the top, it's at the same level as the UseSecurityPolicy method.
Thank you! I reallt appreciate that. Have been struggling a while to get it work but kinda stuck now. These are the headers that are being set (same for / as /umbraco):
Weirdly enough the other headers are being set, except for the CSP one. When I put this code directly in the Configure method in Startup.cs, without the backoffice check, I get all the headers set correctly, also CSP.
var policyCollection = new HeaderPolicyCollection()
.AddContentTypeOptionsNoSniff()
.AddXssProtectionBlock()
.AddFrameOptionsSameOrigin()
...Et cetera.
Must have been some kind of scope issue?? Kind of weird but I'm glad it's solved now. Thank you anyway for taking the time to think towards a solution with me, really appreciate it :) And again sorry for the shitty formatting of the code :')
Using middleware to set Security headers
Hi! I would like to set different Security headers (specifically different Content Security Policy headers) for the frontend of my website and the Umbraco backoffice (version 11). I however do not seem to be able to get this done with middleware, since I don't have access to the IApplicationBuilder builder to .UseSecurityHeaders() in there. I used another example from another topic here on the Umbraco forum, but this does not set the CSP headers at all :
public static IApplicationBuilder UseSecurityPolicy(this IApplicationBuilder app) => app
Above code I call in the Startup.cs like this -> app.UseSecurityPolicy();
Any idea on how to set the CSP headers correctly? Thank you in advance.
you don't actually appear to be setting the header anywhere (unless I'm missing something)
In ASP.NET Core, you can create middleware to set the header to http response, here is a minimal middleware to do this. You need to add this code to the Configure() method in Startup.cs before the UseEndpoints method.
check out this post
https://damienbod.com/2021/08/16/improving-application-security-in-asp-net-core-razor-pages-using-http-headers-part-1/#:~:text=In%20the%20Startup%20class%2C%20the%20UseSecurityHeaders%20method%20is,the%20Configure%20method%20as%20this%20is%20not%20required.
Hi Huw Reddick, thank you for your quick reply. I'm using a package to set the headers (NetEscapades.AspNetCore.SecurityHeaders, https://github.com/andrewlock/NetEscapades.AspNetCore.SecurityHeaders), mainly because it was easy to create a Nonce and implement this at the frontend with a tag helper. This package sets the security headers by using the method app.UseSecurityHeaders(), possible to pass a PolicyCollection as a parameter (like I did) for custom configuration.
So with the way the package works I need to set the headers with that method on the IApplicationBuilder, and not like you directly on the context. Would it be unpossible to use this package then, if I understand it correctly from you?
Just had a quick look and I don't see any reason why you couldn't, so perhaps you have not implemented it quite right.
Where exactly in your startup.cs did you add
app.UseSecurityPolicy()
;I put it here:
public void Configure(IApplicationBuilder app, IWebHostEnvironment env) {
Sorry for the weird formatting at the start. The app.UseSecurityPolicy(); is towards the start of the code.
in your code, where are you defining policycollection?
In the packages examples, it does this
Ahh, I see I omitted that part. I do it here:
public static class SecurityPolicyAppBuilderExtension {
public static HeaderPolicyCollection policyCollection = new HeaderPolicyCollection();
Again sorry for the shitty formatting. It's the public static HeaderPolicyCollection policyCollection = new HeaderPolicyCollection(); almost at the top, it's at the same level as the UseSecurityPolicy method.
I can't see any reason it wouldn't work. I will have a little play later myself.
Do you get any errors or does it just not add the header?
Thank you! I reallt appreciate that. Have been struggling a while to get it work but kinda stuck now. These are the headers that are being set (same for / as /umbraco):
Weirdly enough the other headers are being set, except for the CSP one. When I put this code directly in the Configure method in Startup.cs, without the backoffice check, I get all the headers set correctly, also CSP.
so it may possibly be your backoffice check that is failing then
Hmm yes but then it would be weird that the other headers are being set correctly:
.AddContentTypeOptionsNoSniff()
Ok so I just found the solution. Not declaring the policyCollection:
public static HeaderPolicyCollection policyCollection = new HeaderPolicyCollection();
at the top outside of the method, but inside the method, like:
public static IApplicationBuilder UseSecurityPolicy(this IApplicationBuilder app) => app.UseWhen(x => !IsBackOffice(x), appBuilder => {
...Et cetera.
Must have been some kind of scope issue?? Kind of weird but I'm glad it's solved now. Thank you anyway for taking the time to think towards a solution with me, really appreciate it :) And again sorry for the shitty formatting of the code :')
No problem, glad you got it sorted 🙂
is working on a reply...