You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@unomi.apache.org by jk...@apache.org on 2022/01/04 10:53:05 UTC

[unomi] 01/02: UNOMI-541: handle HttpOnly and Secure option for the profileId cookie

This is an automated email from the ASF dual-hosted git repository.

jkevan pushed a commit to branch handleProfileCookieHttpOnlySecure2
in repository https://gitbox.apache.org/repos/asf/unomi.git

commit 808bcf6462690697c7831d7b1f1ff9d9232053d0
Author: Kevan <ke...@jahia.com>
AuthorDate: Tue Jan 4 11:45:31 2022 +0100

    UNOMI-541: handle HttpOnly and Secure option for the profileId cookie
---
 package/src/main/resources/etc/custom.system.properties           | 2 ++
 .../java/org/apache/unomi/rest/endpoints/ContextJsonEndpoint.java | 2 +-
 rest/src/main/java/org/apache/unomi/utils/HttpUtils.java          | 7 +++++--
 wab/src/main/java/org/apache/unomi/web/ContextServlet.java        | 8 +++++++-
 wab/src/main/resources/OSGI-INF/blueprint/blueprint.xml           | 2 ++
 wab/src/main/resources/org.apache.unomi.web.cfg                   | 2 ++
 6 files changed, 19 insertions(+), 4 deletions(-)

diff --git a/package/src/main/resources/etc/custom.system.properties b/package/src/main/resources/etc/custom.system.properties
index b2faee1..aa9c942 100644
--- a/package/src/main/resources/etc/custom.system.properties
+++ b/package/src/main/resources/etc/custom.system.properties
@@ -207,6 +207,8 @@ org.apache.unomi.profile.cookie.domain=${env:UNOMI_PROFILE_COOKIE_DOMAIN:-}
 org.apache.unomi.profile.cookie.name=${env:UNOMI_PROFILE_COOKIE_NAME:-context-profile-id}
 # This setting controls the maximum age of the profile cookie. By default it is set to a year.
 org.apache.unomi.profile.cookie.maxAgeInSeconds=${env:UNOMI_PROFILE_COOKIE_MAXAGEINSECONDS:-31536000}
+# This setting controls if the cookie should be flagged as HttpOnly or not.
+org.apache.unomi.profile.cookie.httpOnly=${env:UNOMI_PROFILE_COOKIE_HTTPONLY:-false}
 #Allowed profile download formats, actually only csv (horizontal and vertical), json, text and yaml are allowed.
 org.apache.unomi.profile.download.formats=${env:UNOMI_PROFILE_DOWNLOAD_FORMATS:-csv,yaml,json,text}
 # This setting allow for request size (Content-length) protection. Checking that the requests do not exceed the limit.
diff --git a/rest/src/main/java/org/apache/unomi/rest/endpoints/ContextJsonEndpoint.java b/rest/src/main/java/org/apache/unomi/rest/endpoints/ContextJsonEndpoint.java
index 185becb..525dd3a 100644
--- a/rest/src/main/java/org/apache/unomi/rest/endpoints/ContextJsonEndpoint.java
+++ b/rest/src/main/java/org/apache/unomi/rest/endpoints/ContextJsonEndpoint.java
@@ -333,7 +333,7 @@ public class ContextJsonEndpoint {
         }
         // Set profile cookie
         if (!(profile instanceof Persona)) {
-            response.setHeader("Set-Cookie", HttpUtils.getProfileCookieString(profile, configSharingService));
+            response.setHeader("Set-Cookie", HttpUtils.getProfileCookieString(profile, configSharingService, request.isSecure()));
         }
         return contextResponse;
     }
