Skip to content

Commit

Permalink
Merge pull request #1214 from DuendeSoftware/joe/csp-hashes
Browse files Browse the repository at this point in the history
Expose CSP hashes as constants
  • Loading branch information
brockallen committed Mar 16, 2023
2 parents 2c5dcca + 245c955 commit 8661e53
Show file tree
Hide file tree
Showing 6 changed files with 34 additions and 14 deletions.
2 changes: 1 addition & 1 deletion src/IdentityServer/Endpoints/Results/AuthorizeResult.cs
Expand Up @@ -133,7 +133,7 @@ private async Task RenderAuthorizeResponseAsync(HttpContext context)

private void AddSecurityHeaders(HttpContext context)
{
context.Response.AddScriptCspHeaders(_options.Csp, "sha256-orD0/VhH8hLqrLxKHD/HUEMdwqX6/0ve7c5hspX5VJ8=");
context.Response.AddScriptCspHeaders(_options.Csp, IdentityServerConstants.ContentSecurityPolicyHashes.AuthorizeScript);

var referrer_policy = "no-referrer";
if (!context.Response.Headers.ContainsKey("Referrer-Policy"))
Expand Down
2 changes: 1 addition & 1 deletion src/IdentityServer/Endpoints/Results/CheckSessionResult.cs
Expand Up @@ -44,7 +44,7 @@ public async Task ExecuteAsync(HttpContext context)

private void AddCspHeaders(HttpContext context)
{
context.Response.AddScriptCspHeaders(_options.Csp, "sha256-fa5rxHhZ799izGRP38+h4ud5QXNT0SFaFlh4eqDumBI=");
context.Response.AddScriptCspHeaders(_options.Csp, IdentityServerConstants.ContentSecurityPolicyHashes.CheckSessionScript);
}
private string GetHtml(string cookieName)
{
Expand Down
Expand Up @@ -75,7 +75,7 @@ private void AddCspHeaders(HttpContext context)
}

// the hash matches the embedded style element being used below
context.Response.AddStyleCspHeaders(_options.Csp, "sha256-e6FQZewefmod2S/5T11pTXjzE2vn3/8GRwWOs917YE4=", sb.ToString());
context.Response.AddStyleCspHeaders(_options.Csp, IdentityServerConstants.ContentSecurityPolicyHashes.EndSessionStyle, sb.ToString());
}
}

Expand Down
20 changes: 19 additions & 1 deletion src/IdentityServer/IdentityServerConstants.cs
Expand Up @@ -202,7 +202,7 @@ public static class Tracing
public static readonly string Cache = Duende.IdentityServer.Tracing.TraceNames.Cache;
public static readonly string Validation = Duende.IdentityServer.Tracing.TraceNames.Validation;
public static readonly string Services = Duende.IdentityServer.Tracing.TraceNames.Services;

public static readonly string ServiceVersion = Duende.IdentityServer.Tracing.ServiceVersion;
}

Expand All @@ -220,4 +220,22 @@ public static class EndpointNames
public const string CheckSession = "Checksession";
public const string UserInfo = "Userinfo";
}

public static class ContentSecurityPolicyHashes
{
/// <summary>
/// The hash of the inline style used on the end session endpoint.
/// </summary>
public const string EndSessionStyle = "sha256-e6FQZewefmod2S/5T11pTXjzE2vn3/8GRwWOs917YE4=";

/// <summary>
/// The hash of the inline script used on the authorize endpoint.
/// </summary>
public const string AuthorizeScript = "sha256-orD0/VhH8hLqrLxKHD/HUEMdwqX6/0ve7c5hspX5VJ8=";

/// <summary>
/// The hash of the inline script used on the check session endpoint.
/// </summary>
public const string CheckSessionScript = "sha256-fa5rxHhZ799izGRP38+h4ud5QXNT0SFaFlh4eqDumBI=";
}
}
Expand Up @@ -18,6 +18,7 @@
using Microsoft.AspNetCore.WebUtilities;
using Xunit;
using Duende.IdentityServer.Services;
using Duende.IdentityServer;

namespace UnitTests.Endpoints.Results;

