CSRF protection for golang projects.
context.go | ||
cookies.go | ||
go.mod | ||
LICENSE.md | ||
Makefile | ||
middleware.go | ||
README.md | ||
token.go | ||
token_test.go |
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,
},
});
}