Allow empty CSP header in headers provider

Closes #29458

Signed-off-by: rmartinc <rmartinc@redhat.com>
This commit is contained in:
rmartinc 2024-05-11 18:35:34 +02:00 committed by Marek Posolda
parent 6cc8d653f3
commit 2cc051346d
2 changed files with 31 additions and 10 deletions

View file

@ -106,24 +106,25 @@ public class DefaultSecurityHeadersProvider implements SecurityHeadersProvider {
// TODO This will be refactored as part of introducing a more strict CSP header // TODO This will be refactored as part of introducing a more strict CSP header
if (options != null) { if (options != null) {
ContentSecurityPolicyBuilder csp = ContentSecurityPolicyBuilder.create(
headers.getFirst(CONTENT_SECURITY_POLICY.getHeaderName()).toString());
if (options.isAllowAnyFrameAncestor()) { if (options.isAllowAnyFrameAncestor()) {
headers.remove(BrowserSecurityHeaders.X_FRAME_OPTIONS.getHeaderName()); headers.remove(BrowserSecurityHeaders.X_FRAME_OPTIONS.getHeaderName());
}
if (csp.isDefaultFrameAncestors()) { Object cspVal = headers.getFirst(CONTENT_SECURITY_POLICY.getHeaderName());
if (cspVal != null) {
ContentSecurityPolicyBuilder csp = ContentSecurityPolicyBuilder.create(cspVal.toString());
if (options.isAllowAnyFrameAncestor() && csp.isDefaultFrameAncestors()) {
// only remove frame ancestors if defined to default 'self' // only remove frame ancestors if defined to default 'self'
csp.frameAncestors(null); csp.frameAncestors(null);
} }
}
String allowedFrameSrc = options.getAllowedFrameSrc(); String allowedFrameSrc = options.getAllowedFrameSrc();
if (allowedFrameSrc != null) { if (allowedFrameSrc != null) {
csp.addFrameSrc(allowedFrameSrc); csp.addFrameSrc(allowedFrameSrc);
} }
headers.putSingle(CONTENT_SECURITY_POLICY.getHeaderName(), csp.build()); headers.putSingle(CONTENT_SECURITY_POLICY.getHeaderName(), csp.build());
}
} }
} }

View file

@ -40,7 +40,12 @@ import org.keycloak.testsuite.AbstractKeycloakTest;
import org.keycloak.testsuite.ActionURIUtils; import org.keycloak.testsuite.ActionURIUtils;
import org.keycloak.testsuite.oidc.PkceGenerator; import org.keycloak.testsuite.oidc.PkceGenerator;
import org.keycloak.testsuite.runonserver.ServerVersion; import org.keycloak.testsuite.runonserver.ServerVersion;
import org.keycloak.testsuite.updaters.RealmAttributeUpdater;
import org.keycloak.testsuite.util.AdminClientUtil;
import org.keycloak.testsuite.util.RealmBuilder;
import jakarta.ws.rs.client.Client;
import jakarta.ws.rs.core.Response;
import java.io.IOException; import java.io.IOException;
import java.net.URLEncoder; import java.net.URLEncoder;
import java.util.Collections; import java.util.Collections;
@ -200,8 +205,23 @@ public class LoginStatusIframeEndpointTest extends AbstractKeycloakTest {
} }
} }
@Test
public void checkEmptyCsp() throws Exception {
try (RealmAttributeUpdater realmUpdater = new RealmAttributeUpdater(adminClient.realm("test"))
.setBrowserSecurityHeader(BrowserSecurityHeaders.CONTENT_SECURITY_POLICY.getKey(), "")
.update();
Client client = AdminClientUtil.createResteasyClient();
Response response = client.target(suiteContext.getAuthServerInfo().getContextRoot()
+ "/auth/realms/test/protocol/openid-connect/login-status-iframe.html").request().get()) {
assertEquals(Response.Status.OK.getStatusCode(), response.getStatus());
assertNull(response.getHeaderString(BrowserSecurityHeaders.CONTENT_SECURITY_POLICY.getKey()));
assertNull(response.getHeaderString(BrowserSecurityHeaders.X_FRAME_OPTIONS.getHeaderName()));
}
}
@Override @Override
public void addTestRealms(List<RealmRepresentation> testRealms) { public void addTestRealms(List<RealmRepresentation> testRealms) {
testRealms.add(RealmBuilder.create().name("test").build());
} }
} }