Expand Down Expand Up @@ -214,9 +215,9 @@ public async Task form_post_mode_should_pass_results_in_body()
_context.Response.Headers["Cache-Control"].First().Should().Contain("no-cache");
_context.Response.Headers["Cache-Control"].First().Should().Contain("max-age=0");
_context.Response.Headers["Content-Security-Policy"].First().Should().Contain("default-src 'none';");
_context.Response.Headers["Content-Security-Policy"].First().Should().Contain("script-src 'sha256-orD0/VhH8hLqrLxKHD/HUEMdwqX6/0ve7c5hspX5VJ8='");
_context.Response.Headers["Content-Security-Policy"].First().Should().Contain($"script-src '{IdentityServerConstants.ContentSecurityPolicyHashes.AuthorizeScript}'");
_context.Response.Headers["X-Content-Security-Policy"].First().Should().Contain("default-src 'none';");
_context.Response.Headers["X-Content-Security-Policy"].First().Should().Contain("script-src 'sha256-orD0/VhH8hLqrLxKHD/HUEMdwqX6/0ve7c5hspX5VJ8='");
_context.Response.Headers["X-Content-Security-Policy"].First().Should().Contain($"script-src '{IdentityServerConstants.ContentSecurityPolicyHashes.AuthorizeScript}'");
_context.Response.Body.Seek(0, SeekOrigin.Begin);
using (var rdr = new StreamReader(_context.Response.Body))
{
Expand All @@ -242,8 +243,8 @@ public async Task form_post_mode_should_add_unsafe_inline_for_csp_level_1()

await _subject.ExecuteAsync(_context);

_context.Response.Headers["Content-Security-Policy"].First().Should().Contain("script-src 'unsafe-inline' 'sha256-orD0/VhH8hLqrLxKHD/HUEMdwqX6/0ve7c5hspX5VJ8='");
_context.Response.Headers["X-Content-Security-Policy"].First().Should().Contain("script-src 'unsafe-inline' 'sha256-orD0/VhH8hLqrLxKHD/HUEMdwqX6/0ve7c5hspX5VJ8='");
_context.Response.Headers["Content-Security-Policy"].First().Should().Contain($"script-src 'unsafe-inline' '{IdentityServerConstants.ContentSecurityPolicyHashes.AuthorizeScript}'");
_context.Response.Headers["X-Content-Security-Policy"].First().Should().Contain($"script-src 'unsafe-inline' '{IdentityServerConstants.ContentSecurityPolicyHashes.AuthorizeScript}'");
}

[Fact]
Expand All @@ -261,7 +262,7 @@ public async Task form_post_mode_should_not_add_deprecated_header_when_it_is_dis

await _subject.ExecuteAsync(_context);

_context.Response.Headers["Content-Security-Policy"].First().Should().Contain("script-src 'sha256-orD0/VhH8hLqrLxKHD/HUEMdwqX6/0ve7c5hspX5VJ8='");
_context.Response.Headers["Content-Security-Policy"].First().Should().Contain($"script-src '{IdentityServerConstants.ContentSecurityPolicyHashes.AuthorizeScript}'");
_context.Response.Headers["X-Content-Security-Policy"].Should().BeEmpty();
}
}
Expand Up @@ -5,6 +5,7 @@
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Duende.IdentityServer;
using Duende.IdentityServer.Configuration;
using Duende.IdentityServer.Endpoints.Results;
using Duende.IdentityServer.Models;
Expand Down Expand Up @@ -41,9 +42,9 @@ public async Task should_pass_results_in_body()
_context.Response.StatusCode.Should().Be(200);
_context.Response.ContentType.Should().StartWith("text/html");
_context.Response.Headers["Content-Security-Policy"].First().Should().Contain("default-src 'none';");
_context.Response.Headers["Content-Security-Policy"].First().Should().Contain("script-src 'sha256-fa5rxHhZ799izGRP38+h4ud5QXNT0SFaFlh4eqDumBI='");
_context.Response.Headers["Content-Security-Policy"].First().Should().Contain($"script-src '{IdentityServerConstants.ContentSecurityPolicyHashes.CheckSessionScript}'");
_context.Response.Headers["X-Content-Security-Policy"].First().Should().Contain("default-src 'none';");
_context.Response.Headers["X-Content-Security-Policy"].First().Should().Contain("script-src 'sha256-fa5rxHhZ799izGRP38+h4ud5QXNT0SFaFlh4eqDumBI='");
_context.Response.Headers["X-Content-Security-Policy"].First().Should().Contain($"script-src '{IdentityServerConstants.ContentSecurityPolicyHashes.CheckSessionScript}'");
_context.Response.Body.Seek(0, SeekOrigin.Begin);
using (var rdr = new StreamReader(_context.Response.Body))
{
Expand All @@ -59,8 +60,8 @@ public async Task form_post_mode_should_add_unsafe_inline_for_csp_level_1()

await _subject.ExecuteAsync(_context);

_context.Response.Headers["Content-Security-Policy"].First().Should().Contain("script-src 'unsafe-inline' 'sha256-fa5rxHhZ799izGRP38+h4ud5QXNT0SFaFlh4eqDumBI='");
_context.Response.Headers["X-Content-Security-Policy"].First().Should().Contain("script-src 'unsafe-inline' 'sha256-fa5rxHhZ799izGRP38+h4ud5QXNT0SFaFlh4eqDumBI='");
_context.Response.Headers["Content-Security-Policy"].First().Should().Contain($"script-src 'unsafe-inline' '{IdentityServerConstants.ContentSecurityPolicyHashes.CheckSessionScript}'");
_context.Response.Headers["X-Content-Security-Policy"].First().Should().Contain($"script-src 'unsafe-inline' '{IdentityServerConstants.ContentSecurityPolicyHashes.CheckSessionScript}'");
}

[Fact]
Expand All @@ -70,7 +71,7 @@ public async Task form_post_mode_should_not_add_deprecated_header_when_it_is_dis

await _subject.ExecuteAsync(_context);

_context.Response.Headers["Content-Security-Policy"].First().Should().Contain("script-src 'sha256-fa5rxHhZ799izGRP38+h4ud5QXNT0SFaFlh4eqDumBI='");
_context.Response.Headers["Content-Security-Policy"].First().Should().Contain($"script-src '{IdentityServerConstants.ContentSecurityPolicyHashes.CheckSessionScript}'");
_context.Response.Headers["X-Content-Security-Policy"].Should().BeEmpty();
}

Expand Down

0 comments on commit 8661e53

Please sign in to comment.