Copied to clipboard

Flag this post as spam?

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


  • Neil 40 posts 205 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 610 posts 2409 karma points
    Nov 15, 2022 @ 19:37
    Bo Jacobsen
    101

    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 80 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 40 posts 205 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 610 posts 2409 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 80 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 80 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 40 posts 205 karma points
    Nov 16, 2022 @ 12:04
    Neil
    0

    Works perfectly, cheers :)

  • This forum is in read-only mode while we transition to the new forum.

    You can continue this topic on the new forum by tapping the "Continue discussion" link below.

Please Sign in or register to post replies