diff --git a/rest/src/main/java/org/apache/unomi/utils/HttpUtils.java b/rest/src/main/java/org/apache/unomi/utils/HttpUtils.java
index c3fab07..678f3f0 100644
--- a/rest/src/main/java/org/apache/unomi/utils/HttpUtils.java
+++ b/rest/src/main/java/org/apache/unomi/utils/HttpUtils.java
@@ -91,14 +91,17 @@ public class HttpUtils {
      * @param configSharingService shared config location.
      * @return the cookie string to set in the header.
      */
-    public static String getProfileCookieString(Profile profile, ConfigSharingService configSharingService) {
+    public static String getProfileCookieString(Profile profile, ConfigSharingService configSharingService, boolean isSecure) {
         final String profileIdCookieDomain = (String) configSharingService.getProperty("profileIdCookieDomain");
         final String profileIdCookieName = (String) configSharingService.getProperty("profileIdCookieName");
         final Integer profileIdCookieMaxAgeInSeconds = (Integer) configSharingService.getProperty("profileIdCookieMaxAgeInSeconds") ;
+        final Boolean profileIdCookieHttpOnly = (Boolean) configSharingService.getProperty("profileIdCookieHttpOnly");
         return profileIdCookieName + "=" + profile.getItemId() +
                 "; Path=/" +
                 "; Max-Age=" + profileIdCookieMaxAgeInSeconds +
                 (StringUtils.isNotBlank(profileIdCookieDomain) ? ("; Domain=" + profileIdCookieDomain) : "")  +
-                "; SameSite=Lax";
+                "; SameSite=Lax" +
+                (isSecure ? "; Secure" : "") +
+                (profileIdCookieHttpOnly ? "; HttpOnly" : "");
     }
 }
diff --git a/wab/src/main/java/org/apache/unomi/web/ContextServlet.java b/wab/src/main/java/org/apache/unomi/web/ContextServlet.java
index e83cf3f..bb28ac1 100644
--- a/wab/src/main/java/org/apache/unomi/web/ContextServlet.java
+++ b/wab/src/main/java/org/apache/unomi/web/ContextServlet.java
@@ -42,6 +42,7 @@ public class ContextServlet extends HttpServlet {
     private String profileIdCookieName = "context-profile-id";
     private String profileIdCookieDomain;
     private int profileIdCookieMaxAgeInSeconds = MAX_COOKIE_AGE_IN_SECONDS;
+    private boolean profileIdCookieHttpOnly = false;
     private int publicPostRequestBytesLimit = 200000;
 
     private ConfigSharingService configSharingService;
@@ -51,7 +52,8 @@ public class ContextServlet extends HttpServlet {
         super.init(config);
         configSharingService.setProperty("profileIdCookieName", profileIdCookieName);
         configSharingService.setProperty("profileIdCookieDomain", profileIdCookieDomain);
-        configSharingService.setProperty("profileIdCookieMaxAgeInSeconds", (Integer) profileIdCookieMaxAgeInSeconds);
+        configSharingService.setProperty("profileIdCookieMaxAgeInSeconds", profileIdCookieMaxAgeInSeconds);
+        configSharingService.setProperty("profileIdCookieHttpOnly", profileIdCookieHttpOnly);
         configSharingService.setProperty("publicPostRequestBytesLimit", publicPostRequestBytesLimit);
         logger.info("ContextServlet initialized.");
     }
@@ -78,6 +80,10 @@ public class ContextServlet extends HttpServlet {
         this.profileIdCookieMaxAgeInSeconds = profileIdCookieMaxAgeInSeconds;
     }
 
+    public void setProfileIdCookieHttpOnly(boolean profileIdCookieHttpOnly) {
+        this.profileIdCookieHttpOnly = profileIdCookieHttpOnly;
+    }
+
     public void setPublicPostRequestBytesLimit(int publicPostRequestBytesLimit) {
         this.publicPostRequestBytesLimit = publicPostRequestBytesLimit;
     }
diff --git a/wab/src/main/resources/OSGI-INF/blueprint/blueprint.xml b/wab/src/main/resources/OSGI-INF/blueprint/blueprint.xml
index d06d5e0..5437e3b 100644
--- a/wab/src/main/resources/OSGI-INF/blueprint/blueprint.xml
+++ b/wab/src/main/resources/OSGI-INF/blueprint/blueprint.xml
@@ -35,6 +35,7 @@
             <cm:property name="contextserver.domain" value=""/>
             <cm:property name="contextserver.profileIdCookieName" value="context-profile-id"/>
             <cm:property name="contextserver.profileIdCookieMaxAgeInSeconds" value="31536000"/> <!-- 1 year by default -->
+            <cm:property name="contextserver.profileIdCookieHttpOnly" value="false"/> <!-- 1 year by default -->
             <cm:property name="allowed.profile.download.formats" value="yaml"/>
             <cm:property name="public.post.request.bytes.limit" value="200000"/>
         </cm:default-properties>
@@ -46,6 +47,7 @@
         <property name="profileIdCookieDomain" value="${web.contextserver.domain}" />
         <property name="profileIdCookieName" value="${web.contextserver.profileIdCookieName}"/>
         <property name="profileIdCookieMaxAgeInSeconds" value="${web.contextserver.profileIdCookieMaxAgeInSeconds}"/>
+        <property name="profileIdCookieHttpOnly" value="${web.contextserver.profileIdCookieHttpOnly}"/>
         <property name="publicPostRequestBytesLimit" value="${web.public.post.request.bytes.limit}"/>
     </bean>
 
diff --git a/wab/src/main/resources/org.apache.unomi.web.cfg b/wab/src/main/resources/org.apache.unomi.web.cfg
index 5167916..eb48851 100644
--- a/wab/src/main/resources/org.apache.unomi.web.cfg
+++ b/wab/src/main/resources/org.apache.unomi.web.cfg
@@ -22,6 +22,8 @@ contextserver.domain=${org.apache.unomi.profile.cookie.domain:-}
 contextserver.profileIdCookieName=${org.apache.unomi.profile.cookie.name:-context-profile-id}
 # This setting controls the maximum age of the profile cookie. By default it is set to a year.
 contextserver.profileIdCookieMaxAgeInSeconds=${org.apache.unomi.profile.cookie.maxAgeInSeconds:-31536000}
+# This setting controls if the cookie should be flagged as HttpOnly or not.
+contextserver.profileIdCookieHttpOnly=${org.apache.unomi.profile.cookie.httpOnly:-false}
 #Allowed profile download formats, actually only csv (horizontal and vertical), json, text and yaml are allowed.
 allowed.profile.download.formats=${org.apache.unomi.profile.download.formats:-csv,yaml,json,text}
 # This setting allow for request size (Content-length) protection. Checking that the requests do not exceed the limit.