From 4d32ac8765c7e20390a20e73656a00cf1b43f78a Mon Sep 17 00:00:00 2001 From: Scott Rossillo Date: Mon, 11 May 2015 19:48:16 -0400 Subject: [PATCH] Add Servlet 2.x support to the Spring Security adapter Cookie.setHttpOnly() was added in Servlet 3.0. Make setting a cookie as HttpOnly dependent on servlet version. --- .../facade/WrappedHttpServletResponse.java | 19 ++++++++++++++++++- .../WrappedHttpServletResponseTest.java | 1 + 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/integration/spring-security/src/main/java/org/keycloak/adapters/springsecurity/facade/WrappedHttpServletResponse.java b/integration/spring-security/src/main/java/org/keycloak/adapters/springsecurity/facade/WrappedHttpServletResponse.java index c0b5759694..ade1b21812 100644 --- a/integration/spring-security/src/main/java/org/keycloak/adapters/springsecurity/facade/WrappedHttpServletResponse.java +++ b/integration/spring-security/src/main/java/org/keycloak/adapters/springsecurity/facade/WrappedHttpServletResponse.java @@ -1,11 +1,15 @@ package org.keycloak.adapters.springsecurity.facade; import org.keycloak.adapters.HttpFacade.Response; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.OutputStream; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; /** * Concrete Keycloak {@link Response response} implementation wrapping an {@link HttpServletResponse}. @@ -15,6 +19,7 @@ import java.io.OutputStream; */ class WrappedHttpServletResponse implements Response { + private static final Logger log = LoggerFactory.getLogger(WrappedHttpServletResponse.class); private final HttpServletResponse response; /** @@ -50,11 +55,23 @@ class WrappedHttpServletResponse implements Response { cookie.setMaxAge(maxAge); cookie.setSecure(secure); - cookie.setHttpOnly(httpOnly); + this.setHttpOnly(cookie, httpOnly); response.addCookie(cookie); } + private void setHttpOnly(Cookie cookie, boolean httpOnly) { + Method method; + try { + method = Cookie.class.getMethod("setHttpOnly", boolean.class); + method.invoke(cookie, httpOnly); + } catch (NoSuchMethodException e) { + log.warn("Unable to set httpOnly on cookie [{}]; no such method on javax.servlet.http.Cookie", cookie.getName()); + } catch (ReflectiveOperationException e) { + log.error("Unable to set httpOnly on cookie [{}]", cookie.getName(), e); + } + } + @Override public void setStatus(int status) { response.setStatus(status); diff --git a/integration/spring-security/src/test/java/org/keycloak/adapters/springsecurity/facade/WrappedHttpServletResponseTest.java b/integration/spring-security/src/test/java/org/keycloak/adapters/springsecurity/facade/WrappedHttpServletResponseTest.java index 408d9c517d..2dd3a8cbf5 100644 --- a/integration/spring-security/src/test/java/org/keycloak/adapters/springsecurity/facade/WrappedHttpServletResponseTest.java +++ b/integration/spring-security/src/test/java/org/keycloak/adapters/springsecurity/facade/WrappedHttpServletResponseTest.java @@ -48,6 +48,7 @@ public class WrappedHttpServletResponseTest { assertEquals(COOKIE_DOMAIN, mockResponse.getCookie(COOKIE_NAME).getDomain()); assertEquals(maxAge, mockResponse.getCookie(COOKIE_NAME).getMaxAge()); assertEquals(COOKIE_VALUE, mockResponse.getCookie(COOKIE_NAME).getValue()); + assertEquals(true, mockResponse.getCookie(COOKIE_NAME).isHttpOnly()); } @Test