Mike Warren
Mike Warren

Reputation: 3866

Golang cookie not deleting

In trying to test the following code:

//SetSingleSignOn Sets the cookie to allow for single sign cross applications.
func SetSingleSignOn(w http.ResponseWriter, token string) {
    http.SetCookie(w, &http.Cookie{
        Name:     ssoCookie,
        Value:    token,
        Path:     "/",
        HttpOnly: false,
        Secure:   false,
        Domain:   "localhost",
        Expires:  time.Now().AddDate(0, 0, 7),
        MaxAge:   0,
    })
}

//DestroySingleSignOn Gets rid of single sign on, in case a user logs out of the application.
func DestroySingleSignOn(r *http.Request, w http.ResponseWriter) {
    cookie, err := r.Cookie(ssoCookie)
    if err != nil || cookie.Value == "" {
        return
    }

    cookie = &http.Cookie{
        Name:     ssoCookie,
        Path:     "/",
        HttpOnly: false,
        Secure:   false,
        Domain:   "localhost",
        Expires:  time.Now(),
        MaxAge:   -1}

    http.SetCookie(w, cookie)
}

I come across an apparent false fail.

All my tests against SetSingleSignOn pass, but the sanity test against DestroySingleSignOn fails.

The test

looks something like this:

t.Run("SignedOnFirst", func(t *testing.T) {

    req := httptest.NewRequest("POST",
        "localhost:42100",
        nil)
    w := httptest.NewRecorder()

    SetSingleSignOn(w, "12446rewa12314")

    // assert.NotPanics(t, func() { DestroySingleSignOn(req, w) })
    DestroySingleSignOn(req, w)

    // get the cookie
    res := w.Result()
    fmt.Println(res.Cookies())

    assert.Equal(t, 1, len(res.Cookies()))
    cookie := *res.Cookies()[0]
    // cookie should be named ssoCookie
    assert.Equal(t,
        ssoCookie,
        cookie.Name)

    // cookie should have already expired
    assert.True(t,
        time.Now().After(cookie.Expires))

})

It's as if the http.SetCookie(w, cookie) was never invoked at all! Even more bizarre, is when I scrap the function call for straight up

http.SetCookie(w, &http.Cookie{
    Name:     ssoCookie,
    Path:     "/",
    HttpOnly: false,
    Secure:   false,
    Domain:   "localhost",
    Expires:  time.Now(),
    MaxAge:   -1}

it seems to work (the last cookie is inactive), but now there's two cookies in res.Cookies()!

What could be causing this?

Upvotes: 1

Views: 1164

Answers (1)

Gavin
Gavin

Reputation: 4515

In your DestorySingleSignOn function, you begin with this block:

cookie, err := r.Cookie(ssoCookie)
if err != nil || cookie.Value == "" {
    return
}

Notice, you are checking for the cookie on the request, but the cookie has only been set on the response. You would need to issue a request to get the initial cookie set, and then issue a second request with that cookie for this to work.

t.Run("SignedOnFirst", func(t *testing.T) {

    req := httptest.NewRequest("POST",
        "localhost:42100",
        nil)
    w := httptest.NewRecorder()

    SetSingleSignOn(w, "12446rewa12314")

    // get the initial cookie
    res := w.Result()
    cookie := res.Cookies()[0]

    // issue a second request with the cookie
    req = httptest.NewRequest("POST",
        "localhost:42100",
        nil)
    req.AddCookie(cookie)
    w = httptest.NewRecorder()

    // assert.NotPanics(t, func() { DestroySingleSignOn(req, w) })
    DestroySingleSignOn(req, w)

    // get the new cookie
    res = w.Result()
    fmt.Println(res.Cookies())

    assert.Equal(t, 1, len(res.Cookies()))
    cookie = *res.Cookies()[0]
    // cookie should be named ssoCookie
    assert.Equal(t,
        ssoCookie,
        cookie.Name)

    // cookie should have already expired
    assert.True(t,
        time.Now().After(cookie.Expires))

})

Upvotes: 3

Related Questions