csrf.go 1.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748
  1. // Copyright 2017 Frédéric Guillot. All rights reserved.
  2. // Use of this source code is governed by the Apache 2.0
  3. // license that can be found in the LICENSE file.
  4. package middleware
  5. import (
  6. "context"
  7. "github.com/miniflux/miniflux2/helper"
  8. "log"
  9. "net/http"
  10. )
  11. func Csrf(next http.Handler) http.Handler {
  12. return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  13. var csrfToken string
  14. csrfCookie, err := r.Cookie("csrfToken")
  15. if err == http.ErrNoCookie || csrfCookie.Value == "" {
  16. csrfToken = helper.GenerateRandomString(64)
  17. cookie := &http.Cookie{
  18. Name: "csrfToken",
  19. Value: csrfToken,
  20. Path: "/",
  21. Secure: r.URL.Scheme == "https",
  22. HttpOnly: true,
  23. }
  24. http.SetCookie(w, cookie)
  25. } else {
  26. csrfToken = csrfCookie.Value
  27. }
  28. ctx := r.Context()
  29. ctx = context.WithValue(ctx, "CsrfToken", csrfToken)
  30. w.Header().Add("Vary", "Cookie")
  31. isTokenValid := csrfToken == r.FormValue("csrf") || csrfToken == r.Header.Get("X-Csrf-Token")
  32. if r.Method == "POST" && !isTokenValid {
  33. log.Println("[Middleware:CSRF] Invalid or missing CSRF token!")
  34. w.WriteHeader(http.StatusBadRequest)
  35. w.Write([]byte("Invalid or missing CSRF token!"))
  36. } else {
  37. next.ServeHTTP(w, r.WithContext(ctx))
  38. }
  39. })
  40. }