chore(test): add test for cache control and security headers
This commit is contained in:
96
main_test.go
96
main_test.go
@@ -30,14 +30,89 @@ var (
|
||||
port atomic.Int32
|
||||
)
|
||||
|
||||
func TestSecurity(t *testing.T) {
|
||||
func TestIntegrationSecurityHeader(t *testing.T) {
|
||||
t.Parallel()
|
||||
t.Run("should keep caching for static content", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
_, basePath, ctx := setupIntegrationTest(t)
|
||||
|
||||
req, err := http.NewRequestWithContext(ctx, "GET", basePath+"/static/favicon.svg", nil)
|
||||
assert.Nil(t, err)
|
||||
|
||||
resp, err := httpClient.Do(req)
|
||||
assert.Nil(t, err)
|
||||
|
||||
cacheControl := resp.Header.Get("Cache-Control")
|
||||
assert.Equal(t, "", cacheControl)
|
||||
})
|
||||
t.Run("should disable caching for dynamic content", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
_, basePath, ctx := setupIntegrationTest(t)
|
||||
|
||||
req, err := http.NewRequestWithContext(ctx, "GET", basePath, nil)
|
||||
assert.Nil(t, err)
|
||||
|
||||
resp, err := httpClient.Do(req)
|
||||
assert.Nil(t, err)
|
||||
|
||||
cacheControl := resp.Header.Get("Cache-Control")
|
||||
assert.Equal(t, "no-cache, no-store, must-revalidate", cacheControl)
|
||||
})
|
||||
t.Run("should include security headers", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
_, basePath, ctx := setupIntegrationTest(t)
|
||||
|
||||
req, err := http.NewRequestWithContext(ctx, "GET", basePath, nil)
|
||||
assert.Nil(t, err)
|
||||
|
||||
resp, err := httpClient.Do(req)
|
||||
assert.Nil(t, err)
|
||||
|
||||
value := resp.Header.Get("X-Content-Type-Options")
|
||||
assert.Equal(t, "nosniff", value)
|
||||
|
||||
value = resp.Header.Get("Access-Control-Allow-Origin")
|
||||
assert.Equal(t, basePath, value)
|
||||
|
||||
value = resp.Header.Get("Access-Control-Allow-Methods")
|
||||
assert.Equal(t, "GET, POST, DELETE", value)
|
||||
|
||||
value = resp.Header.Get("Content-Security-Policy")
|
||||
assert.Equal(t, "default-src 'none';"+
|
||||
"script-src 'self' https://umami.me-fit.eu"+
|
||||
"connect-src 'self' https://umami.me-fit.eu"+
|
||||
"img-src 'self'"+
|
||||
"style-src 'self'"+
|
||||
"form-action 'self'"+
|
||||
"frame-ancestors 'none'", value)
|
||||
|
||||
value = resp.Header.Get("Cross-Origin-Resource-Policy")
|
||||
assert.Equal(t, "same-origin", value)
|
||||
|
||||
value = resp.Header.Get("Cross-Origin-Opener-Policy")
|
||||
assert.Equal(t, "same-origin", value)
|
||||
|
||||
value = resp.Header.Get("Cross-Origin-Embedder-Policy")
|
||||
assert.Equal(t, "require-corp", value)
|
||||
|
||||
value = resp.Header.Get("Permissions-Policy")
|
||||
assert.Equal(t, "geolocation=(), camera=(), microphone=(), interest-cohort=()", value)
|
||||
|
||||
value = resp.Header.Get("Referrer-Policy")
|
||||
assert.Equal(t, "strict-origin-when-cross-origin", value)
|
||||
|
||||
value = resp.Header.Get("Strict-Transport-Security")
|
||||
assert.Equal(t, "max-age=63072000; includeSubDomains; preload", value)
|
||||
})
|
||||
}
|
||||
|
||||
func TestAuth(t *testing.T) {
|
||||
func TestIntegrationAuth(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
t.Run("should signin and return session cookie", func(t *testing.T) {
|
||||
t.Run("should return secure cookie on signin with generated csrf-token and session-id", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
db, basePath, ctx := setupIntegrationTest(t)
|
||||
@@ -46,9 +121,7 @@ func TestAuth(t *testing.T) {
|
||||
_, err := db.Exec(`
|
||||
INSERT INTO user (user_id, email, email_verified, is_admin, password, salt, created_at)
|
||||
VALUES (?, "mail@mail.de", FALSE, FALSE, ?, ?, datetime())`, uuid.New(), pass, []byte("salt"))
|
||||
if err != nil {
|
||||
t.Fatalf("Error inserting user: %v", err)
|
||||
}
|
||||
assert.Nil(t, err)
|
||||
|
||||
req, err := http.NewRequestWithContext(ctx, "GET", basePath+"/auth/signin", nil)
|
||||
assert.Nil(t, err)
|
||||
@@ -73,7 +146,7 @@ func TestAuth(t *testing.T) {
|
||||
req, err = http.NewRequestWithContext(ctx, "POST", basePath+"/api/auth/signin", strings.NewReader(formData.Encode()))
|
||||
assert.Nil(t, err)
|
||||
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
|
||||
req.Header.Set("Cookie", anonymousSession.Name+"="+anonymousSession.Value)
|
||||
req.Header.Set("Cookie", "id="+anonymousSession.Value)
|
||||
|
||||
resp, err = httpClient.Do(req)
|
||||
assert.Nil(t, err)
|
||||
@@ -81,11 +154,10 @@ func TestAuth(t *testing.T) {
|
||||
assert.Equal(t, http.StatusSeeOther, resp.StatusCode)
|
||||
|
||||
cookie := findCookie(resp, "id")
|
||||
if cookie == nil {
|
||||
t.Fatalf("No session cookie found")
|
||||
} else if cookie.SameSite != http.SameSiteStrictMode || cookie.HttpOnly != true || cookie.Secure != true {
|
||||
t.Fatalf("Cookie is not secure")
|
||||
}
|
||||
assert.NotNil(t, cookie)
|
||||
assert.Equal(t, http.SameSiteStrictMode, cookie.SameSite, "Cookie is not secure")
|
||||
assert.True(t, cookie.HttpOnly, "Cookie is not secure")
|
||||
assert.True(t, cookie.Secure, "Cookie is not secure")
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user