Skip to content

Commit

Permalink
Merge branch 'bugfix/swagger-ui-csp-issue' into feature/173335-groupi…
Browse files Browse the repository at this point in the history
…ng-projects
  • Loading branch information
paullocknimble committed Jul 24, 2024
2 parents 0ac3b81 + dbb078c commit 20f31b1
Showing 1 changed file with 46 additions and 0 deletions.
46 changes: 46 additions & 0 deletions Dfe.Academies.Academisation.WebApi/Program.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.Reflection;
using System.Text;
using System.Text.Json;
using Dfe.Academies.Academisation.Core.Utils;
using Dfe.Academies.Academisation.Data;
Expand Down Expand Up @@ -39,9 +40,12 @@
using FluentValidation;
using MediatR;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Options;
using NetEscapades.AspNetCore.SecurityHeaders;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using Newtonsoft.Json.Serialization;
using Swashbuckle.AspNetCore.SwaggerUI;

var builder = WebApplication.CreateBuilder(args);

Expand Down Expand Up @@ -151,6 +155,35 @@
builder.Services.ConfigureOptions<SwaggerOptions>();
builder.Services.AddAutoMapper(typeof(AutoMapperProfile));

builder.Services.AddHttpContextAccessor();

builder.Services
.AddOptions<SwaggerUIOptions>()
.Configure<IHttpContextAccessor>((swaggerUiOptions, httpContextAccessor) =>
{
// 2. Take a reference of the original Stream factory which reads from Swashbuckle's embedded resources
var originalIndexStreamFactory = swaggerUiOptions.IndexStream;

// 3. Override the Stream factory
swaggerUiOptions.IndexStream = () =>
{
// 4. Read the original index.html file
using var originalStream = originalIndexStreamFactory();
using var originalStreamReader = new StreamReader(originalStream);
var originalIndexHtmlContents = originalStreamReader.ReadToEnd();

// 5. Get the request-specific nonce generated by NetEscapades.AspNetCore.SecurityHeaders
var requestSpecificNonce = httpContextAccessor.HttpContext.GetNonce();

// 6. Replace inline `<script>` and `<style>` tags by adding a `nonce` attribute to them
var nonceEnabledIndexHtmlContents = originalIndexHtmlContents
.Replace("<script>", $"<script nonce=\"{requestSpecificNonce}\">", StringComparison.OrdinalIgnoreCase)
.Replace("<style>", $"<style nonce=\"{requestSpecificNonce}\">", StringComparison.OrdinalIgnoreCase);

// 7. Return a new Stream that contains our modified contents
return new MemoryStream(Encoding.UTF8.GetBytes(nonceEnabledIndexHtmlContents));
};
});


builder.Services.AddMediatR(cfg => cfg.RegisterServicesFromAssemblies(typeof(CreateLoanCommandHandler).GetTypeInfo().Assembly));
Expand Down Expand Up @@ -207,6 +240,19 @@
.AddContentSecurityPolicy(builder =>
{
builder.AddDefaultSrc().None();

// Only allow loading resources from this app by default
builder.AddDefaultSrc().Self();

builder.AddStyleSrc()
.Self()
// Allow nonce-enabled <style> tags
.WithNonce();

builder.AddScriptSrc()
.Self()
// Allow nonce-enabled <script> tags
.WithNonce();
})
.AddPermissionsPolicy(builder =>
{
Expand Down

0 comments on commit 20f31b1

Please sign in to comment.