Copied to clipboard

Flag this post as spam?

This post will be reported to the moderators as potential spam to be looked at


  • Neil 37 posts 201 karma points
    Nov 15, 2022 @ 16:24
    Neil
    0

    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?

  • Bo Jacobsen 593 posts 2389 karma points
    Nov 15, 2022 @ 19:37
    Bo Jacobsen
    100

    Hi Neil.

    Yes, you can now do it in your middleware.

    public static IApplicationBuilder UseCustomMiddleware(this IApplicationBuilder app)
    {
        // Use when path is Umbraco
        app.UseWhen(context => context.Request.Path.StartsWithSegments(new PathString("/umbraco")), appBuilder =>
        {
            // Apply stuff here..
        });
    
        // Use when path is not Umbraco
        app.UseWhen(context => !context.Request.Path.StartsWithSegments(new PathString("/umbraco")), appBuilder =>
        {
            // Apply stuff here..
        });
    
        return app;
    }
    
  • Grakify 13 posts 79 karma points
    Sep 26, 2023 @ 13:32
    Grakify
    0

    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!

  • Neil 37 posts 201 karma points
    Sep 26, 2023 @ 13:51
    Neil
    0

    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();
            });
        }
      }
    
  • Bo Jacobsen 593 posts 2389 karma points
    Sep 26, 2023 @ 13:55
    Bo Jacobsen
    0

    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.

  • Grakify 13 posts 79 karma points
    Sep 26, 2023 @ 14:06
    Grakify
    0

    Hi Neil, you're a real lifesaver! Thank you for your quick reply, your code did the trick :) You rock!

  • Grakify 13 posts 79 karma points
    Sep 26, 2023 @ 14:06
    Grakify
    0

    Hi Bo! No I didn't, Neil luckily just provided the code that made it work for me. Thanks anyway for your answer :)

  • Neil 37 posts 201 karma points
    Nov 16, 2022 @ 12:04
    Neil
    0

    Works perfectly, cheers :)

Please Sign in or register to post replies

Write your reply to:

Draft