Documentation
¶
Overview ¶
Package nosurf implements an HTTP handler that mitigates Cross-Site Request Forgery Attacks.
Index ¶
- Constants
- Variables
- func NewPure(handler http.Handler) http.Handler
- func Reason(req *http.Request) error
- func StaticOrigins(origins ...string) (func(r *url.URL) bool, error)
- func Token(req *http.Request) string
- func VerifyToken(realToken, sentToken string) bool
- type CSRFHandler
- func (h *CSRFHandler) ExemptFunc(fn func(r *http.Request) bool)
- func (h *CSRFHandler) ExemptGlob(pattern string)
- func (h *CSRFHandler) ExemptGlobs(patterns ...string)
- func (h *CSRFHandler) ExemptPath(path string)
- func (h *CSRFHandler) ExemptPaths(paths ...string)
- func (h *CSRFHandler) ExemptRegexp(re interface{})
- func (h *CSRFHandler) ExemptRegexps(res ...interface{})
- func (h *CSRFHandler) IsExempt(r *http.Request) bool
- func (h *CSRFHandler) RegenerateToken(w http.ResponseWriter, r *http.Request) string
- func (h *CSRFHandler) ServeHTTP(w http.ResponseWriter, r *http.Request)
- func (h *CSRFHandler) SetBaseCookie(cookie http.Cookie)
- func (h *CSRFHandler) SetFailureHandler(handler http.Handler)
- func (h *CSRFHandler) SetIsAllowedOriginFunc(f func(*url.URL) bool)
- func (h *CSRFHandler) SetIsTLSFunc(f func(*http.Request) bool)
Constants ¶
const ( // the name of CSRF cookie CookieName = "csrf_token" // the name of the form field FormFieldName = "csrf_token" // the name of CSRF header HeaderName = "X-CSRF-Token" // the HTTP status code for the default failure handler FailureCode = 400 // Max-Age in seconds for the default base cookie. 365 days. MaxAge = 365 * 24 * 60 * 60 )
Variables ¶
var ( ErrNoReferer = errors.New("A secure request contained no Referer or its value was malformed") ErrBadReferer = errors.New("A secure request's Referer comes from a different origin" + " from the request's URL") ErrBadOrigin = errors.New("Request was made with a disallowed origin specified in the Origin header") ErrBadToken = errors.New("The CSRF token in the cookie doesn't match the one" + " received in a form/header.") )
reasons for CSRF check failures
Functions ¶
func Reason ¶
Reason takes an HTTP request and returns the reason of failure of the CSRF check for that request
Note that the same availability restrictions apply for Reason() as for Token().
func StaticOrigins ¶ added in v1.2.0
StaticOrigins returns a delegate, suitable for passing to CSRFHandler.SetIsAllowedOriginFunc, that validates the request origin against a static list of allowed origins. This function expects each element to be of form `scheme://host`, e.g.: `https://example.com`, `http://example.org`. If any element of the slice is an invalid URL, this function will return an error. If an element includes additional URL parts (e.g. a path), these parts will be ignored, as origin checks only take the scheme and host into account.
Example:
h := nosurf.New()
origins, err := nosurf.StaticOrigins("https://api.example.com", "http://insecure.example.com")
if err != nil {
panic(err)
}
h.SetIsAllowedOriginFunc(origins)
func Token ¶
Token takes an HTTP request and returns the CSRF token for that request or an empty string if the token does not exist.
Note that the token won't be available after CSRFHandler finishes (that is, in another handler that wraps it, or after the request has been served)
func VerifyToken ¶
VerifyToken verifies the sent token equals the real one and returns a bool value indicating if tokens are equal. Supports masked tokens. realToken comes from Token(r) and sentToken is token sent unusual way.
Types ¶
type CSRFHandler ¶
type CSRFHandler struct {
// contains filtered or unexported fields
}
func New ¶
func New(handler http.Handler) *CSRFHandler
Constructs a new CSRFHandler that calls the specified handler if the CSRF check succeeds.
func (*CSRFHandler) ExemptFunc ¶
func (h *CSRFHandler) ExemptFunc(fn func(r *http.Request) bool)
func (*CSRFHandler) ExemptGlob ¶
func (h *CSRFHandler) ExemptGlob(pattern string)
Exempts URLs that match the specified glob pattern (as used by filepath.Match()) from CSRF checks
Note that ExemptGlob() is unable to detect syntax errors, because it doesn't have a path to check it against and filepath.Match() doesn't report an error if the path is empty. If we find a way to check the syntax, ExemptGlob MIGHT PANIC on a syntax error in the future. ALWAYS check your globs for syntax errors.
func (*CSRFHandler) ExemptGlobs ¶
func (h *CSRFHandler) ExemptGlobs(patterns ...string)
A variadic argument version of ExemptGlob()
func (*CSRFHandler) ExemptPath ¶
func (h *CSRFHandler) ExemptPath(path string)
Exempts an exact path from CSRF checks With this (and other Exempt* methods) you should take note that Go's paths include a leading slash.
func (*CSRFHandler) ExemptPaths ¶
func (h *CSRFHandler) ExemptPaths(paths ...string)
A variadic argument version of ExemptPath()
func (*CSRFHandler) ExemptRegexp ¶
func (h *CSRFHandler) ExemptRegexp(re interface{})
Accepts a regular expression string or a compiled *regexp.Regexp and exempts URLs that match it from CSRF checks.
If the given argument is neither of the accepted values, or the given string fails to compile, ExemptRegexp() panics.
func (*CSRFHandler) ExemptRegexps ¶
func (h *CSRFHandler) ExemptRegexps(res ...interface{})
A variadic argument version of ExemptRegexp()
func (*CSRFHandler) IsExempt ¶
func (h *CSRFHandler) IsExempt(r *http.Request) bool
Checks if the given request is exempt from CSRF checks. It checks the ExemptFunc first, then the exact paths, then the globs and finally the regexps.
func (*CSRFHandler) RegenerateToken ¶
func (h *CSRFHandler) RegenerateToken(w http.ResponseWriter, r *http.Request) string
Generates a new token, sets it on the given request and returns it
func (*CSRFHandler) ServeHTTP ¶
func (h *CSRFHandler) ServeHTTP(w http.ResponseWriter, r *http.Request)
func (*CSRFHandler) SetBaseCookie ¶
func (h *CSRFHandler) SetBaseCookie(cookie http.Cookie)
Sets the base cookie to use when building a CSRF token cookie This way you can specify the Domain, Path, HttpOnly, Secure, etc.
func (*CSRFHandler) SetFailureHandler ¶
func (h *CSRFHandler) SetFailureHandler(handler http.Handler)
Sets the handler to call in case the CSRF check fails. By default it's defaultFailureHandler.
func (*CSRFHandler) SetIsAllowedOriginFunc ¶ added in v1.2.0
func (h *CSRFHandler) SetIsAllowedOriginFunc(f func(*url.URL) bool)
SetAllowedOrigins defines a function that checks whether the request comes from an allowed origin. This function will be invoked when the request is not considered a same-origin request. If this function returns `false`, request will be disallowed.
In most cases, this will be used with StaticOrigins.
func (*CSRFHandler) SetIsTLSFunc ¶ added in v1.2.0
func (h *CSRFHandler) SetIsTLSFunc(f func(*http.Request) bool)
SetIsTLSFunc sets a delegate function which determines, on a per-request basis, whether the request is made over a secure connection. This should return `true` iff the URL that the user uses to access the application begins with https://. For example, if the Go web application is served via plain-text HTTP, but the user is accessing it through HTTPS via a TLS-terminating reverse-proxy, this should return `true`.
Examples:
1. If you're using the Go TLS stack (no TLS-terminating proxies in between the user and the app), you may use:
h.SetIsTLSFunc(func(r *http.Request) bool { return r.TLS != nil })
2. If your application is behind a reverse proxy that terminates TLS, you should configure the reverse proxy to report the protocol that the request was made over via an HTTP header, e.g. `X-Forwarded-Proto`. You should also validate that the request is coming in from an IP of a trusted reverse proxy to ensure that this header has not been spoofed by an attacker. For example:
var trustedProxies = []string{"198.51.100.1", "198.51.100.2"}
h.SetIsTLSFunc(func(r *http.Request) bool {
ip, _, _ := strings.Cut(r.RemoteAddr, ":")
proto := r.Header.Get("X-Forwarded-Proto")
return slices.Contains(trustedProxies, ip) && proto == "https"
})
