Browse Source

fix: CSRF sending masked token

security-updates
nic 3 months ago
parent
commit
6dee48b92a
  1. 1
      apps/web/main.go
  2. 30
      internal/middleware/csrf_expose.go
  3. 13
      templates/layout.html

1
apps/web/main.go

@ -119,6 +119,7 @@ func main() {
protected.Use(middleware.CSRFSimple) protected.Use(middleware.CSRFSimple)
} else { } else {
protected.Use(csrfMw) protected.Use(csrfMw)
protected.Use(middleware.CSRFExposeToken)
} }
} }

30
internal/middleware/csrf_expose.go

@ -0,0 +1,30 @@
package middleware
import (
"net/http"
"strings"
"github.com/gorilla/csrf"
)
// CSRFExposeToken sets a readable cookie with the per-request masked CSRF token on safe methods.
func CSRFExposeToken(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
switch r.Method {
case http.MethodGet, http.MethodHead, http.MethodOptions:
token := csrf.Token(r)
if token != "" {
secure := r.TLS != nil || strings.EqualFold(r.Header.Get("X-Forwarded-Proto"), "https")
http.SetCookie(w, &http.Cookie{
Name: "XSRF-TOKEN-VALUE",
Value: token,
Path: "/",
HttpOnly: false,
Secure: secure,
SameSite: http.SameSiteLaxMode,
})
}
}
next.ServeHTTP(w, r)
})
}

13
templates/layout.html

@ -7,13 +7,16 @@
<title>ServiceTrade Tools</title> <title>ServiceTrade Tools</title>
<script src="https://unpkg.com/htmx.org@1.9.6"></script> <script src="https://unpkg.com/htmx.org@1.9.6"></script>
<script> <script>
// Read XSRF-TOKEN cookie and send as X-CSRF-Token on all htmx requests // Send CSRF token on all htmx requests: prefer masked token cookie (XSRF-TOKEN-VALUE), fallback to storage token (XSRF-TOKEN)
document.addEventListener('DOMContentLoaded', function () { document.addEventListener('DOMContentLoaded', function () {
function readCookie(name) {
var re = new RegExp('(?:^|; )' + name.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&') + '=([^;]+)');
var m = document.cookie.match(re);
return m ? decodeURIComponent(m[1]) : null;
}
document.body.addEventListener('htmx:configRequest', function (evt) { document.body.addEventListener('htmx:configRequest', function (evt) {
var m = document.cookie.match(/(?:^|; )XSRF-TOKEN=([^;]+)/); var token = readCookie('XSRF-TOKEN-VALUE') || readCookie('XSRF-TOKEN');
if (m) { if (token) { evt.detail.headers['X-CSRF-Token'] = token; }
try { evt.detail.headers['X-CSRF-Token'] = decodeURIComponent(m[1]); } catch (e) { }
}
}); });
}); });
</script> </script>

Loading…
Cancel
Save