@@ -0,0 +1,96 @@
|
||||
package web
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"net/url"
|
||||
"testing"
|
||||
|
||||
"github.com/justinas/nosurf"
|
||||
)
|
||||
|
||||
func TestSecureHeaders(t *testing.T) {
|
||||
rr := httptest.NewRecorder()
|
||||
|
||||
r, err := http.NewRequest(http.MethodGet, "/", nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
next := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
w.Write([]byte("OK"))
|
||||
})
|
||||
|
||||
secureHeaders(next).ServeHTTP(rr, r)
|
||||
|
||||
rs := rr.Result()
|
||||
|
||||
expectedValue := "default-src 'self'; style-src 'self'; style-src-attr 'unsafe-inline'; script-src 'self'; img-src 'self' data: blob:; media-src 'self' blob:; manifest-src 'self'; connect-src 'self'"
|
||||
if got := rs.Header.Get("Content-Security-Policy"); got != expectedValue {
|
||||
t.Errorf("Content-Security-Policy: got %q, want %q", got, expectedValue)
|
||||
}
|
||||
|
||||
expectedValue = "strict-origin-when-cross-origin"
|
||||
if got := rs.Header.Get("Referrer-Policy"); got != expectedValue {
|
||||
t.Errorf("Referrer-Policy: got %q, want %q", got, expectedValue)
|
||||
}
|
||||
|
||||
expectedValue = "nosniff"
|
||||
if got := rs.Header.Get("X-Content-Type-Options"); got != expectedValue {
|
||||
t.Errorf("X-Content-Type-Options: got %q, want %q", got, expectedValue)
|
||||
}
|
||||
|
||||
expectedValue = "deny"
|
||||
if got := rs.Header.Get("X-Frame-Options"); got != expectedValue {
|
||||
t.Errorf("X-Frame-Options: got %q, want %q", got, expectedValue)
|
||||
}
|
||||
if got := rs.Header.Get("Permissions-Policy"); got != "camera=(self), microphone=(self)" {
|
||||
t.Errorf("Permissions-Policy: got %q, want %q", got, "camera=(self), microphone=(self)")
|
||||
}
|
||||
|
||||
if rs.StatusCode != http.StatusOK {
|
||||
t.Errorf("status: got %d, want %d", rs.StatusCode, http.StatusOK)
|
||||
}
|
||||
|
||||
defer rs.Body.Close()
|
||||
body, err := io.ReadAll(rs.Body)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
body = bytes.TrimSpace(body)
|
||||
|
||||
if got := string(body); got != "OK" {
|
||||
t.Errorf("body: got %q, want %q", got, "OK")
|
||||
}
|
||||
}
|
||||
|
||||
func TestNoSurfAcceptsSameOriginHTTPFromLAN(t *testing.T) {
|
||||
app := &application{config: Config{CookieSecure: false}}
|
||||
handler := app.noSurf(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
if r.Method == http.MethodGet {
|
||||
_, _ = w.Write([]byte(nosurf.Token(r)))
|
||||
return
|
||||
}
|
||||
w.WriteHeader(http.StatusNoContent)
|
||||
}))
|
||||
|
||||
getRequest := httptest.NewRequest(http.MethodGet, "http://192.168.1.50:4040/login", nil)
|
||||
getResponse := httptest.NewRecorder()
|
||||
handler.ServeHTTP(getResponse, getRequest)
|
||||
|
||||
csrfCookie := getResponse.Result().Cookies()[0]
|
||||
form := url.Values{"csrf_token": {getResponse.Body.String()}}
|
||||
postRequest := httptest.NewRequest(http.MethodPost, "http://192.168.1.50:4040/login", bytes.NewBufferString(form.Encode()))
|
||||
postRequest.Header.Set("Content-Type", "application/x-www-form-urlencoded")
|
||||
postRequest.Header.Set("Origin", "http://192.168.1.50:4040")
|
||||
postRequest.AddCookie(csrfCookie)
|
||||
postResponse := httptest.NewRecorder()
|
||||
|
||||
handler.ServeHTTP(postResponse, postRequest)
|
||||
|
||||
if postResponse.Code != http.StatusNoContent {
|
||||
t.Fatalf("status: got %d, want %d", postResponse.Code, http.StatusNoContent)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user