Skip to content

Commit

Permalink
webapi: Add test for securecookie error.
Browse files Browse the repository at this point in the history
A simple test to ensure an error string returned by the securecookie lib
does not change when we upgrade to newer versions. Important because
vspd checks for this error using string comparison.
  • Loading branch information
jholdstock committed Aug 15, 2023
1 parent de79ce7 commit 27acf0e
Show file tree
Hide file tree
Showing 2 changed files with 71 additions and 1 deletion.
5 changes: 4 additions & 1 deletion webapi/middleware.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@ import (
"golang.org/x/time/rate"
)

// This is a hard-coded string from the securecookie library.
const invalidCookieErr = "securecookie: the value is not valid"

// rateLimit middleware limits how many requests each client IP can submit per
// second. If the limit is exceeded the limitExceeded handler will be executed
// and the context will be aborted.
Expand Down Expand Up @@ -67,7 +70,7 @@ func (s *Server) withSession(store *sessions.CookieStore) gin.HandlerFunc {
// "value is not valid" occurs if the cookie secret changes. This is
// common during development (eg. when using the test harness) but
// it should not occur in production.
if strings.Contains(err.Error(), "securecookie: the value is not valid") {
if strings.Contains(err.Error(), invalidCookieErr) {
s.log.Warn("Cookie secret has changed. Generating new session.")

// Persist the newly generated session.
Expand Down
67 changes: 67 additions & 0 deletions webapi/middleware_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
// Copyright (c) 2023 The Decred developers
// Use of this source code is governed by an ISC
// license that can be found in the LICENSE file.

package webapi

import (
"net/http"
"net/http/httptest"
"strings"
"testing"

"github.com/gorilla/sessions"
)

// NOTE: This test does not test any vspd code.
//
// If the cookie store secret changes unexpectedly (common during development)
// the securecookie library returns an error with a hard-coded, non-exported
// string.
//
// "securecookie: the value is not valid"
//
// TestCookieSecretError ensures the string returned by the lib does not change,
// which is important because vspd checks for the error using string comparison.
func TestCookieSecretError(t *testing.T) {

// Create a cookie store, get a cookie from it.

store := sessions.NewCookieStore([]byte("first secret"))

req, err := http.NewRequest(http.MethodPost, "/", nil)
if err != nil {
t.Fatal(err)
}

session, err := store.Get(req, "key")
if err != nil {
t.Fatal(err)
}

w := httptest.NewRecorder()
err = store.Save(req, w, session)
if err != nil {
t.Fatal(err)
}

cookie := w.Result().Header["Set-Cookie"][0]

// Create another cookie store using a different secret, send cookie from
// first store to the new store, confirm error is correct.

store2 := sessions.NewCookieStore([]byte("second secret"))

req2, err := http.NewRequest(http.MethodPost, "/", nil)
if err != nil {
t.Fatal(err)
}
req2.Header.Add("Cookie", cookie)

_, err = store2.Get(req2, "key")

if !strings.Contains(err.Error(), invalidCookieErr) {
t.Fatalf("securecookie library returned unexpected error, wanted %q, got %q",
invalidCookieErr, err.Error())
}
}

0 comments on commit 27acf0e

Please sign in to comment.