Skip to content

Commit fd1410d

Browse files
committed
Add tests for wrong CSP hash constants
1 parent b8107f8 commit fd1410d

3 files changed

Lines changed: 76 additions & 5 deletions

File tree

identity-server/test/IdentityServer.UnitTests/Endpoints/Results/AuthorizeResultTests.cs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
// See LICENSE in the project root for license information.
33

44

5+
using System.Text.RegularExpressions;
56
using Duende.IdentityModel;
67
using Duende.IdentityServer;
78
using Duende.IdentityServer.Configuration;
@@ -226,6 +227,32 @@ public async Task form_post_mode_should_pass_results_in_body()
226227
html.ShouldContain("<input type='hidden' name='state' value='state' />");
227228
}
228229

230+
[Fact]
231+
public async Task csp_hash_should_match_inline_script()
232+
{
233+
_response.Request = new ValidatedAuthorizeRequest
234+
{
235+
ClientId = "client",
236+
ResponseMode = OidcConstants.ResponseModes.FormPost,
237+
RedirectUri = "http://client/callback",
238+
State = "state"
239+
};
240+
241+
await _subject.WriteHttpResponse(new AuthorizeResult(_response), _context);
242+
243+
_context.Response.StatusCode.ShouldBe(200);
244+
_context.Response.ContentType.ShouldStartWith("text/html");
245+
_context.Response.Body.Seek(0, SeekOrigin.Begin);
246+
using var rdr = new StreamReader(_context.Response.Body);
247+
var html = await rdr.ReadToEndAsync();
248+
249+
var match = Regex.Match(html, "<script>(.*?)</script>", RegexOptions.Singleline | RegexOptions.IgnoreCase);
250+
match.Success.ShouldBeTrue();
251+
252+
var scriptSha256 = "sha256-" + match.Groups[1].Value.ToSha256();
253+
IdentityServerConstants.ContentSecurityPolicyHashes.AuthorizeScript.ShouldContain(scriptSha256);
254+
}
255+
229256
[Fact]
230257
public async Task form_post_mode_should_add_unsafe_inline_for_csp_level_1()
231258
{

identity-server/test/IdentityServer.UnitTests/Endpoints/Results/CheckSessionResultTests.cs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
// See LICENSE in the project root for license information.
33

44

5+
using System.Text.RegularExpressions;
6+
using Duende.IdentityModel;
57
using Duende.IdentityServer;
68
using Duende.IdentityServer.Configuration;
79
using Duende.IdentityServer.Endpoints.Results;
@@ -46,6 +48,24 @@ public async Task should_pass_results_in_body()
4648
html.ShouldContain("<script id='cookie-name' type='application/json'>foobar</script>");
4749
}
4850

51+
[Fact]
52+
public async Task csp_hash_should_match_inline_script()
53+
{
54+
await _subject.WriteHttpResponse(new CheckSessionResult(), _context);
55+
56+
_context.Response.StatusCode.ShouldBe(200);
57+
_context.Response.ContentType.ShouldStartWith("text/html");
58+
_context.Response.Body.Seek(0, SeekOrigin.Begin);
59+
using var rdr = new StreamReader(_context.Response.Body);
60+
var html = await rdr.ReadToEndAsync();
61+
62+
var match = Regex.Match(html, "<script>(.*?)</script>", RegexOptions.Singleline | RegexOptions.IgnoreCase);
63+
match.Success.ShouldBeTrue();
64+
65+
var scriptSha256 = "sha256-" + match.Groups[1].Value.ToSha256();
66+
IdentityServerConstants.ContentSecurityPolicyHashes.CheckSessionScript.ShouldContain(scriptSha256);
67+
}
68+
4969
[Fact]
5070
public async Task form_post_mode_should_add_unsafe_inline_for_csp_level_1()
5171
{

identity-server/test/IdentityServer.UnitTests/Endpoints/Results/EndSessionCallbackResultTests.cs

Lines changed: 29 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@
22
// See LICENSE in the project root for license information.
33

44

5+
using System.Text.RegularExpressions;
6+
using Duende.IdentityModel;
7+
using Duende.IdentityServer;
58
using Duende.IdentityServer.Configuration;
69
using Duende.IdentityServer.Endpoints.Results;
710
using Duende.IdentityServer.Models;
@@ -52,10 +55,10 @@ public async Task success_should_render_html_and_iframes()
5255
_context.Response.Headers.CacheControl.First().ShouldContain("no-cache");
5356
_context.Response.Headers.CacheControl.First().ShouldContain("max-age=0");
5457
_context.Response.Headers.ContentSecurityPolicy.First().ShouldContain("default-src 'none';");
55-
_context.Response.Headers.ContentSecurityPolicy.First().ShouldContain("style-src 'sha256-e6FQZewefmod2S/5T11pTXjzE2vn3/8GRwWOs917YE4=';");
58+
_context.Response.Headers.ContentSecurityPolicy.First().ShouldContain($"style-src '{IdentityServerConstants.ContentSecurityPolicyHashes.EndSessionStyle}';");
5659
_context.Response.Headers.ContentSecurityPolicy.First().ShouldContain("frame-src http://foo.com http://bar.com");
5760
_context.Response.Headers["X-Content-Security-Policy"].First().ShouldContain("default-src 'none';");
58-
_context.Response.Headers["X-Content-Security-Policy"].First().ShouldContain("style-src 'sha256-e6FQZewefmod2S/5T11pTXjzE2vn3/8GRwWOs917YE4=';");
61+
_context.Response.Headers["X-Content-Security-Policy"].First().ShouldContain($"style-src '{IdentityServerConstants.ContentSecurityPolicyHashes.EndSessionStyle}';");
5962
_context.Response.Headers["X-Content-Security-Policy"].First().ShouldContain("frame-src http://foo.com http://bar.com");
6063
_context.Response.Body.Seek(0, SeekOrigin.Begin);
6164
using var rdr = new StreamReader(_context.Response.Body);
@@ -64,6 +67,27 @@ public async Task success_should_render_html_and_iframes()
6467
html.ShouldContain("<iframe loading='eager' allow='' src='http://bar.com'></iframe>");
6568
}
6669

