blob: e2f47f8152d1c5685cb99670d42128e2ee97d5bf [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.wicket.coep;
import org.apache.wicket.coop.CrossOriginOpenerPolicyRequestCycleListener;
import org.apache.wicket.request.IRequestHandler;
import org.apache.wicket.request.cycle.IRequestCycleListener;
import org.apache.wicket.request.cycle.RequestCycle;
import org.apache.wicket.request.http.WebResponse;
import org.apache.wicket.util.lang.Args;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import jakarta.servlet.http.HttpServletRequest;
/**
* Sets <a href="https://wicg.github.io/cross-origin-embedder-policy/">Cross-Origin Embedder
* Policy</a> (COEP) headers on the responses based on the mode specified by
* {@link CrossOriginEmbedderPolicyConfiguration}. COEP can be enabled in <code>REPORTING</code>
* mode which will set the headers as <code>Cross-Origin-Embedder-Policy-Report-Only</code> or
* <code>ENFORCING</code> mode which will set the header as
* <code>Cross-Origin-Embedder-Policy</code>. The header is not set for the paths that are exempted
* from COEP. The only valid value of COEP is <code>require-corp</code>, so if the listener is
* enabled the policy value will be specified as so.
*
* COEP prevents a document from loading any non-same-origin resources which don't explicitly grant
* the document permission to be loaded. Using COEP and COOP together allows developers to safely
* use powerful features such as <code>SharedArrayBuffer</code>,
* <code>performance.measureMemory()</code>, and the JS Self-Profiling API.See
* {@link CrossOriginOpenerPolicyRequestCycleListener} for instructions on how to enable COOP.
* Read more about cross-origin isolation on
* <a href="https://web.dev/why-coop-coep/">https://web.dev/why-coop-coep/</a>
*
*
* @author Santiago Diaz - saldiaz@google.com
* @author Ecenaz Jen Ozmen - ecenazo@google.com
*
* @see CrossOriginEmbedderPolicyConfiguration
* @see org.apache.wicket.settings.SecuritySettings
*/
public class CrossOriginEmbedderPolicyRequestCycleListener implements IRequestCycleListener
{
private static final Logger log = LoggerFactory.getLogger(CrossOriginEmbedderPolicyRequestCycleListener.class);
static final String REQUIRE_CORP = "require-corp";
private CrossOriginEmbedderPolicyConfiguration coepConfig;
public CrossOriginEmbedderPolicyRequestCycleListener(CrossOriginEmbedderPolicyConfiguration coepConfig)
{
this.coepConfig = Args.notNull(coepConfig, "coepConfig");
}
@Override
public void onRequestHandlerResolved(RequestCycle cycle, IRequestHandler handler)
{
final Object containerRequest = cycle.getRequest().getContainerRequest();
if (containerRequest instanceof HttpServletRequest)
{
HttpServletRequest request = (HttpServletRequest) containerRequest;
String path = request.getContextPath();
final String coepHeaderName = coepConfig.getCoepHeader();
if (coepConfig.getExemptions().contains(path))
{
log.debug("Request path {} is exempted from COEP, no '{}' header added", path, coepHeaderName);
return;
}
if (cycle.getResponse() instanceof WebResponse)
{
WebResponse webResponse = (WebResponse) cycle.getResponse();
if (webResponse.isHeaderSupported())
{
webResponse.setHeader(coepHeaderName, REQUIRE_CORP);
}
}
}
}
}