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 ;
58using Duende . IdentityServer . Configuration ;
69using Duende . IdentityServer . Endpoints . Results ;
710using 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