Forum Discussion

arjen_kuindersm's avatar
arjen_kuindersm
Icon for Nimbostratus rankNimbostratus
Jul 15, 2015

Adding secure and httponly to cookies with same cookiename

Hi

 

While implementing secure/httponly Cookies i have discovered that it's difficult to extract cookie name/values. I have the following code:

 

when CLIENT_ACCEPTED { 
    Check for SSL
   if {[TCP::local_port] eq 443 } {
      set makeCookieSecure 1
   } else {
      set makeCookieSecure 0
   }
}

when HTTP_RESPONSE {
   
    Secure Cookies / Httponly
   
   set myValues [HTTP::cookie names]
   foreach x $myValues {
      set cookieName $x
      set cookieValue [HTTP::cookie value $x]
      log local0. "cookie: $x value $cookieValue"
      HTTP::cookie remove $x
      HTTP::cookie insert name $cookieName value $cookieValue path "/" version 1
      if {$makeCookieSecure} {HTTP::cookie secure $x enable}
      HTTP::cookie httponly $x enable
   }
}

The code works, but when there are 2 cookies with the same name, the "set cookieValue [HTTP::cookie value $x]" retrieves the 1st cookie overwriting newer set values. Browsers can handle multiple cookies overwriting the cookie with the last value. Is there a way to extract the cookies from the headers as an index?

 

2 Replies

  • I will start off by saying that servers are not supposed to set the same cookie more than once. From RFC6265 section 4.1:

     

    Servers SHOULD NOT include more than one Set-Cookie header field in
    the same response with the same cookie-name.  (See Section 5.2 for
    how user agents handle this case.)
    

     

    I'm guessing that isn't specifically helpful to you, but I think it is useful to note.

    Having said that, the HTTP::cookie primitives don't contain a method to retrieve duplicates. As such, you'll need to use HTTP::header and look for Set-Cookie and Set-Cookie2 headers. Since you want to insert the secure and HttpOnly attributes, you'll have to iterate over all over the Set-Cookie and Set-Cookie2 header values, remove all Set-Cookie and Set-Cookie2 headers, then re-insert those headers using the values you collected (with some values potentially modified). Something like this (though untested! and I only account for Set-Cookie headers):

     

    when HTTP_RESPONSE {
        if { $makeCookieSecure } {
            set cookies [HTTP::header values Set-Cookie]
            
            for { set i 0 } { $i < [llength $cookies] } { incr i } {
                set c [lindex $cookies $i]
                if { !([string tolower $c] contains "; secure") } {
                    lset cookies $i "$c; secure"
                }
                
                if { !([string tolower $c] contains "; httponly" } {
                    lset cookies $i "$c; HttpOnly"
                }
            }
        }
        
        HTTP::header remove "Set-Cookie"
        
        foreach c $cookies {
            HTTP::header insert "Set-Cookie" "$c"
        }
    }
    

     

    Keep in mind that this will place all cookies at the end of the Header stream. If that is undesirable, the code gets more complicated.

  • Your right. We opted for changing the software making it only deliver 1 cookie with the same name, respecting the RFC. Thanks for your support!