mirror of
https://github.com/pocket-id/pocket-id.git
synced 2025-12-10 17:23:19 +03:00
54 lines
1.3 KiB
Go
54 lines
1.3 KiB
Go
package middleware
|
|
|
|
import (
|
|
"crypto/rand"
|
|
"encoding/base64"
|
|
|
|
"github.com/gin-gonic/gin"
|
|
)
|
|
|
|
// CspMiddleware sets a Content Security Policy header and, when possible,
|
|
// includes a per-request nonce for inline scripts.
|
|
type CspMiddleware struct{}
|
|
|
|
func NewCspMiddleware() *CspMiddleware { return &CspMiddleware{} }
|
|
|
|
// GetCSPNonce returns the CSP nonce generated for this request, if any.
|
|
func GetCSPNonce(c *gin.Context) string {
|
|
if v, ok := c.Get("csp_nonce"); ok {
|
|
if s, ok := v.(string); ok {
|
|
return s
|
|
}
|
|
}
|
|
return ""
|
|
}
|
|
|
|
func (m *CspMiddleware) Add() gin.HandlerFunc {
|
|
return func(c *gin.Context) {
|
|
// Generate a random base64 nonce for this request
|
|
nonce := generateNonce()
|
|
c.Set("csp_nonce", nonce)
|
|
|
|
csp := "default-src 'self'; " +
|
|
"base-uri 'self'; " +
|
|
"object-src 'none'; " +
|
|
"frame-ancestors 'none'; " +
|
|
"form-action 'self'; " +
|
|
"img-src * blob:;" +
|
|
"font-src 'self'; " +
|
|
"style-src 'self' 'unsafe-inline'; " +
|
|
"script-src 'self' 'nonce-" + nonce + "'"
|
|
|
|
c.Writer.Header().Set("Content-Security-Policy", csp)
|
|
c.Next()
|
|
}
|
|
}
|
|
|
|
func generateNonce() string {
|
|
b := make([]byte, 16)
|
|
if _, err := rand.Read(b); err != nil {
|
|
return "" // if generation fails, return empty; policy will omit nonce
|
|
}
|
|
return base64.RawURLEncoding.EncodeToString(b)
|
|
}
|