18

I wrote a web application that set a cookie and delete it. To clarify to scenario what I mean look at the following code snippet.

package main

import (
    "fmt"
    "github.com/gorilla/mux"
    "net/http"
    "time"
)

func rootHandler(rw http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(rw, "Hello Foo")

}

func setCookieHandler(rw http.ResponseWriter, r *http.Request) {
    c := &http.Cookie{
        Name:     "storage",
        Value:    "value",
        Path:     "/",
        MaxAge:   0,
        HttpOnly: true,
    }

    http.SetCookie(rw, c)
}

func deleteCookieHandler(rw http.ResponseWriter, r *http.Request) {

    c, err := r.Cookie("storage")
    if err != nil {
        panic(err.Error())
    }
    c.Name = "Deleted"
    c.Value = "Unuse"
    c.Expires = time.Unix(1414414788, 1414414788000)
}

func readCookieHandler(rw http.ResponseWriter, r *http.Request) {

    c, err := r.Cookie("storage")
    if err != nil {
        panic(err.Error())
    }
    fmt.Println(c.Expires)
}

func evaluateCookieHandler(rw http.ResponseWriter, r *http.Request) {

    c, err := r.Cookie("storage")
    if err != nil {
        panic(err.Error())
    }

    if time.Now().After(c.Expires) {
        fmt.Println("Cookie is expired.")
    }
}

func main() {
    mux := mux.NewRouter()
    mux.HandleFunc("/", rootHandler)
    mux.HandleFunc("/cookie", setCookieHandler)
    mux.HandleFunc("/delete", deleteCookieHandler)
    mux.HandleFunc("/read", readCookieHandler)
    mux.HandleFunc("/eval", evaluateCookieHandler)

    http.ListenAndServe(":3000", mux)
}

As you can see, when I visit /cookie location, it will be set a cookie as expected. Then when I call /delete, it should change the name, value and expired time from cookie. The expired time is changed, but name and value not.

enter image description here

What do I want is, to delete the cookie from browser for sign out in a authentication system, when user click sign out button to delete cookie.
I also discover this link and follow the advice, but does not work as expected.

Community
  • 1
  • 1
softshipper
  • 32,463
  • 51
  • 192
  • 400

3 Answers3

33

To delete a cookie named "storage", sending set-cookie with the same cookie name.

deleteCookieHandler() should be as follows

c := &http.Cookie{
    Name:     "storage",
    Value:    "",
    Path:     "/",
    Expires: time.Unix(0, 0),

    HttpOnly: true,
}

http.SetCookie(rw, c)
hisatoria
  • 431
  • 1
  • 4
  • 5
18

MaxAge=0 means no 'Max-Age' attribute specified.

MaxAge<0 means delete cookie now, equivalently 'Max-Age: 0'

MaxAge>0 means Max-Age attribute present and given in seconds

c := &http.Cookie{
    Name:     "storage",
    Value:    "",
    Path:     "/",
    MaxAge:   -1,
    HttpOnly: true,
}

http.SetCookie(rw, c)
Nail Khunafin
  • 189
  • 1
  • 3
  • actually according to mozilla: "Number of seconds until the cookie expires. A zero or negative number will expire the cookie immediately. If both Expires and Max-Age are set, Max-Age has precedence." -- see here: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie – dmaixner Jul 22 '20 at 13:54
  • 1
    @dmaixner You're correct according to the cookie spec, but this answer is correct when dealing with the golang `http.Cookie` struct: https://golang.org/src/net/http/cookie.go – Kelsin Oct 03 '20 at 23:33
  • I can confirm -- this worked for me. – warvariuc Dec 20 '21 at 14:46
12

Cookies are keyed by name, so when you "change" the name, you actually "create" a different cookie, already expired.

Keep the name the same and it should work, but don't forget to take some time one day to read about cookies and how they work.

Thomas Broyer
  • 64,353
  • 7
  • 91
  • 164
  • First of all, thanks for answer. Do you mean, that I should set only expires field? – softshipper Dec 27 '14 at 20:38
  • Expires should be enough yes. Setting an empty or "short" value helps cut the payload and avoid leaking data in some cases. – Thomas Broyer Dec 27 '14 at 22:33
  • 1
    Do not use the Expires field, use a negative Max-Age instead. Reason: much saner, less traffic, works with unsynchronised clocks. One more thing to pay attention to: Cookies are not only keyed by name but also by path (and domain): Set the explicitly during deletion. – Volker Dec 27 '14 at 23:31
  • I change my codes https://gist.github.com/kostonstyle/91d8b8fa87628fa300da. Consider the deleteCookieHandler, I set the max-age negative and when I call /delete path, the max-age stay unchanged, when I look in the browser the cookie. The cookie does not have the max-age in the past. Try the example, and you will see what I mean. – softshipper Dec 28 '14 at 17:31
  • I figure out, I forgot http.SetCookie(rw, c) at the end from deleteCookieHandler function. – softshipper Dec 28 '14 at 18:25
  • @Volker IE8 and below don't support Max-Age. http://mrcoles.com/blog/cookies-max-age-vs-expires/ – volker238 Mar 18 '16 at 15:28