rwadurian/backend/mpc-system/pkg/middleware/security.go

91 lines
2.7 KiB
Go

package middleware
import (
"github.com/gin-gonic/gin"
)
// SecurityConfig holds configuration for security headers middleware
type SecurityConfig struct {
// EnableHSTS enables HTTP Strict Transport Security header
EnableHSTS bool
// HSTSMaxAge is the max-age value for HSTS in seconds (default: 31536000 = 1 year)
HSTSMaxAge int
// EnableNoSniff enables X-Content-Type-Options: nosniff
EnableNoSniff bool
// EnableXSSFilter enables X-XSS-Protection header
EnableXSSFilter bool
// EnableFrameDeny enables X-Frame-Options: DENY
EnableFrameDeny bool
// ContentSecurityPolicy sets the Content-Security-Policy header
ContentSecurityPolicy string
// ReferrerPolicy sets the Referrer-Policy header
ReferrerPolicy string
}
// DefaultSecurityConfig returns a secure default configuration
func DefaultSecurityConfig() SecurityConfig {
return SecurityConfig{
EnableHSTS: true,
HSTSMaxAge: 31536000, // 1 year
EnableNoSniff: true,
EnableXSSFilter: true,
EnableFrameDeny: true,
ContentSecurityPolicy: "default-src 'self'",
ReferrerPolicy: "strict-origin-when-cross-origin",
}
}
// SecurityHeaders creates a middleware that adds security headers to responses
func SecurityHeaders(config SecurityConfig) gin.HandlerFunc {
return func(c *gin.Context) {
// Prevent MIME type sniffing
if config.EnableNoSniff {
c.Header("X-Content-Type-Options", "nosniff")
}
// XSS protection (legacy, but still useful for older browsers)
if config.EnableXSSFilter {
c.Header("X-XSS-Protection", "1; mode=block")
}
// Prevent clickjacking
if config.EnableFrameDeny {
c.Header("X-Frame-Options", "DENY")
}
// HTTP Strict Transport Security
if config.EnableHSTS {
hstsValue := "max-age=31536000; includeSubDomains"
if config.HSTSMaxAge > 0 {
hstsValue = "max-age=" + string(rune(config.HSTSMaxAge)) + "; includeSubDomains"
}
c.Header("Strict-Transport-Security", hstsValue)
}
// Content Security Policy
if config.ContentSecurityPolicy != "" {
c.Header("Content-Security-Policy", config.ContentSecurityPolicy)
}
// Referrer Policy
if config.ReferrerPolicy != "" {
c.Header("Referrer-Policy", config.ReferrerPolicy)
}
// Permissions Policy (formerly Feature-Policy)
c.Header("Permissions-Policy", "geolocation=(), microphone=(), camera=()")
// Cache control for API responses
c.Header("Cache-Control", "no-store, no-cache, must-revalidate, proxy-revalidate")
c.Header("Pragma", "no-cache")
c.Header("Expires", "0")
c.Next()
}
}
// SecureHeaders is a convenience function that applies default security headers
func SecureHeaders() gin.HandlerFunc {
return SecurityHeaders(DefaultSecurityConfig())
}