aboutsummaryrefslogtreecommitdiff
path: root/vendor/github.com/gorilla
diff options
context:
space:
mode:
authorNiall Sheridan <nsheridan@gmail.com>2016-07-17 23:54:42 +0100
committerNiall Sheridan <nsheridan@gmail.com>2016-07-24 23:23:33 +0100
commit44fef1c2a163bdfd781ef08a06e3cf5cf9b7d5da (patch)
treebcde234bf45255a8935aeacf7ee544f256b455cc /vendor/github.com/gorilla
parentc9849d667ab55c23d343332a11afb3eb8ede3f2d (diff)
Add a page for revoking certs
Add a template for revocation Use DATETIME type to store created/expires times Require auth for the /admin and /revoke endpoints
Diffstat (limited to 'vendor/github.com/gorilla')
-rw-r--r--vendor/github.com/gorilla/csrf/LICENSE27
-rw-r--r--vendor/github.com/gorilla/csrf/README.md232
-rw-r--r--vendor/github.com/gorilla/csrf/context.go25
-rw-r--r--vendor/github.com/gorilla/csrf/context_legacy.go24
-rw-r--r--vendor/github.com/gorilla/csrf/csrf.go276
-rw-r--r--vendor/github.com/gorilla/csrf/doc.go159
-rw-r--r--vendor/github.com/gorilla/csrf/helpers.go205
-rw-r--r--vendor/github.com/gorilla/csrf/options.go130
-rw-r--r--vendor/github.com/gorilla/csrf/store.go82
9 files changed, 1160 insertions, 0 deletions
diff --git a/vendor/github.com/gorilla/csrf/LICENSE b/vendor/github.com/gorilla/csrf/LICENSE
new file mode 100644
index 0000000..f407b7f
--- /dev/null
+++ b/vendor/github.com/gorilla/csrf/LICENSE
@@ -0,0 +1,27 @@
+Copyright (c) 2015, Matt Silverlock (matt@eatsleeprepeat.net) All rights
+reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this
+list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice,
+this list of conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its contributors
+may be used to endorse or promote products derived from this software without
+specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/vendor/github.com/gorilla/csrf/README.md b/vendor/github.com/gorilla/csrf/README.md
new file mode 100644
index 0000000..02e4f42
--- /dev/null
+++ b/vendor/github.com/gorilla/csrf/README.md
@@ -0,0 +1,232 @@
+# gorilla/csrf
+[![GoDoc](https://godoc.org/github.com/gorilla/csrf?status.svg)](https://godoc.org/github.com/gorilla/csrf) [![Build Status](https://travis-ci.org/gorilla/csrf.svg?branch=master)](https://travis-ci.org/gorilla/csrf)
+
+gorilla/csrf is a HTTP middleware library that provides [cross-site request
+forgery](http://blog.codinghorror.com/preventing-csrf-and-xsrf-attacks/) (CSRF)
+ protection. It includes:
+
+* The `csrf.Protect` middleware/handler provides CSRF protection on routes
+ attached to a router or a sub-router.
+* A `csrf.Token` function that provides the token to pass into your response,
+ whether that be a HTML form or a JSON response body.
+* ... and a `csrf.TemplateField` helper that you can pass into your `html/template`
+ templates to replace a `{{ .csrfField }}` template tag with a hidden input
+ field.
+
+gorilla/csrf is designed to work with any Go web framework, including:
+
+* The [Gorilla](http://www.gorillatoolkit.org/) toolkit
+* Go's built-in [net/http](http://golang.org/pkg/net/http/) package
+* [Goji](https://goji.io) - see the [tailored fork](https://github.com/goji/csrf)
+* [Gin](https://github.com/gin-gonic/gin)
+* [Echo](https://github.com/labstack/echo)
+* ... and any other router/framework that rallies around Go's `http.Handler` interface.
+
+gorilla/csrf is also compatible with middleware 'helper' libraries like
+[Alice](https://github.com/justinas/alice) and [Negroni](https://github.com/codegangsta/negroni).
+
+## Install
+
+With a properly configured Go toolchain:
+```sh
+go get github.com/gorilla/csrf
+```
+
+## Examples
+
+* [HTML Forms](#html-forms)
+* [JavaScript Apps](#javascript-applications)
+* [Google App Engine](#google-app-engine)
+* [Setting Options](#setting-options)
+
+gorilla/csrf is easy to use: add the middleware to your router with
+the below:
+
+```go
+CSRF := csrf.Protect([]byte("32-byte-long-auth-key"))
+http.ListenAndServe(":8000", CSRF(r))
+```
+
+...and then collect the token with `csrf.Token(r)` in your handlers before
+passing it to the template, JSON body or HTTP header (see below).
+
+Note that the authentication key passed to `csrf.Protect([]byte(key))` should be
+32-bytes long and persist across application restarts. Generating a random key
+won't allow you to authenticate existing cookies and will break your CSRF
+validation.
+
+gorilla/csrf inspects the HTTP headers (first) and form body (second) on
+subsequent POST/PUT/PATCH/DELETE/etc. requests for the token.
+
+### HTML Forms
+
+Here's the common use-case: HTML forms you want to provide CSRF protection for,
+in order to protect malicious POST requests being made:
+
+```go
+package main
+
+import (
+ "net/http"
+
+ "github.com/gorilla/csrf"
+ "github.com/gorilla/mux"
+)
+
+func main() {
+ r := mux.NewRouter()
+ r.HandleFunc("/signup", ShowSignupForm)
+ // All POST requests without a valid token will return HTTP 403 Forbidden.
+ r.HandleFunc("/signup/post", SubmitSignupForm)
+
+ // Add the middleware to your router by wrapping it.
+ http.ListenAndServe(":8000",
+ csrf.Protect([]byte("32-byte-long-auth-key"))(r))
+ // PS: Don't forget to pass csrf.Secure(false) if you're developing locally
+ // over plain HTTP (just don't leave it on in production).
+}
+
+func ShowSignupForm(w http.ResponseWriter, r *http.Request) {
+ // signup_form.tmpl just needs a {{ .csrfField }} template tag for
+ // csrf.TemplateField to inject the CSRF token into. Easy!
+ t.ExecuteTemplate(w, "signup_form.tmpl", map[string]interface{
+ csrf.TemplateTag: csrf.TemplateField(r),
+ })
+ // We could also retrieve the token directly from csrf.Token(r) and
+ // set it in the request header - w.Header.Set("X-CSRF-Token", token)
+ // This is useful if your sending JSON to clients or a front-end JavaScript
+ // framework.
+}
+
+func SubmitSignupForm(w http.ResponseWriter, r *http.Request) {
+ // We can trust that requests making it this far have satisfied
+ // our CSRF protection requirements.
+}
+```
+
+Note that the CSRF middleware will (by necessity) consume the request body if the
+token is passed via POST form values. If you need to consume this in your
+handler, insert your own middleware earlier in the chain to capture the request
+body.
+
+### JavaScript Applications
+
+This approach is useful if you're using a front-end JavaScript framework like
+React, Ember or Angular, or are providing a JSON API.
+
+We'll also look at applying selective CSRF protection using
+[gorilla/mux's](http://www.gorillatoolkit.org/pkg/mux) sub-routers,
+as we don't handle any POST/PUT/DELETE requests with our top-level router.
+
+```go
+package main
+
+import (
+ "github.com/gorilla/csrf"
+ "github.com/gorilla/mux"
+)
+
+func main() {
+ r := mux.NewRouter()
+
+ api := r.PathPrefix("/api").Subrouter()
+ api.HandleFunc("/user/:id", GetUser).Methods("GET")
+
+ http.ListenAndServe(":8000",
+ csrf.Protect([]byte("32-byte-long-auth-key"))(r))
+}
+
+func GetUser(w http.ResponseWriter, r *http.Request) {
+ // Authenticate the request, get the id from the route params,
+ // and fetch the user from the DB, etc.
+
+ // Get the token and pass it in the CSRF header. Our JSON-speaking client
+ // or JavaScript framework can now read the header and return the token in
+ // in its own "X-CSRF-Token" request header on the subsequent POST.
+ w.Header().Set("X-CSRF-Token", csrf.Token(r))
+ b, err := json.Marshal(user)
+ if err != nil {
+ http.Error(w, err.Error(), 500)
+ return
+ }
+
+ w.Write(b)
+}
+```
+
+### Google App Engine
+
+If you're using [Google App
+Engine](https://cloud.google.com/appengine/docs/go/how-requests-are-handled#Go_Requests_and_HTTP),
+which doesn't allow you to hook into the default `http.ServeMux` directly,
+you can still use gorilla/csrf (and gorilla/mux):
+
+```go
+package app
+
+// Remember: appengine has its own package main
+func init() {
+ r := mux.NewRouter()
+ r.HandleFunc("/", IndexHandler)
+ // ...
+
+ // We pass our CSRF-protected router to the DefaultServeMux
+ http.Handle("/", csrf.Protect([]byte(your-key))(r))
+}
+```
+
+### Setting Options
+
+What about providing your own error handler and changing the HTTP header the
+package inspects on requests? (i.e. an existing API you're porting to Go). Well,
+gorilla/csrf provides options for changing these as you see fit:
+
+```go
+func main() {
+ CSRF := csrf.Protect(
+ []byte("a-32-byte-long-key-goes-here"),
+ csrf.RequestHeader("Authenticity-Token"),
+ csrf.FieldName("authenticity_token"),
+ csrf.ErrorHandler(http.HandlerFunc(serverError(403))),
+ )
+
+ r := mux.NewRouter()
+ r.HandleFunc("/signup", GetSignupForm)
+ r.HandleFunc("/signup/post", PostSignupForm)
+
+ http.ListenAndServe(":8000", CSRF(r))
+}
+```
+
+Not too bad, right?
+
+If there's something you're confused about or a feature you would like to see
+added, open an issue.
+
+## Design Notes
+
+Getting CSRF protection right is important, so here's some background:
+
+* This library generates unique-per-request (masked) tokens as a mitigation
+ against the [BREACH attack](http://breachattack.com/).
+* The 'base' (unmasked) token is stored in the session, which means that
+ multiple browser tabs won't cause a user problems as their per-request token
+ is compared with the base token.
+* Operates on a "whitelist only" approach where safe (non-mutating) HTTP methods
+ (GET, HEAD, OPTIONS, TRACE) are the *only* methods where token validation is not
+ enforced.
+* The design is based on the battle-tested
+ [Django](https://docs.djangoproject.com/en/1.8/ref/csrf/) and [Ruby on
+ Rails](http://api.rubyonrails.org/classes/ActionController/RequestForgeryProtection.html)
+ approaches.
+* Cookies are authenticated and based on the [securecookie](https://github.com/gorilla/securecookie)
+ library. They're also Secure (issued over HTTPS only) and are HttpOnly
+ by default, because sane defaults are important.
+* Go's `crypto/rand` library is used to generate the 32 byte (256 bit) tokens
+ and the one-time-pad used for masking them.
+
+This library does not seek to be adventurous.
+
+## License
+
+BSD licensed. See the LICENSE file for details.
diff --git a/vendor/github.com/gorilla/csrf/context.go b/vendor/github.com/gorilla/csrf/context.go
new file mode 100644
index 0000000..fe47270
--- /dev/null
+++ b/vendor/github.com/gorilla/csrf/context.go
@@ -0,0 +1,25 @@
+// +build go1.7
+
+package csrf
+
+import (
+ "context"
+ "net/http"
+
+ "github.com/pkg/errors"
+)
+
+func contextGet(r *http.Request, key string) (interface{}, error) {
+ val := r.Context().Value(key)
+ if val == nil {
+ return nil, errors.Errorf("no value exists in the context for key %q", key)
+ }
+
+ return val, nil
+}
+
+func contextSave(r *http.Request, key string, val interface{}) *http.Request {
+ ctx := r.Context()
+ ctx = context.WithValue(ctx, key, val)
+ return r.WithContext(ctx)
+}
diff --git a/vendor/github.com/gorilla/csrf/context_legacy.go b/vendor/github.com/gorilla/csrf/context_legacy.go
new file mode 100644
index 0000000..dabf0a6
--- /dev/null
+++ b/vendor/github.com/gorilla/csrf/context_legacy.go
@@ -0,0 +1,24 @@
+// +build !go1.7
+
+package csrf
+
+import (
+ "net/http"
+
+ "github.com/gorilla/context"
+
+ "github.com/pkg/errors"
+)
+
+func contextGet(r *http.Request, key string) (interface{}, error) {
+ if val, ok := context.GetOk(r, key); ok {
+ return val, nil
+ }
+
+ return nil, errors.Errorf("no value exists in the context for key %q", key)
+}
+
+func contextSave(r *http.Request, key string, val interface{}) *http.Request {
+ context.Set(r, key, val)
+ return r
+}
diff --git a/vendor/github.com/gorilla/csrf/csrf.go b/vendor/github.com/gorilla/csrf/csrf.go
new file mode 100644
index 0000000..dc4755e
--- /dev/null
+++ b/vendor/github.com/gorilla/csrf/csrf.go
@@ -0,0 +1,276 @@
+package csrf
+
+import (
+ "fmt"
+ "net/http"
+ "net/url"
+
+ "github.com/pkg/errors"
+
+ "github.com/gorilla/context"
+ "github.com/gorilla/securecookie"
+)
+
+// CSRF token length in bytes.
+const tokenLength = 32
+
+// Context/session keys & prefixes
+const (
+ tokenKey string = "gorilla.csrf.Token"
+ formKey string = "gorilla.csrf.Form"
+ errorKey string = "gorilla.csrf.Error"
+ skipCheckKey string = "gorilla.csrf.Skip"
+ cookieName string = "_gorilla_csrf"
+ errorPrefix string = "gorilla/csrf: "
+)
+
+var (
+ // The name value used in form fields.
+ fieldName = tokenKey
+ // defaultAge sets the default MaxAge for cookies.
+ defaultAge = 3600 * 12
+ // The default HTTP request header to inspect
+ headerName = "X-CSRF-Token"
+ // Idempotent (safe) methods as defined by RFC7231 section 4.2.2.
+ safeMethods = []string{"GET", "HEAD", "OPTIONS", "TRACE"}
+)
+
+// TemplateTag provides a default template tag - e.g. {{ .csrfField }} - for use
+// with the TemplateField function.
+var TemplateTag = "csrfField"
+
+var (
+ // ErrNoReferer is returned when a HTTPS request provides an empty Referer
+ // header.
+ ErrNoReferer = errors.New("referer not supplied")
+ // ErrBadReferer is returned when the scheme & host in the URL do not match
+ // the supplied Referer header.
+ ErrBadReferer = errors.New("referer invalid")
+ // ErrNoToken is returned if no CSRF token is supplied in the request.
+ ErrNoToken = errors.New("CSRF token not found in request")
+ // ErrBadToken is returned if the CSRF token in the request does not match
+ // the token in the session, or is otherwise malformed.
+ ErrBadToken = errors.New("CSRF token invalid")
+)
+
+type csrf struct {
+ h http.Handler
+ sc *securecookie.SecureCookie
+ st store
+ opts options
+}
+
+// options contains the optional settings for the CSRF middleware.
+type options struct {
+ MaxAge int
+ Domain string
+ Path string
+ // Note that the function and field names match the case of the associated
+ // http.Cookie field instead of the "correct" HTTPOnly name that golint suggests.
+ HttpOnly bool
+ Secure bool
+ RequestHeader string
+ FieldName string
+ ErrorHandler http.Handler
+ CookieName string
+}
+
+// Protect is HTTP middleware that provides Cross-Site Request Forgery
+// protection.
+//
+// It securely generates a masked (unique-per-request) token that
+// can be embedded in the HTTP response (e.g. form field or HTTP header).
+// The original (unmasked) token is stored in the session, which is inaccessible
+// by an attacker (provided you are using HTTPS). Subsequent requests are
+// expected to include this token, which is compared against the session token.
+// Requests that do not provide a matching token are served with a HTTP 403
+// 'Forbidden' error response.
+//
+// Example:
+// package main
+//
+// import (
+// "github.com/elithrar/protect"
+// "github.com/gorilla/mux"
+// )
+//
+// func main() {
+// r := mux.NewRouter()
+//
+// mux.HandlerFunc("/signup", GetSignupForm)
+// // POST requests without a valid token will return a HTTP 403 Forbidden.
+// mux.HandlerFunc("/signup/post", PostSignupForm)
+//
+// // Add the middleware to your router.
+// http.ListenAndServe(":8000",
+// // Note that the authentication key provided should be 32 bytes
+// // long and persist across application restarts.
+// csrf.Protect([]byte("32-byte-long-auth-key"))(r))
+// }
+//
+// func GetSignupForm(w http.ResponseWriter, r *http.Request) {
+// // signup_form.tmpl just needs a {{ .csrfField }} template tag for
+// // csrf.TemplateField to inject the CSRF token into. Easy!
+// t.ExecuteTemplate(w, "signup_form.tmpl", map[string]interface{
+// csrf.TemplateTag: csrf.TemplateField(r),
+// })
+// // We could also retrieve the token directly from csrf.Token(r) and
+// // set it in the request header - w.Header.Set("X-CSRF-Token", token)
+// // This is useful if your sending JSON to clients or a front-end JavaScript
+// // framework.
+// }
+//
+func Protect(authKey []byte, opts ...Option) func(http.Handler) http.Handler {
+ return func(h http.Handler) http.Handler {
+ cs := parseOptions(h, opts...)
+
+ // Set the defaults if no options have been specified
+ if cs.opts.ErrorHandler == nil {
+ cs.opts.ErrorHandler = http.HandlerFunc(unauthorizedHandler)
+ }
+
+ if cs.opts.MaxAge < 0 {
+ // Default of 12 hours
+ cs.opts.MaxAge = defaultAge
+ }
+
+ if cs.opts.FieldName == "" {
+ cs.opts.FieldName = fieldName
+ }
+
+ if cs.opts.CookieName == "" {
+ cs.opts.CookieName = cookieName
+ }
+
+ if cs.opts.RequestHeader == "" {
+ cs.opts.RequestHeader = headerName
+ }
+
+ // Create an authenticated securecookie instance.
+ if cs.sc == nil {
+ cs.sc = securecookie.New(authKey, nil)
+ // Use JSON serialization (faster than one-off gob encoding)
+ cs.sc.SetSerializer(securecookie.JSONEncoder{})
+ // Set the MaxAge of the underlying securecookie.
+ cs.sc.MaxAge(cs.opts.MaxAge)
+ }
+
+ if cs.st == nil {
+ // Default to the cookieStore
+ cs.st = &cookieStore{
+ name: cs.opts.CookieName,
+ maxAge: cs.opts.MaxAge,
+ secure: cs.opts.Secure,
+ httpOnly: cs.opts.HttpOnly,
+ path: cs.opts.Path,
+ domain: cs.opts.Domain,
+ sc: cs.sc,
+ }
+ }
+
+ return cs
+ }
+}
+
+// Implements http.Handler for the csrf type.
+func (cs *csrf) ServeHTTP(w http.ResponseWriter, r *http.Request) {
+ // Skip the check if directed to. This should always be a bool.
+ if val, err := contextGet(r, skipCheckKey); err == nil {
+ if skip, ok := val.(bool); ok {
+ if skip {
+ cs.h.ServeHTTP(w, r)
+ return
+ }
+ }
+ }
+
+ // Retrieve the token from the session.
+ // An error represents either a cookie that failed HMAC validation
+ // or that doesn't exist.
+ realToken, err := cs.st.Get(r)
+ if err != nil || len(realToken) != tokenLength {
+ // If there was an error retrieving the token, the token doesn't exist
+ // yet, or it's the wrong length, generate a new token.
+ // Note that the new token will (correctly) fail validation downstream
+ // as it will no longer match the request token.
+ realToken, err = generateRandomBytes(tokenLength)
+ if err != nil {
+ envError(r, err)
+ cs.opts.ErrorHandler.ServeHTTP(w, r)
+ return
+ }
+
+ // Save the new (real) token in the session store.
+ err = cs.st.Save(realToken, w)
+ if err != nil {
+ envError(r, err)
+ cs.opts.ErrorHandler.ServeHTTP(w, r)
+ return
+ }
+ }
+
+ // Save the masked token to the request context
+ r = contextSave(r, tokenKey, mask(realToken, r))
+ // Save the field name to the request context
+ r = contextSave(r, formKey, cs.opts.FieldName)
+
+ // HTTP methods not defined as idempotent ("safe") under RFC7231 require
+ // inspection.
+ if !contains(safeMethods, r.Method) {
+ // Enforce an origin check for HTTPS connections. As per the Django CSRF
+ // implementation (https://goo.gl/vKA7GE) the Referer header is almost
+ // always present for same-domain HTTP requests.
+ if r.URL.Scheme == "https" {
+ // Fetch the Referer value. Call the error handler if it's empty or
+ // otherwise fails to parse.
+ referer, err := url.Parse(r.Referer())
+ if err != nil || referer.String() == "" {
+ envError(r, ErrNoReferer)
+ cs.opts.ErrorHandler.ServeHTTP(w, r)
+ return
+ }
+
+ if sameOrigin(r.URL, referer) == false {
+ envError(r, ErrBadReferer)
+ cs.opts.ErrorHandler.ServeHTTP(w, r)
+ return
+ }
+ }
+
+ // If the token returned from the session store is nil for non-idempotent
+ // ("unsafe") methods, call the error handler.
+ if realToken == nil {
+ envError(r, ErrNoToken)
+ cs.opts.ErrorHandler.ServeHTTP(w, r)
+ return
+ }
+
+ // Retrieve the combined token (pad + masked) token and unmask it.
+ requestToken := unmask(cs.requestToken(r))
+
+ // Compare the request token against the real token
+ if !compareTokens(requestToken, realToken) {
+ envError(r, ErrBadToken)
+ cs.opts.ErrorHandler.ServeHTTP(w, r)
+ return
+ }
+
+ }
+
+ // Set the Vary: Cookie header to protect clients from caching the response.
+ w.Header().Add("Vary", "Cookie")
+
+ // Call the wrapped handler/router on success.
+ cs.h.ServeHTTP(w, r)
+ // Clear the request context after the handler has completed.
+ context.Clear(r)
+}
+
+// unauthorizedhandler sets a HTTP 403 Forbidden status and writes the
+// CSRF failure reason to the response.
+func unauthorizedHandler(w http.ResponseWriter, r *http.Request) {
+ http.Error(w, fmt.Sprintf("%s - %s",
+ http.StatusText(http.StatusForbidden), FailureReason(r)),
+ http.StatusForbidden)
+ return
+}
diff --git a/vendor/github.com/gorilla/csrf/doc.go b/vendor/github.com/gorilla/csrf/doc.go
new file mode 100644
index 0000000..612c8d9
--- /dev/null
+++ b/vendor/github.com/gorilla/csrf/doc.go
@@ -0,0 +1,159 @@
+/*
+Package csrf (gorilla/csrf) provides Cross Site Request Forgery (CSRF)
+prevention middleware for Go web applications & services.
+
+It includes:
+
+ * The `csrf.Protect` middleware/handler provides CSRF protection on routes
+ attached to a router or a sub-router.
+ * A `csrf.Token` function that provides the token to pass into your response,
+ whether that be a HTML form or a JSON response body.
+ * ... and a `csrf.TemplateField` helper that you can pass into your `html/template`
+ templates to replace a `{{ .csrfField }}` template tag with a hidden input
+ field.
+
+gorilla/csrf is easy to use: add the middleware to individual handlers with
+the below:
+
+ CSRF := csrf.Protect([]byte("32-byte-long-auth-key"))
+ http.HandlerFunc("/route", CSRF(YourHandler))
+
+... and then collect the token with `csrf.Token(r)` before passing it to the
+template, JSON body or HTTP header (you pick!). gorilla/csrf inspects the form body
+(first) and HTTP headers (second) on subsequent POST/PUT/PATCH/DELETE/etc. requests
+for the token.
+
+Note that the authentication key passed to `csrf.Protect([]byte(key))` should be
+32-bytes long and persist across application restarts. Generating a random key
+won't allow you to authenticate existing cookies and will break your CSRF
+validation.
+
+Here's the common use-case: HTML forms you want to provide CSRF protection for,
+in order to protect malicious POST requests being made:
+
+ package main
+
+ import (
+ "fmt"
+ "html/template"
+ "net/http"
+
+ "github.com/gorilla/csrf"
+ "github.com/gorilla/mux"
+ )
+
+ var form = `
+ <html>
+ <head>
+ <title>Sign Up!</title>
+ </head>
+ <body>
+ <form method="POST" action="/signup/post" accept-charset="UTF-8">
+ <input type="text" name="name">
+ <input type="text" name="email">
+ <!--
+ The default template tag used by the CSRF middleware .
+ This will be replaced with a hidden <input> field containing the
+ masked CSRF token.
+ -->
+ {{ .csrfField }}
+ <input type="submit" value="Sign up!">
+ </form>
+ </body>
+ </html>
+ `
+
+ var t = template.Must(template.New("signup_form.tmpl").Parse(form))
+
+ func main() {
+ r := mux.NewRouter()
+ r.HandleFunc("/signup", ShowSignupForm)
+ // All POST requests without a valid token will return HTTP 403 Forbidden.
+ r.HandleFunc("/signup/post", SubmitSignupForm)
+
+ // Add the middleware to your router by wrapping it.
+ http.ListenAndServe(":8000",
+ csrf.Protect([]byte("32-byte-long-auth-key"))(r))
+ }
+
+ func ShowSignupForm(w http.ResponseWriter, r *http.Request) {
+ // signup_form.tmpl just needs a {{ .csrfField }} template tag for
+ // csrf.TemplateField to inject the CSRF token into. Easy!
+ t.ExecuteTemplate(w, "signup_form.tmpl", map[string]interface{}{
+ csrf.TemplateTag: csrf.TemplateField(r),
+ })
+ }
+
+ func SubmitSignupForm(w http.ResponseWriter, r *http.Request) {
+ // We can trust that requests making it this far have satisfied
+ // our CSRF protection requirements.
+ fmt.Fprintf(w, "%v\n", r.PostForm)
+ }
+
+Note that the CSRF middleware will (by necessity) consume the request body if the
+token is passed via POST form values. If you need to consume this in your
+handler, insert your own middleware earlier in the chain to capture the request
+body.
+
+You can also send the CSRF token in the response header. This approach is useful
+if you're using a front-end JavaScript framework like Ember or Angular, or are
+providing a JSON API:
+
+ package main
+
+ import (
+ "github.com/gorilla/csrf"
+ "github.com/gorilla/mux"
+ )
+
+ func main() {
+ r := mux.NewRouter()
+
+ api := r.PathPrefix("/api").Subrouter()
+ api.HandleFunc("/user/:id", GetUser).Methods("GET")
+
+ http.ListenAndServe(":8000",
+ csrf.Protect([]byte("32-byte-long-auth-key"))(r))
+ }
+
+ func GetUser(w http.ResponseWriter, r *http.Request) {
+ // Authenticate the request, get the id from the route params,
+ // and fetch the user from the DB, etc.
+
+ // Get the token and pass it in the CSRF header. Our JSON-speaking client
+ // or JavaScript framework can now read the header and return the token in
+ // in its own "X-CSRF-Token" request header on the subsequent POST.
+ w.Header().Set("X-CSRF-Token", csrf.Token(r))
+ b, err := json.Marshal(user)
+ if err != nil {
+ http.Error(w, err.Error(), 500)
+ return
+ }
+
+ w.Write(b)
+ }
+
+In addition: getting CSRF protection right is important, so here's some background:
+
+ * This library generates unique-per-request (masked) tokens as a mitigation
+ against the [BREACH attack](http://breachattack.com/).
+ * The 'base' (unmasked) token is stored in the session, which means that
+ multiple browser tabs won't cause a user problems as their per-request token
+ is compared with the base token.
+ * Operates on a "whitelist only" approach where safe (non-mutating) HTTP methods
+ (GET, HEAD, OPTIONS, TRACE) are the *only* methods where token validation is not
+ enforced.
+ * The design is based on the battle-tested
+ [Django](https://docs.djangoproject.com/en/1.8/ref/csrf/) and [Ruby on
+ Rails](http://api.rubyonrails.org/classes/ActionController/RequestForgeryProtection.html)
+ approaches.
+ * Cookies are authenticated and based on the [securecookie](https://github.com/gorilla/securecookie)
+ library. They're also Secure (issued over HTTPS only) and are HttpOnly
+ by default, because sane defaults are important.
+ * Go's `crypto/rand` library is used to generate the 32 byte (256 bit) tokens
+ and the one-time-pad used for masking them.
+
+This library does not seek to be adventurous.
+
+*/
+package csrf
diff --git a/vendor/github.com/gorilla/csrf/helpers.go b/vendor/github.com/gorilla/csrf/helpers.go
new file mode 100644
index 0000000..7adb5ff
--- /dev/null
+++ b/vendor/github.com/gorilla/csrf/helpers.go
@@ -0,0 +1,205 @@
+package csrf
+
+import (
+ "crypto/rand"
+ "crypto/subtle"
+ "encoding/base64"
+ "fmt"
+ "html/template"
+ "net/http"
+ "net/url"
+
+ "github.com/gorilla/context"
+)
+
+// Token returns a masked CSRF token ready for passing into HTML template or
+// a JSON response body. An empty token will be returned if the middleware
+// has not been applied (which will fail subsequent validation).
+func Token(r *http.Request) string {
+ if val, err := contextGet(r, tokenKey); err == nil {
+ if maskedToken, ok := val.(string); ok {
+ return maskedToken
+ }
+ }
+
+ return ""
+}
+
+// FailureReason makes CSRF validation errors available in the request context.
+// This is useful when you want to log the cause of the error or report it to
+// client.
+func FailureReason(r *http.Request) error {
+ if val, err := contextGet(r, errorKey); err == nil {
+ if err, ok := val.(error); ok {
+ return err
+ }
+ }
+
+ return nil
+}
+
+// UnsafeSkipCheck will skip the CSRF check for any requests. This must be
+// called before the CSRF middleware.
+//
+// Note: You should not set this without otherwise securing the request from
+// CSRF attacks. The primary use-case for this function is to turn off CSRF
+// checks for non-browser clients using authorization tokens against your API.
+func UnsafeSkipCheck(r *http.Request) *http.Request {
+ return contextSave(r, skipCheckKey, true)
+}
+
+// TemplateField is a template helper for html/template that provides an <input> field
+// populated with a CSRF token.
+//
+// Example:
+//
+// // The following tag in our form.tmpl template:
+// {{ .csrfField }}
+//
+// // ... becomes:
+// <input type="hidden" name="gorilla.csrf.Token" value="<token>">
+//
+func TemplateField(r *http.Request) template.HTML {
+ if name, err := contextGet(r, formKey); err == nil {
+ fragment := fmt.Sprintf(`<input type="hidden" name="%s" value="%s">`,
+ name, Token(r))
+
+ return template.HTML(fragment)
+ }
+
+ return template.HTML("")
+}
+
+// mask returns a unique-per-request token to mitigate the BREACH attack
+// as per http://breachattack.com/#mitigations
+//
+// The token is generated by XOR'ing a one-time-pad and the base (session) CSRF
+// token and returning them together as a 64-byte slice. This effectively
+// randomises the token on a per-request basis without breaking multiple browser
+// tabs/windows.
+func mask(realToken []byte, r *http.Request) string {
+ otp, err := generateRandomBytes(tokenLength)
+ if err != nil {
+ return ""
+ }
+
+ // XOR the OTP with the real token to generate a masked token. Append the
+ // OTP to the front of the masked token to allow unmasking in the subsequent
+ // request.
+ return base64.StdEncoding.EncodeToString(append(otp, xorToken(otp, realToken)...))
+}
+
+// unmask splits the issued token (one-time-pad + masked token) and returns the
+// unmasked request token for comparison.
+func unmask(issued []byte) []byte {
+ // Issued tokens are always masked and combined with the pad.
+ if len(issued) != tokenLength*2 {
+ return nil
+ }
+
+ // We now know the length of the byte slice.
+ otp := issued[tokenLength:]
+ masked := issued[:tokenLength]
+
+ // Unmask the token by XOR'ing it against the OTP used to mask it.
+ return xorToken(otp, masked)
+}
+
+// requestToken returns the issued token (pad + masked token) from the HTTP POST
+// body or HTTP header. It will return nil if the token fails to decode.
+func (cs *csrf) requestToken(r *http.Request) []byte {
+ // 1. Check the HTTP header first.
+ issued := r.Header.Get(cs.opts.RequestHeader)
+
+ // 2. Fall back to the POST (form) value.
+ if issued == "" {
+ issued = r.PostFormValue(cs.opts.FieldName)
+ }
+
+ // 3. Finally, fall back to the multipart form (if set).
+ if issued == "" && r.MultipartForm != nil {
+ vals := r.MultipartForm.Value[cs.opts.FieldName]
+
+ if len(vals) > 0 {
+ issued = vals[0]
+ }
+ }
+
+ // Decode the "issued" (pad + masked) token sent in the request. Return a
+ // nil byte slice on a decoding error (this will fail upstream).
+ decoded, err := base64.StdEncoding.DecodeString(issued)
+ if err != nil {
+ return nil
+ }
+
+ return decoded
+}
+
+// generateRandomBytes returns securely generated random bytes.
+// It will return an error if the system's secure random number generator
+// fails to function correctly.
+func generateRandomBytes(n int) ([]byte, error) {
+ b := make([]byte, n)
+ _, err := rand.Read(b)
+ // err == nil only if len(b) == n
+ if err != nil {
+ return nil, err
+ }
+
+ return b, nil
+
+}
+
+// sameOrigin returns true if URLs a and b share the same origin. The same
+// origin is defined as host (which includes the port) and scheme.
+func sameOrigin(a, b *url.URL) bool {
+ return (a.Scheme == b.Scheme && a.Host == b.Host)
+}
+
+// compare securely (constant-time) compares the unmasked token from the request
+// against the real token from the session.
+func compareTokens(a, b []byte) bool {
+ // This is required as subtle.ConstantTimeCompare does not check for equal
+ // lengths in Go versions prior to 1.3.
+ if len(a) != len(b) {
+ return false
+ }
+
+ return subtle.ConstantTimeCompare(a, b) == 1
+}
+
+// xorToken XORs tokens ([]byte) to provide unique-per-request CSRF tokens. It
+// will return a masked token if the base token is XOR'ed with a one-time-pad.
+// An unmasked token will be returned if a masked token is XOR'ed with the
+// one-time-pad used to mask it.
+func xorToken(a, b []byte) []byte {
+ n := len(a)
+ if len(b) < n {
+ n = len(b)
+ }
+
+ res := make([]byte, n)
+
+ for i := 0; i < n; i++ {
+ res[i] = a[i] ^ b[i]
+ }
+
+ return res
+}
+
+// contains is a helper function to check if a string exists in a slice - e.g.
+// whether a HTTP method exists in a list of safe methods.
+func contains(vals []string, s string) bool {
+ for _, v := range vals {
+ if v == s {
+ return true
+ }
+ }
+
+ return false
+}
+
+// envError stores a CSRF error in the request context.
+func envError(r *http.Request, err error) {
+ context.Set(r, errorKey, err)
+}
diff --git a/vendor/github.com/gorilla/csrf/options.go b/vendor/github.com/gorilla/csrf/options.go
new file mode 100644
index 0000000..c644d49
--- /dev/null
+++ b/vendor/github.com/gorilla/csrf/options.go
@@ -0,0 +1,130 @@
+package csrf
+
+import "net/http"
+
+// Option describes a functional option for configuring the CSRF handler.
+type Option func(*csrf)
+
+// MaxAge sets the maximum age (in seconds) of a CSRF token's underlying cookie.
+// Defaults to 12 hours.
+func MaxAge(age int) Option {
+ return func(cs *csrf) {
+ cs.opts.MaxAge = age
+ }
+}
+
+// Domain sets the cookie domain. Defaults to the current domain of the request
+// only (recommended).
+//
+// This should be a hostname and not a URL. If set, the domain is treated as
+// being prefixed with a '.' - e.g. "example.com" becomes ".example.com" and
+// matches "www.example.com" and "secure.example.com".
+func Domain(domain string) Option {
+ return func(cs *csrf) {
+ cs.opts.Domain = domain
+ }
+}
+
+// Path sets the cookie path. Defaults to the path the cookie was issued from
+// (recommended).
+//
+// This instructs clients to only respond with cookie for that path and its
+// subpaths - i.e. a cookie issued from "/register" would be included in requests
+// to "/register/step2" and "/register/submit".
+func Path(p string) Option {
+ return func(cs *csrf) {
+ cs.opts.Path = p
+ }
+}
+
+// Secure sets the 'Secure' flag on the cookie. Defaults to true (recommended).
+// Set this to 'false' in your development environment otherwise the cookie won't
+// be sent over an insecure channel. Setting this via the presence of a 'DEV'
+// environmental variable is a good way of making sure this won't make it to a
+// production environment.
+func Secure(s bool) Option {
+ return func(cs *csrf) {
+ cs.opts.Secure = s
+ }
+}
+
+// HttpOnly sets the 'HttpOnly' flag on the cookie. Defaults to true (recommended).
+func HttpOnly(h bool) Option {
+ return func(cs *csrf) {
+ // Note that the function and field names match the case of the
+ // related http.Cookie field instead of the "correct" HTTPOnly name
+ // that golint suggests.
+ cs.opts.HttpOnly = h
+ }
+}
+
+// ErrorHandler allows you to change the handler called when CSRF request
+// processing encounters an invalid token or request. A typical use would be to
+// provide a handler that returns a static HTML file with a HTTP 403 status. By
+// default a HTTP 403 status and a plain text CSRF failure reason are served.
+//
+// Note that a custom error handler can also access the csrf.Failure(r)
+// function to retrieve the CSRF validation reason from the request context.
+func ErrorHandler(h http.Handler) Option {
+ return func(cs *csrf) {
+ cs.opts.ErrorHandler = h
+ }
+}
+
+// RequestHeader allows you to change the request header the CSRF middleware
+// inspects. The default is X-CSRF-Token.
+func RequestHeader(header string) Option {
+ return func(cs *csrf) {
+ cs.opts.RequestHeader = header
+ }
+}
+
+// FieldName allows you to change the name attribute of the hidden <input> field
+// inspected by this package. The default is 'gorilla.csrf.Token'.
+func FieldName(name string) Option {
+ return func(cs *csrf) {
+ cs.opts.FieldName = name
+ }
+}
+
+// CookieName changes the name of the CSRF cookie issued to clients.
+//
+// Note that cookie names should not contain whitespace, commas, semicolons,
+// backslashes or control characters as per RFC6265.
+func CookieName(name string) Option {
+ return func(cs *csrf) {
+ cs.opts.CookieName = name
+ }
+}
+
+// setStore sets the store used by the CSRF middleware.
+// Note: this is private (for now) to allow for internal API changes.
+func setStore(s store) Option {
+ return func(cs *csrf) {
+ cs.st = s
+ }
+}
+
+// parseOptions parses the supplied options functions and returns a configured
+// csrf handler.
+func parseOptions(h http.Handler, opts ...Option) *csrf {
+ // Set the handler to call after processing.
+ cs := &csrf{
+ h: h,
+ }
+
+ // Default to true. See Secure & HttpOnly function comments for rationale.
+ // Set here to allow package users to override the default.
+ cs.opts.Secure = true
+ cs.opts.HttpOnly = true
+
+ // Range over each options function and apply it
+ // to our csrf type to configure it. Options functions are
+ // applied in order, with any conflicting options overriding
+ // earlier calls.
+ for _, option := range opts {
+ option(cs)
+ }
+
+ return cs
+}
diff --git a/vendor/github.com/gorilla/csrf/store.go b/vendor/github.com/gorilla/csrf/store.go
new file mode 100644
index 0000000..39f47ad
--- /dev/null
+++ b/vendor/github.com/gorilla/csrf/store.go
@@ -0,0 +1,82 @@
+package csrf
+
+import (
+ "net/http"
+ "time"
+
+ "github.com/gorilla/securecookie"
+)
+
+// store represents the session storage used for CSRF tokens.
+type store interface {
+ // Get returns the real CSRF token from the store.
+ Get(*http.Request) ([]byte, error)
+ // Save stores the real CSRF token in the store and writes a
+ // cookie to the http.ResponseWriter.
+ // For non-cookie stores, the cookie should contain a unique (256 bit) ID
+ // or key that references the token in the backend store.
+ // csrf.GenerateRandomBytes is a helper function for generating secure IDs.
+ Save(token []byte, w http.ResponseWriter) error
+}
+
+// cookieStore is a signed cookie session store for CSRF tokens.
+type cookieStore struct {
+ name string
+ maxAge int
+ secure bool
+ httpOnly bool
+ path string
+ domain string
+ sc *securecookie.SecureCookie
+}
+
+// Get retrieves a CSRF token from the session cookie. It returns an empty token
+// if decoding fails (e.g. HMAC validation fails or the named cookie doesn't exist).
+func (cs *cookieStore) Get(r *http.Request) ([]byte, error) {
+ // Retrieve the cookie from the request
+ cookie, err := r.Cookie(cs.name)
+ if err != nil {
+ return nil, err
+ }
+
+ token := make([]byte, tokenLength)
+ // Decode the HMAC authenticated cookie.
+ err = cs.sc.Decode(cs.name, cookie.Value, &token)
+ if err != nil {
+ return nil, err
+ }
+
+ return token, nil
+}
+
+// Save stores the CSRF token in the session cookie.
+func (cs *cookieStore) Save(token []byte, w http.ResponseWriter) error {
+ // Generate an encoded cookie value with the CSRF token.
+ encoded, err := cs.sc.Encode(cs.name, token)
+ if err != nil {
+ return err
+ }
+
+ cookie := &http.Cookie{
+ Name: cs.name,
+ Value: encoded,
+ MaxAge: cs.maxAge,
+ HttpOnly: cs.httpOnly,
+ Secure: cs.secure,
+ Path: cs.path,
+ Domain: cs.domain,
+ }
+
+ // Set the Expires field on the cookie based on the MaxAge
+ // If MaxAge <= 0, we don't set the Expires attribute, making the cookie
+ // session-only.
+ if cs.maxAge > 0 {
+ cookie.Expires = time.Now().Add(
+ time.Duration(cs.maxAge) * time.Second)
+ }
+
+ // Write the authenticated cookie to the response.
+ http.SetCookie(w, cookie)
+
+ return nil
+}