Cross-Site Request Forgery

Middleware csrf generates and validates CSRF tokens for Macaron Instances.

Installation

go get github.com/go-macaron/csrf

Usage

To use this middleware, you have to register session first.

package main
import (
"github.com/go-macaron/csrf"
"github.com/go-macaron/session"
"gopkg.in/macaron.v1"
)
func main() {
m := macaron.Classic()
m.Use(macaron.Renderer())
m.Use(session.Sessioner())
m.Use(csrf.Csrfer())
// Simulate the authentication of a session.
// If uid exists redirect to a form that requires CSRF protection.
m.Get("/", func(ctx *macaron.Context, sess session.Store) {
if sess.Get("uid") == nil {
ctx.Redirect("/login")
return
}
ctx.Redirect("/protected")
})
// Set uid for the session.
m.Get("/login", func(ctx *macaron.Context, sess session.Store) {
sess.Set("uid", 123456)
ctx.Redirect("/")
})
// Render a protected form. Passing a csrf token by calling x.GetToken()
m.Get("/protected", func(ctx *macaron.Context, sess session.Store, x csrf.CSRF) {
if sess.Get("uid") == nil {
ctx.Redirect("/login", 401)
return
}
// Pass token to the protected template.
ctx.Data["csrf_token"] = x.GetToken()
ctx.HTML(200, "protected")
})
// Apply CSRF validation to route.
m.Post("/protected", csrf.Validate, func(ctx *macaron.Context, sess session.Store) {
if sess.Get("uid") != nil {
ctx.RenderData(200, []byte("You submitted a valid token"))
return
}
ctx.Redirect("/login", 401)
})
m.Run()
}
<!-- templates/protected.tmpl -->
<form action="/protected" method="post">
<input type="hidden" name="_csrf" value="{{.csrf_token}}">
<button>Submit</button>
</form>

Options

csrf.Csrfer comes with a variety of configuration options:

// ...
m.Use(csrf.Csrfer(csrf.Options{
// The global secret value used to generate Tokens. Default is a random string.
Secret: "mysecret",
// HTTP header used to set and get token. Default is "X-CSRFToken".
Header: "X-CSRFToken",
// Form value used to set and get token. Default is "_csrf".
Form: "_csrf",
// Cookie value used to set and get token. Default is "_csrf".
Cookie: "_csrf",
// Cookie path. Default is "/".
CookiePath: "/",
// Key used for getting the unique ID per user. Default is "uid".
SessionKey: "uid",
// If true, send token via header. Default is false.
SetHeader: false,
// If true, send token via cookie. Default is false.
SetCookie: false,
// Set the Secure flag to true on the cookie. Default is false.
Secure: false,
// Disallow Origin appear in request header. Default is false.
Origin: false,
// The function called when Validate fails. Default is a simple error print.
ErrorFunc: func(w http.ResponseWriter) {
http.Error(w, "Invalid csrf token.", http.StatusBadRequest)
},
}))
// ...