Skip to content

Commit

Permalink
[Fixes #1756] Backport SameSite attribute handling from Pax Web 8
Browse files Browse the repository at this point in the history
  • Loading branch information
grgrzybek committed Sep 13, 2022
1 parent 4c08612 commit 48c46bb
Show file tree
Hide file tree
Showing 10 changed files with 57 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@ public interface WebContainerConstants {
String PROPERTY_SESSION_COOKIE_HTTP_ONLY = PID + ".session.cookie.httpOnly";
String PROPERTY_SESSION_COOKIE_SECURE = PID + ".session.cookie.secure";
String PROPERTY_SESSION_COOKIE_MAX_AGE = PID + ".session.cookie.maxAge";
String PROPERTY_SESSION_COOKIE_SAME_SITE = PID + ".session.cookie.sameSite";
String PROPERTY_SESSION_LAZY_LOAD = PID + ".session.lazyload";
String PROPERTY_SESSION_STORE_DIRECTORY = PID + ".session.storedirectory";

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ public interface JettyServer {
* null or "none" no URL rewriting will be done.
* @param sessionCookieHttpOnly if set, the session cookie is not available to client side
* scripting.
* @param sessionCookieSameSite
* @param sessionCookieSecure if set, the session cookie is only transfered over secure
* transports (https).
* @param sessionWorkerName name appended to session id, used to assist session affinity
Expand All @@ -77,6 +78,7 @@ public interface JettyServer {
void configureContext(Map<String, Object> attributes,
Integer sessionTimeout, String sessionCookie, String sessionDomain,
String sessionPath, String sessionUrl, Boolean sessionCookieHttpOnly,
String sessionCookieSameSite,
Boolean sessionCookieSecure, String sessionWorkerName,
Boolean lazyLoad, String storeDirectory,
Integer maxAge, Boolean showStacks);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -297,11 +297,12 @@ public void configureContext(final Map<String, Object> attributes,
final Integer sessionTimeout, final String sessionCookie,
final String sessionDomain, final String sessionPath,
final String sessionUrl, final Boolean sessionCookieHttpOnly,
final String sessionCookieSameSite,
final Boolean sessionCookieSecure, final String workerName,
final Boolean lazyLoad, final String storeDirectory,
final Integer maxAge, final Boolean showStacks) {
server.configureContext(attributes, sessionTimeout, sessionCookie,
sessionDomain, sessionPath, sessionUrl, sessionCookieHttpOnly,
sessionDomain, sessionPath, sessionUrl, sessionCookieHttpOnly, sessionCookieSameSite,
sessionCookieSecure, workerName, lazyLoad, storeDirectory, maxAge, showStacks);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@

import javax.servlet.ServletContainerInitializer;

import org.eclipse.jetty.http.HttpCookie;
import org.eclipse.jetty.security.Authenticator;
import org.eclipse.jetty.security.SecurityHandler;
import org.eclipse.jetty.security.authentication.BasicAuthenticator;
Expand Down Expand Up @@ -122,6 +123,7 @@ public HttpServiceContext getHandler() {
private String defaultRealmName;

private Boolean sessionCookieHttpOnly;
private String sessionCookieSameSite;

private Boolean sessionCookieSecure;

Expand Down Expand Up @@ -165,6 +167,7 @@ public HandlerCollection getRootHandlerCollection() {

public void configureContext(final Map<String, Object> attributes, final Integer timeout, final String cookie,
final String domain, final String path, final String url, final Boolean cookieHttpOnly,
final String sessionCookieSameSite,
final Boolean sessionCookieSecure, final String workerName, final Boolean lazy, final String directory,
Integer maxAge, final Boolean showStacks) {
this.contextAttributes = attributes;
Expand All @@ -174,6 +177,7 @@ public void configureContext(final Map<String, Object> attributes, final Integer
this.sessionPath = path;
this.sessionUrl = url;
this.sessionCookieHttpOnly = cookieHttpOnly;
this.sessionCookieSameSite = sessionCookieSameSite;
this.sessionCookieSecure = sessionCookieSecure;
this.sessionWorkerName = workerName;
lazyLoad = lazy;
Expand Down Expand Up @@ -337,9 +341,20 @@ private HttpServiceContext addContext(final ContextModel model) {
if (maxAge == null) {
maxAge = -1;
}
String sameSiteValue = sessionCookieSameSite;
HttpCookie.SameSite sameSite = null;
if (sameSiteValue != null && !"unset".equalsIgnoreCase(sameSiteValue)) {
if ("none".equalsIgnoreCase(sameSiteValue)) {
sameSite = HttpCookie.SameSite.NONE;
} else if ("lax".equalsIgnoreCase(sameSiteValue)) {
sameSite = HttpCookie.SameSite.LAX;
} else if ("strict".equalsIgnoreCase(sameSiteValue)) {
sameSite = HttpCookie.SameSite.STRICT;
}
}
configureSessionManager(context, modelSessionTimeout, modelSessionCookie, modelSessionDomain, modelSessionPath,
modelSessionUrl, modelSessionCookieHttpOnly, modelSessionSecure, workerName, lazyLoad, storeDirectory,
maxAge);
maxAge, sameSite);

if (this.defaultAuthMethod != null && model.getAuthMethod() == null) {
model.setAuthMethod(this.defaultAuthMethod);
Expand Down Expand Up @@ -572,11 +587,12 @@ private Map<String, Object> getContextAttributes(final BundleContext bundleConte
* @param workerName name appended to session id, used to assist session affinity
* in a load balancer
* @param maxAge session cookie maxAge
* @param sameSite
*/
private void configureSessionManager(final ServletContextHandler context, final Integer minutes,
final String cookie, String domain, String path, final String url, final Boolean cookieHttpOnly,
final Boolean secure, final String workerName, final Boolean lazy, final String directory,
final int maxAge) {
final int maxAge, HttpCookie.SameSite sameSite) {
LOG.debug("configureSessionManager for context [" + context + "] using - timeout:" + minutes + ", cookie:"
+ cookie + ", url:" + url + ", cookieHttpOnly:" + cookieHttpOnly + ", workerName:" + workerName
+ ", lazyLoad:" + lazy + ", storeDirectory: " + directory);
Expand Down Expand Up @@ -618,6 +634,9 @@ private void configureSessionManager(final ServletContextHandler context, final
((DefaultSessionIdManager) sessionHandler.getSessionIdManager()).setWorkerName(workerName);
LOG.debug("Worker name set to {} for context [{}]", workerName, context);
}
if (sameSite != null) {
sessionHandler.setSameSite(sameSite);
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -470,6 +470,7 @@ public void start() {
configuration.getSessionPath(),
configuration.getSessionUrl(),
configuration.getSessionCookieHttpOnly(),
configuration.getSessionCookieSameSite(),
configuration.getSessionCookieSecure(),
configuration.getWorkerName(),
configuration.getSessionLazyLoad(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -457,6 +457,11 @@ public Integer getSessionCookieMaxAge() {
return getResolvedIntegerProperty(PROPERTY_SESSION_COOKIE_MAX_AGE);
}

@Override
public String getSessionCookieSameSite() {
return getResolvedStringProperty(PROPERTY_SESSION_COOKIE_SAME_SITE);
}

@Override
public Boolean getSessionLazyLoad() {
return getResolvedBooleanProperty(PROPERTY_SESSION_LAZY_LOAD);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ limitations under the License.
<AD name="Session cookie path" id="org.ops4j.pax.web.session.path" type="String" default=""/>
<AD name="Session URL" id="org.ops4j.pax.web.session.url" type="String" default="jsessionid"/>
<AD name="Session cookie HttpOnly" id="org.ops4j.pax.web.session.cookie.httpOnly" type="String" default="true" />
<AD name="Session cookie SameSite attribute (unset, none, lax, strict)" id="org.ops4j.pax.web.session.cookie.sameSite" type="String" default="unset" />
<AD name="Session cookie secure" id="org.ops4j.pax.web.session.cookie.secure" type="String" default="false" />
<AD name="Session lazy load" id="org.ops4j.pax.web.session.lazyload" type="String" default="false" />
<AD name="Session store directory" id="org.ops4j.pax.web.session.storedirectory" type="String" default="" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@
import java.net.URL;
import java.util.List;

import static org.ops4j.pax.web.service.WebContainerConstants.PROPERTY_SESSION_COOKIE_SAME_SITE;

public interface Configuration {

Boolean useNIO();
Expand Down Expand Up @@ -132,6 +134,8 @@ public interface Configuration {

Integer getSessionCookieMaxAge();

String getSessionCookieSameSite();

String getSessionStoreDirectory();

Boolean getSessionLazyLoad();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,8 @@ public class EmbeddedTomcat extends Tomcat {

private Integer configurationSessionCookieMaxAge;

private String configurationSessionCookieSameSite;

private Boolean configurationSessionCookieHttpOnly;

private File configurationDir;
Expand Down Expand Up @@ -259,6 +261,7 @@ private void mergeConfiguration(Configuration configuration) {
configurationSessionCookieMaxAge = configuration.getSessionCookieMaxAge();
configurationSessionCookieHttpOnly = configuration
.getSessionCookieHttpOnly();
configurationSessionCookieSameSite = configuration.getSessionCookieSameSite();

// NCSA Logger --> AccessLogValve
if (configuration.isLogNCSAFormatEnabled()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,10 @@
import io.undertow.UndertowOptions;
import io.undertow.security.idm.Account;
import io.undertow.security.idm.Credential;
import io.undertow.server.handlers.CookieSameSiteMode;
import io.undertow.server.handlers.DisallowedMethodsHandler;
import io.undertow.server.handlers.ProxyPeerAddressHandler;
import io.undertow.server.handlers.SameSiteCookieHandler;
import io.undertow.server.handlers.resource.FileResourceManager;
import io.undertow.server.handlers.resource.ResourceHandler;
import io.undertow.servlet.api.ServletContainer;
Expand Down Expand Up @@ -751,6 +753,21 @@ public String getProperty(String key, String defaultValue) {
if (peerHostLookup) {
rootHandler = new PeerNameResolvingHandler(rootHandler);
}

// https://github.com/ops4j/org.ops4j.pax.web/issues/1727 - SameSite attribute
String sameSiteValue = configuration.getSessionCookieSameSite();
if (sameSiteValue != null && !"unset".equalsIgnoreCase(sameSiteValue)) {
String mode = null;
if ("none".equalsIgnoreCase(sameSiteValue)) {
mode = CookieSameSiteMode.NONE.toString();
} else if ("lax".equalsIgnoreCase(sameSiteValue)) {
mode = CookieSameSiteMode.LAX.toString();
} else if ("strict".equalsIgnoreCase(sameSiteValue)) {
mode = CookieSameSiteMode.STRICT.toString();
}
rootHandler = new SameSiteCookieHandler(rootHandler, mode, configuration.getSessionCookie());
}

if (!disallowedMethods.isEmpty()) {
Set<HttpString> disallowedMethodNames = new HashSet<>();
for (String m : disallowedMethods) {
Expand Down

0 comments on commit 48c46bb

Please sign in to comment.