CSRF Protection for gorilla/sessions in the Go Language
CSRFBanana is a middleware package that helps prevent cross-site request forgery attacks. The package can generate tokens per session or per page. Tokens can also be regenerated after a successful or failed attempt to validate.
In this package, the CSRF tokens are stored in the (same) session cookie that is handled by gorilla/sessions. You can read about the different CSRF approaches on StackOverflow: Why is it common to put CSRF prevention tokens in cookies?
Import the package:
import "github.com/josephspurrier/csrfbanana"
Configure the package as middleware:
// Default handler
h := http.HandlerFunc(YourOwnDefaultFunction)
// Insert the CSRFBanana here to prevent CSRF
cs := csrfbanana.New(h, Store, SessionName)
// Set error page for CSRF failures
cs.FailureHandler(http.HandlerFunc(routeInvalidToken))
// Generate a new token after each success/failure (also prevents double submits)
cs.ClearAfterUsage(true)
// Exclude routes like /static/ from token generation/checking
cs.ExcludeRegexPaths([]string{"/static(.*)"})
// Set the token length (default is 32)
csrfbanana.TokenLength = 32
// Set the token name used in the forms and session (default is token)
csrfbanana.TokenName = "token"
// Set the token to generate per page (false - the default) or per session (true)
csrfbanana.SingleToken = false
// Pass the handler to your HTTP server
http.ListenAndServe(":80", cs)
Generate the token before passing to your templates:
// Create a map for the template
vars := make(map[string]string)
// Store the CSRF token to the map
vars["token"] = csrfbanana.Token(w, r, sess)
// Show the template
templ.Execute(w, vars)
Add the token to every POST form that is not excluded by ExcludeRegexPaths():
<input type="hidden" name="token" value="{{.token}}">
Note: Any other POST operation needs to either include the token or be added to ExcludeRegexPaths().
To see the example in action, use the following commands:
go get github.com/josephspurrier/csrfbanana/example
go run src/github.com/josephspurrier/csrfbanana/example/example.go
Thanks to Justinas Stankevičius for his CSRF package which I used as a solid example.