CSRF protection for golang projects.
Find a file
2025-06-11 23:54:29 +05:00
context.go Initial commit 2025-06-11 00:24:24 +05:00
cookies.go Initial commit 2025-06-11 00:24:24 +05:00
go.mod Update repository path 2025-06-11 23:54:29 +05:00
LICENSE.md Initial commit 2025-06-11 00:24:24 +05:00
Makefile Initial commit 2025-06-11 00:24:24 +05:00
middleware.go Initial commit 2025-06-11 00:24:24 +05:00
README.md Update repository path 2025-06-11 23:54:29 +05:00
token.go Initial commit 2025-06-11 00:24:24 +05:00
token_test.go Initial commit 2025-06-11 00:24:24 +05:00

CSRF protection

A golang library that implements CSRF protection.

Implementation

This library sets a cookie with a random token. Every unsafe request (POST, PUT, DELETE, etc.) must contain a copy of this token in a form field or HTTP header.

Usage

package main

import (
	"net/http"

	"code.app-house.ru/go/csrf"
)

func main() {
	r := http.NewServeMux()
	csrfProtection := csrf.New()

	// You can change field or header name (as well as other settings):
	// csrfProtection.FormFieldName = "foo"
	// csrfProtection.HeaderName = "bar"

	http.ListenAndServe(":8000", csrfProtection.Middleware(r))
}

Option 1: add a hidden input to all forms that use unsafe methods:

<input type="hidden" name="{{ .CsrfFieldName }}" value="{{ .CsrfToken }}" />

Your HTTP handler may look like this:

template.Execute(w, yourViewModel{
	CsrfFieldName: csrfProtection.FieldName,
	CsrfToken: csrf.GetCSRFToken(r.Context()),
})

Option 2: provide a token using JavaScript:

/**
 * Copied from https://docs.djangoproject.com/en/5.2/howto/csrf/.
 * @param {string} name - Cookie name.
 * @returns {string | null}
 */
function getCookie(name) {
  let cookieValue = null;
  if (document.cookie && document.cookie !== "") {
    const cookies = document.cookie.split(";");
    for (let i = 0; i < cookies.length; i++) {
      const cookie = cookies[i].trim();
      // Does this cookie string begin with the name we want?
      if (cookie.substring(0, name.length + 1) === name + "=") {
        cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
        break;
      }
    }
  }
  return cookieValue;
}

async function makeRequest() {
  const csrfToken = getCookie("csrfmiddlewaretoken");
  await fetch("/handler", {
    method: "POST",
    headers: {
      "X-CSRFToken": csrfToken,
    },
  });
}