70+
[Fact]
71+
public async Task csp_hash_should_match_inline_style()
72+
{
73+
_result.IsError = false;
74+
_result.FrontChannelLogoutUrls = new string[] { "http://foo.com", "http://bar.com" };
75+
76+
await _subject.WriteHttpResponse(new EndSessionCallbackResult(_result), _context);
77+
78+
_context.Response.StatusCode.ShouldBe(200);
79+
_context.Response.ContentType.ShouldStartWith("text/html");
80+
_context.Response.Body.Seek(0, SeekOrigin.Begin);
81+
using var rdr = new StreamReader(_context.Response.Body);
82+
var html = await rdr.ReadToEndAsync();
83+
84+
var match = Regex.Match(html, "<style>(.*?)</style>", RegexOptions.Singleline | RegexOptions.IgnoreCase);
85+
match.Success.ShouldBeTrue();
86+
87+
var styleSha256 = "sha256-" + match.Groups[1].Value.ToSha256();
88+
IdentityServerConstants.ContentSecurityPolicyHashes.EndSessionStyle.ShouldContain(styleSha256);
89+
}
90+
6791
[Fact]
6892
public async Task fsuccess_should_add_unsafe_inline_for_csp_level_1()
6993
{
@@ -73,8 +97,8 @@ public async Task fsuccess_should_add_unsafe_inline_for_csp_level_1()
7397

7498
await _subject.WriteHttpResponse(new EndSessionCallbackResult(_result), _context);
7599

76-
_context.Response.Headers.ContentSecurityPolicy.First().ShouldContain("style-src 'unsafe-inline' 'sha256-e6FQZewefmod2S/5T11pTXjzE2vn3/8GRwWOs917YE4='");
77-
_context.Response.Headers["X-Content-Security-Policy"].First().ShouldContain("style-src 'unsafe-inline' 'sha256-e6FQZewefmod2S/5T11pTXjzE2vn3/8GRwWOs917YE4='");
100+
_context.Response.Headers.ContentSecurityPolicy.First().ShouldContain($"style-src 'unsafe-inline' '{IdentityServerConstants.ContentSecurityPolicyHashes.EndSessionStyle}'");
101+
_context.Response.Headers["X-Content-Security-Policy"].First().ShouldContain($"style-src 'unsafe-inline' '{IdentityServerConstants.ContentSecurityPolicyHashes.EndSessionStyle}'");
78102
}
79103

80104
[Fact]
@@ -86,7 +110,7 @@ public async Task form_post_mode_should_not_add_deprecated_header_when_it_is_dis
86110

87111
await _subject.WriteHttpResponse(new EndSessionCallbackResult(_result), _context);
88112

89-
_context.Response.Headers.ContentSecurityPolicy.First().ShouldContain("style-src 'sha256-e6FQZewefmod2S/5T11pTXjzE2vn3/8GRwWOs917YE4='");
113+
_context.Response.Headers.ContentSecurityPolicy.First().ShouldContain($"style-src '{IdentityServerConstants.ContentSecurityPolicyHashes.EndSessionStyle}'");
90114
_context.Response.Headers["X-Content-Security-Policy"].ShouldBeEmpty();
91115
}
92116
}

0 commit comments

Comments
 (0)