
Securing cookies in Go - wilsonfiifi
https://www.calhoun.io/securing-cookies-in-go/
======
hannob
The part about man in the middle attacks is as far as I can tell dangerously
misleading.

Defaulting to HTTPS is _not_ enough to prevent cookie theft by man in the
middle attacks, because a browser will still happily do HTTP connections.
(They'll get redirected to HTTPS if you configure the server for HTTPS only,
but that's only happening _after_ the Cookie is already transmitted without
encryption.)

Traditionally there is a "secure" flag for cookies. (I know little go, but
from reading the docs it seems it can be set in http.Cookie with Secure =
true, similarly to the httponly flag he's describing.)

However these days there's a better solution: Use HSTS, which enforces HTTPS
connections after the first connection has been made. Even better is HSTS
preloading, where your domain is added to a whitelist of HSTS domains within
common browsers.

~~~
buildme
Caveat: only do this if you're absolutely certain you never want to make a
plain HTTP request ever again, because once you're on each browser's HSTS
preload list, it takes months to get removed and have the updated list
propagated out to browsers. [1]

[1] [https://www.troyhunt.com/understanding-http-strict-
transport...](https://www.troyhunt.com/understanding-http-strict-transport/)

------
weitzj
Well rounded article. The securecookie from Gorilla works quite nicely. A good
feature is that you can have key-rotation in the server-side signature
function and can gradually introduce new keys to sign your cookies

------
gcb0
Not requiring explicit parameters for things like domain, etc in this day and
age is just ridiculous.

I expect PHP5 to be that way. php7 and golang doing that, in this day and age,
is inadmissible.

Yeah you should still be able to write a quick hack and make it work fine
without worrying about security, but the language/framework should at least
make you explicitly say "set this cookie, and allow all domains and client
side access. fine".

~~~
jorams
> Not requiring explicit parameters for things like domain, etc in this day
> and age is just ridiculous.

While I agree with the sentiment, domain is probably the worst possible
example, because it defaults to the most specific possible configuration of
"exactly the same domain".

~~~
elithrar
Correct; the same goes for Path, which is often a fun bug for many newer web
programmers when they set the cookie on '/login' and then wonder why the
cookie isn't being passed on '/store' or even '/'.

------
chmike
The passage about Gorilla's securecookie is misleading. JWT only sign the
data. It doesn't encypher it. The Gorilla's securecookie, encypher the data
and signs the encyphered data, the date and the cookie name.

Note also the existence of github.com/chmike/securecookie which is as secured,
and more efficient in size, number of allocations and speed.

------
eecc
“SetCookie doesn't return an error”, in a core library. I guess there’s a
rationalization to this folly.

~~~
jrockway
It does very little that can cause an error:

[https://golang.org/src/net/http/cookie.go?s=3875:3923#L147](https://golang.org/src/net/http/cookie.go?s=3875:3923#L147)

    
    
        func SetCookie(w ResponseWriter, cookie *Cookie) {
        	    if v := cookie.String(); v != "" {
    		    w.Header().Add("Set-Cookie", v)
    	    }
        }
    

If you want to set the header "Set-Cookie" to the empty string instead of not
sending the header, you can just call w.Header().Add("set-cookie", "")
yourself, I guess.

~~~
ThePadawan
I would start arguing about the semantics of "causing an error" here, but I
don't think it would as productive as reducing it down to this question.

If I as a client of this library call "SetCookie", and after the call, a
cookie has not been set (and I was not notified), I would call that an error
(or fault, or whatever), independent of implementation.

~~~
im_dario
Setting a cookie translates to writing a header down the socket but it isn't
written when SetCookie is called. It is written when you use the
ResponseWriter as a parameter for a writer method (io.WriteString, for
instance).

As SetCookie just adds a new header to an aliased map (Headers) and setting to
a map shouldn't fail (how it could?), it makes sense to report any error when
the HTTP response is written serialized to the socket, not before. At least,
for me, as you can manipulate the response as you wish and you only need to
worry about errors on write.

------
denormalfloat
Encrypting or signing cookies quickly becomes painful when you have multiple
front ends. Either they all need to coordinate around the signing key, or they
all need to share the same key, and they need to synchronize on key rotation.

~~~
intothemild
multiple frontends as in multiple instances? or different instances.

what I do is set the domain to be specific to my subdomain. (note this really
only works when doing subdomain stuff, if you're doing subroute things like
Amazon ALB.. then I dunno)

Having things be separated like this is good, since Cookie's can get big fast,
you can go over the max cookie size.

------
zellyn
It's interesting that they're comparing Go the language and Rails the
framework. Obviously, it's apples-to-oranges, but it makes sense that people
would think about it that way.

