Documentation ¶
Overview ¶
Package secure manages authentication cookies for stateless web applications, and form tokens for CSRF protection.
An encrypted connection (https) is required.
Call 'Configure()' once to provide the information for the package to operate, including the type of the authentication data that will be used. The actual configuration parameters are stored in a 'Config' type struct. The 'DB' interface syncs the Config to an external database, and automatically rotates security keys.
Once configured, call 'Authentication()' to retrieve the data from the cookie. It will redirect to a login page if no valid cookie is present (unless the 'optional' argument was 'true'). 'LogIn()' creates a new cookie, stores the provided data in it, and redirects back to the page that required the authentication. 'Update()' updates the authentication data in the current cookie. 'LogOut()' deletes the cookie.
You'll probably want to wrap 'Authentication()' in a function that converts the 'interface{}' result to the type that you use for the cookie data.
Index ¶
- Constants
- Variables
- func Authentication(r *http.Request) interface{}
- func Configure(record interface{}, dbImpl DB, validateFunc ValidateCookie, ...)
- func Handle(handle httprouter.Handle) httprouter.Handle
- func IfHandle(authenticatedHandle httprouter.Handle, unauthenticatedHandle httprouter.Handle) httprouter.Handle
- func LogIn(w http.ResponseWriter, r *http.Request, record interface{}) (err error)
- func LogOut(w http.ResponseWriter, r *http.Request, redirect bool)
- func Update(w http.ResponseWriter, r *http.Request, record interface{}) (err error)
- type Config
- type DB
- type FormToken
- type Keys
- type SecureRouter
- func (r *SecureRouter) DELETE(path string, handle httprouter.Handle)
- func (r *SecureRouter) GET(path string, handle httprouter.Handle)
- func (r *SecureRouter) HEAD(path string, handle httprouter.Handle)
- func (r *SecureRouter) OPTIONS(path string, handle httprouter.Handle)
- func (r *SecureRouter) PATCH(path string, handle httprouter.Handle)
- func (r *SecureRouter) POST(path string, handle httprouter.Handle)
- func (r *SecureRouter) PUT(path string, handle httprouter.Handle)
- type Session
- type Token
- type ValidateCookie
Constants ¶
const FormValueName = "_formtoken"
FormValueName is the name of the FormValue that is checked in PUT, POST, PATCH, and DELETE handles.
Variables ¶
var ( // ErrTokenNotSaved is returned by LogIn() if it couldn't set the cookie. ErrTokenNotSaved = errors.New("secure: failed to save the session cookie") // ErrNoTLS is returned by LogIn() if the connection isn't encrypted // (https) ErrNoTLS = errors.New("secure: logging in requires an encrypted conection") )
Functions ¶
func Authentication ¶
Authentication returns the record that was stored in the cookie on LogIn().
Call from a Handle wrapped in secure.Handle or secure.IfHandle.
func Configure ¶
func Configure(record interface{}, dbImpl DB, validateFunc ValidateCookie, opt_config ...*Config)
Configure configures the package and must be called once before calling any other function in this package.
'record' is an arbitrary (can be empty) instance of the type of the authentication data that will be passed to Login() to store in the cookie. It's needed to get its type registered with the serialisation package used (encoding/gob).
'dbImpl' is the implementation of the DB interface to sync the configuration and rotate the keys.
'validate' is the function that regularly verifies the cookie data.
'opt_config' is the Config instance to start with. If omitted, the config from the db is used, or else the default config.
func Handle ¶
func Handle(handle httprouter.Handle) httprouter.Handle
secure.Handle ensures the client is logged in when accessing a certian route, redirecting to the log in page if not. The given Handle function should call Authentication() to get the client's account details.
If the cookie is missing, the session has timed out, or the cookie data is invalidated though the ValidateCookie function, the response then gets status 403 Forbidden, and the browser will redirect to config.LogInPath.
func IfHandle ¶
func IfHandle(authenticatedHandle httprouter.Handle, unauthenticatedHandle httprouter.Handle) httprouter.Handle
secure.IfHandle calls the one Handle function for logged-in clients, and the other for logged-out clients.
func LogIn ¶
func LogIn(w http.ResponseWriter, r *http.Request, record interface{}) (err error)
LogIn creates the cookie and sets the cookie. It redirects back to the path where Authenticate() was called.
'record' is the authentication data to store in the cookie, as returned by Authentication()
Types ¶
type Config ¶
type Config struct { // Session manages session cryptography. Session *Session // Token manages token cryptography. Token *Token }
Config holds the package's configuration parameters. Can be synced with an external database, through the DB interface.
type DB ¶
type DB interface { // Fetch fetches a Config instance from the database. Fetch(dst *Config) error // Upsert inserts a Config instance into the database if none is present // on Configure(). Upsert updates the CookieKeyPairs and CookieTimeStamp values on key // rotation time. Upsert(src *Config) error }
DB is the interface to implement for syncing the configuration parameters.
Syncing is executed every config.SyncInterval. If parameter values are changed in the database, the new values get synced to all servers that run the application.
type FormToken ¶
type FormToken struct { // IP is the client's IP address. IP string // Path is the path on this server the token is valid for. Path string // Timestamp is when the token was created. Timestamp time.Time }
A FormToken is a secured identification of a request, suitable for protection against cross site request forgery.
func NewFormToken ¶
NewFormToken initialises a new FormToken. The opt_path argument overrides the default r.URL.Path.
type Keys ¶
type Keys struct { // KeyPairs holds 3 key pairs: current, previous, and next. KeyPairs [][]byte // Start is when the current key pair became current. Start time.Time // TimeOut is how much time Start the key pairs should be rotated. TimeOut time.Duration }
Keys manages rotating cryptographic keys.
type SecureRouter ¶
type SecureRouter struct {
*httprouter.Router
}
A SecureRouter is a secured httprouter. PUT, POST, PATCH, and DELETE handles check for a valid FormToken encrypted token string in the request's "_formtoken" FormValue.
func (*SecureRouter) DELETE ¶
func (r *SecureRouter) DELETE(path string, handle httprouter.Handle)
DELETE registers a handler for a DELETE request to the given path. The handler is only run if the request carries a valid form token.
func (*SecureRouter) GET ¶
func (r *SecureRouter) GET(path string, handle httprouter.Handle)
GET registers a handler for a GET request to the given path.
func (*SecureRouter) HEAD ¶
func (r *SecureRouter) HEAD(path string, handle httprouter.Handle)
HEAD registers a handler for a HEAD request to the given path.
func (*SecureRouter) OPTIONS ¶
func (r *SecureRouter) OPTIONS(path string, handle httprouter.Handle)
OPTIONS registers a handler for a OPTIONS request to the given path.
func (*SecureRouter) PATCH ¶
func (r *SecureRouter) PATCH(path string, handle httprouter.Handle)
PATCH registers a handler for a PATCH request to the given path. The handler is only run if the request carries a valid form token.
func (*SecureRouter) POST ¶
func (r *SecureRouter) POST(path string, handle httprouter.Handle)
POST registers a handler for a POST request to the given path. The handler is only run if the request carries a valid form token.
func (*SecureRouter) PUT ¶
func (r *SecureRouter) PUT(path string, handle httprouter.Handle)
PUT registers a handler for a PUT request to the given path. The handler is only run if the request carries a valid form token.
type Session ¶
type Session struct { // Keys encapsulates the rotating key data & functionality. *Keys // LogInPath is the URL where Authentication() redirects to; a log in form // should be served here. // Default value is "/session". LogInPath string // LogOutPath is the URL where LogOut() redirects to. // Default value is "/". LogOutPath string // ValidateTimeOut determines whether it's time to have the // cookie data checked by the ValidateCookie function. // Default value is 5 minutes. ValidateTimeOut time.Duration // contains filtered or unexported fields }
A Session value is stored in the Config to manage session cryptography.
type Token ¶
type Token struct { // Keys encapsulates the rotating key data & functionality. *Keys // contains filtered or unexported fields }
A Token value is stored in the Config to manage token cryptography.
type ValidateCookie ¶
type ValidateCookie func(src interface{}) (dst interface{}, valid bool)
ValidateCookie is the type of the function passed to Configure(), that gets called to have the application test whether the cookie data is still valid (e.g. to prevent continued access with a cookie that was created with an old password)
'src' is the authentication data from the cookie.
'dst' is the fresh authentication data to replace the cookie data with.
'valid' is whether the old data was good enough to keep the current cookie.
Default implementation always returns the cookie data as is, and true, which is significantly insecure.
Each successful validation stores a timestamp in the cookie. ValidateCookie is called on Authentication, if the time since the validation timestamp > config.SyncInterval