authboss

package module
v0.0.0-...-2eff32e Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 2, 2015 License: MIT Imports: 24 Imported by: 0

README

Authboss

GoDoc Build Status Coverage Status Gitter

Authboss is a modular authentication system for the web. It tries to remove as much boilerplate and "hard things" as possible so that each time you start a new web project in Go, you can plug it in, configure, and start building your app without having to build an authentication system each time. This reduces the potential for mistakes since authentication is not exactly trivial and should hopefully be generic enough to be plugged into all sorts of different web applications.

Modules

Each module can be turned on simply by importing it and the side-effects take care of the rest. Not all the capabilities of authboss are represented by a module, see use cases to view the supported use cases as well as how to use them in your app.

Name Import Path Description
Auth gopkg.in/authboss.v0/register Provides database password authentication for users.
Confirm gopkg.in/authboss.v0/confirm Sends an e-mail verification before allowing users to log in.
Lock gopkg.in/authboss.v0/lock Locks user accounts after N authentication failures in M time.
OAuth2 gopkg.in/authboss.v0/oauth2 Provides oauth2 authentication for users.
Recover gopkg.in/authboss.v0/recover Allows for password resets via e-mail.
Register gopkg.in/authboss.v0/register User-initiated account creation.
Remember gopkg.in/authboss.v0/remember Persisting login sessions past session cookie expiry.

Getting Started

Install the library and import it:

go get gopkg.in/authboss.v0

After that a good place to start in any Authboss implementation is the configuration struct. There are many defaults setup for you but there are some elements that must be provided. to find out what is configurable view the documentation linked to above, each struct element is documented.

Required options:

  • Storer or OAuth2Storer (for user storage)
  • SessionStoreMaker (for flash messages, having a user logged in)
  • CookieStoreMaker (for remember me cookies)
  • XSRFName/XSRFMaker (for generating xsrf tokens to prevent xsrf attacks in authboss forms)

Recommended options:

  • LogWriter: This is where authboss will log it's errors, as well as put status information on startup.
  • MountPath: If you are mounting the authboss paths behind a certain path like /auth
  • ViewsPath: Views to override the default authboss views go here (default: ./)
  • Mailer: If you use any modules that make use of e-mails, this should be set.
  • EmailFrom: The e-mail address you send your authboss notifications from.
  • RootURL: This should be set if you use oauth2 or e-mails as it's required for generating URLs.
  • ErrorHandler/NotFoundHandler/BadRequestHandler: You should display something that makes sense for your app with these.

The amount of code necessary to start and configure authboss is fairly minimal, of course this is excluding your storer, cookie storer, session storer, xsrf maker implementations.

ab := authboss.New() // Usually store this globally
ab.MountPath = "/authboss"
ab.LogWriter = os.Stdout

if err := ab.Init(); err != nil {
	// Handle error, don't let program continue to run
	log.Fatalln(err)
}

// Make sure to put authboss's router somewhere
http.Handle("/authboss", ab.NewRouter())
http.ListenAndServe(":8080")

Once you've got this code set up, it's time to implement the use cases you care about.

Use Cases

  • Get the logged in user (goto)
  • Reset a User's password (goto)
  • User authentication via password (goto)
  • User authentication via OAuth2 (goto)
  • User registration (goto)
  • Confirming registrations via e-mail (goto)
  • Password recovery via e-mail (goto)
  • Persisting login sessions past session expiration (goto)
  • Locking user accounts after so many authentication failures (goto)
  • Expiring user sessions after inactivity (goto)
  • Form Field validation for Authboss forms (goto)
  • Redirect after authboss route (login/logout/oauth etc.) (goto)

How To

There is a full implementation of authboss at: https://github.com/go-authboss/authboss-sample This sample implements a blog with all of the modules with exception that it doesn't use the expiry middleware since it conflicts with the remember module.

Get the logged in User

The current user should always be retrieved through the methods authboss.CurrentUser and authboss.CurrentUserP (panic version). The reason for this is because they do checking against Remember me tokens and differentiate between normal and oauth2 logins.

The interface{} returned is actually your User struct (see: Storers) and you can convert it if it's not nil.

func (a *Authboss) CurrentUser(w http.ResponseWriter, r *http.Request) (interface{}, error)
Return Values Meaning
nil, nil The session had no user ID in it, no remember token, no user.
nil, ErrUserNotFound Session had user ID, but user not found in database.
nil, err Some horrible error has occurred.
user struct, nil The user is logged in.

Reset a User's password

Because on password reset various cleanings need to happen (for example Remember Me tokens should all be deleted) setting the user's password yourself is not a good idea.

Authboss has the UpdatePassword method for you to use. Please consult it's documentation for a thorough explanation of each parameter and usage.

func (a *Authboss) UpdatePassword(w http.ResponseWriter, r *http.Request, ptPassword string, user interface{}, updater func() error) error

An example usage might be:

myUserSave := func() error {
	_, err := db.Exec(`update user set name = $1, password = $2 where id = $3`, user.Name, user.Password, user.ID)
	return err
}

// WARNING: Never pass the form value directly into the database as you see here :D
err := ab.UpdatePassword(w, r, r.FormValue("password"), &user1, myUserSave)
if err != nil {
	// Handle error here, in most cases this will be the error from myUserSave
}

User Authentication via Password

Requirements:

Storage Requirements:

  • Email OR Username (string)
  • Password (string)

How it works: A route is registered for an authentication page. Link to the route, the user follows this link. The Layout and the authboss login view is displayed. The user enters their credentials then the user credentials are verified. The storer will pull back the user and verify that the bcrypted password is correct, then log him in using a session cookie and redirect him to the AuthLoginOKPath.

Another link is created for a logout. Simply link/redirect the user to this page and the user will be logged out.

User Authentication via OAuth2

Requirements:

Storage Requirements:

  • Oauth2Uid (string)
  • Oauth2Provider (string)
  • Oauth2Token (string)
  • Oauth2Refresh (string)
  • Oauth2Expiry (time.Time)

How it works: Routes are registered for each oauth2 provider you specify in the OAuth2Providers configuration. You redirect the user to one of these initial routes (/mount_path/oauth2/providername) and the oauth2 module will ensure the user logs in and receives a token. It then calls the Callback you specify in your OAuth2Provider inside the config, this is responsible for returning various information, please see the docs for OAuth2Provider. Once the callback is complete, the user is saved in the database, and logged in using the session.

Please note that in order to redirect to specific URLs or have the user use the remember module for oauth2 logins you must pass query parameters in the initial route.

params := url.Values{}
params.Set(authboss.CookieRemember, "true")
params.Set(authboss.FormValueRedirect, `/my/redirect/path`)
uri := `/authboss_mount_path/oauth2/google?` + params.Encode()

// Use uri to create a link for the user to log in with Google oauth2 in a template
// <a href="{{.googleOAuthUri}}">Log in with Google!</a>

Examples:

User Registration

Requirements:

Storage Requirements:

  • Email OR Username (string)
  • Password (string)

How it works: User is linked to registration page, the Layout and Registration view are rendered. When the form is submitted, the policies are checked to ensure validation of all form fields (including any custom ones created by overridden views). The password is bcrypt'd and the user is stored. If the confirm module has been loaded the user will be redirected to the RegisterOKPath with a message telling them to check their e-mail and an e-mail will have been sent. If the module is not loaded they will be automatically logged in after registration.

See also: Validation

Confirming Registrations

Requirements:

Storage Requirements:

  • Email (string)
  • ConfirmToken (string)
  • Confirmed (bool)

How it works: After registration, the user will be informed they have an e-mail waiting for them. They click the link provided in the e-mail and their account becomes confirmed, they will automatically be logged in and redirected to RegisterOKPath.

Password Recovery

Requirements:

Storage Requirements:

  • RecoverToken (string)
  • RecoverTokenExpiry (time.Time)

How it works: The user goes to the password recovery page. They then enter their primary ID two times and press recover. An e-mail is sent to the user that includes a token that expires after some time. The user clicks the link in the e-mail and is prompted to enter a new password. Once the password they enter passes all policies their new password is stored, they are logged in and redirected to the RecoverOKPath.

Remember Me (persistent login)

Requirements:

Storage Requirements:

A separate table/Nested Array containing many tokens for any given user

  • Token (string)

RememberStorer: A remember storer is an interface that must be satisfied by one of the authboss.Cfg.Storer or authboss.Cfg.OAuth2Storer if neither satisfies the requirement the module will fail to load.

How it works: When the authentication form is submitted if the form value rm is set to "true" the remember module will automatically create a remember token for the user and set this in the database as well as in a cookie. As for OAuth2 logins, it will look for an encoded state parameter that is automatically included by simply passing rm=true in the query arguments to the initial oauth2 login url (see OAuth2 for more details).

If the user is not logged in and the CurrentUser method is called remember module will look for a token in the request and attempt to use this to log the user in. If a valid token is found the user is logged in and receives a new token and the old one is deleted.

If a user recovers their password using the recover module, all remember me tokens are deleted for that user.

Half Auth: A session value with the name in the constant authboss.SessionHalfAuth will be set to "true" if the session was created by a half-auth. Doing a full log in using the auth or oauth2 modules ensure this value is cleared. You should be careful about providing access to pages with sensitive information if this value is true in the session, and force a full auth in these situations.

Locking Accounts for Authentication Failures

Requirements:

Storage Requirements:

  • AttemptNumber (int64)
  • AttemptTime (time.Time)
  • Locked (time.Time)

How it works: When a user fails authentication the attempt time is stored as well as the number of attempts being set to one. If the user continues to fail authentication in the timeframe of AttemptTime + LockWindow then the attempt number will continue to increase. Once the account number reaches the configured LockAfter amount the account will become locked for the configured LockDuration. After this duration the user will be able to attempt to log in again.

Expiring Inactive User Sessions

Requirements:

How it works: A middleware is installed into the stack. This middleware uses the session to log the last action time of the user. If the last action occurred longer than the configured expire time ago then the users login session will be deleted.

mux := mux.NewRouter() // Gorilla Mux syntax
http.ListenAndServe(":8080", ab.ExpireMiddleware(mux)) // Install the middleware

Validation

Field validation: Validation is achieved through the use of policies. These policies are in the configuration. They can be added for any field. Any type can be used for validation that implements the Validator interface. Authboss supplies a quite flexible field validator called Rules that you can use instead of writing your own. Validation errors are reported and handled all in the same way, and the view decides how to display these to the user. See the examples or the authboss default view files to see how to display errors.

ab.Policies = []Validator{
	authboss.Rules{
		FieldName:       "username",
		Required:        true,
		MinLength:       2,
		MaxLength:       4,
		AllowWhitespace: false,
	},
}

Confirmation fields: To ensure one field matches a confirmation field, such as when registering and entering a password. Simply add the field to the list of ConfirmFields, where each real entry in the array is two entries, the first being the name of the field to be confirmed and the second being the name of the confirm field. These confirm fields are only used on the register page, and by default only has password but you can add others.

ab.ConfirmFields: []string{
	StorePassword, ConfirmPrefix + StorePassword,
},

Redirecting after Authboss routes

Sometimes you want your web application to authenticate a user and redirect him back to where he came from, or to a different page. You can do this by passing the "redir" query parameter with a path to whatever URL you'd like. For example:

<a href="/auth/login?redir=/userprofile">Login</a>

These redirection paths only occur on success paths currently, although this may change in the future.

Implementing Storers

Authboss makes no presumptions about how you want to store your data. While different web frameworks have their own authentication plugins such as passport or devise, Go has so no such standard framework and therefore we cannot make any of these assumptions and data handling is a bit more manual.

There are three parts to storage: Storer interfaces, User Struct, Binding/Unbinding.

Storer Interfaces

Each of the store interfaces provides some amount of functionality to a module. Without the appropriate storer type the module cannot function. Most of these interfaces simply do look ups on the user based on different field. Some of them like the RememberStorer are more special in their functionality.

You can see an example here: Blog Storer. This storer implements all 6 of the Storer Interfaces. If you don't use as many modules as the blog, you don't need to implement all of these methods.

Most of the methods return an (interface{}, error), the interface{} user struct that is described below. In cases where the queries produce no values (ie no user found), special error values are returned, ErrUserNotFound and ErrTokenNotFound. Please consult the documentation for each Storer interface for more information on what you should be returning in each situation.

User Struct

The idea is to create a struct that matches Authboss's storage requirements so that it can be easily serialized from and to using reflection available through the methods: authboss.Attributes.Bind(), and authboss.Unbind(). These methods use a camel-case naming convention and do not have struct tags for naming control (yet). Oauth2Uid in the struct -> "oauth2_uid" in the attributes map and vice versa. Bind() uses reflection to set attributes so the user struct should be returned from storer methods as a pointer.

Fields: Each module in authboss has storage requirements. These are listed in the documentation but also at runtime authboss.ModuleAttributes is available to list out each required field. The fields must be named appropriately and of the correct type.

Choose a PrimaryID: Email or Username can be selected for a primary id for the user (default email). This must be a unique field in the data store and must be set to the Authboss configuration's PrimaryID, you can use authboss.StoreEmail and authboss.StoreUsername constants to set it appropriately. Keep in mind that you can have both of these fields if you choose, but only one will be used to log in with. Systems that wish to use Username should consider keeping e-mail address to allow the rest of the modules that require email such as recover or confirm to function.

Binding/Unbinding

In your Create/Put/PutOAuth methods you will be handed an authboss.Attributes type. You can manually work with this type, and there are many helper methods available but by far the easiest way is to simply pass in a correct user struct to it's .Bind() method. See examples below. In any type of Get methods, the user struct should be filled with data, and passed back through the interface{} return parameter. authboss.Unbind() will be called on this struct to extract it's data into authboss.Attributes, which is used for all authboss operations, and later Put will be called with the updated attributes for you to save them again.

Examples

Implementing Client Storers

ClientStorer Interface

ClientStorer's encapsulate the functionality of cookies for the web application. The session storer is for session data, the cookie storer is actually only used for the remember tokens so it should create cookies of very long durations (however long you want your users remembered for).

These are simple to implement and the following examples should show exactly what needs to be done. If you're using gorilla toolkit you can copy these examples almost verbatim.

Keep in mind that these need not be only cookie-based, any storage medium that can reliably take a request/response pair and store session/client data can be used. You could insert a redis backend here if you like that approach better than just cookies.

Examples:

Views

The view system in Authboss uses Go templates with the concepts of layout/views to render HTML to the user. It uses the authboss.HTMLData type to pass data into templates. This HTMLData type has some helpers to merge different values in.

ViewData: There is a LayoutDataMaker function that should be defined in the config to provide any layout data (titles, additional data) for rendering authboss views. This should typically include the keys: authboss.FlashSuccessKey, authboss.FlashErrorKey to display error and success messages from Authboss.

// Example LayoutDataMaker
func layoutData(w http.ResponseWriter, r *http.Request) authboss.HTMLData {
	userInter, err := ab.CurrentUser(w, r)

	return authboss.HTMLData{
		"loggedin":               userInter != nil,
		authboss.FlashSuccessKey: ab.FlashSuccess(w, r),
		authboss.FlashErrorKey:   ab.FlashError(w, r),
	}
}

Layouts: There are 3 layouts to provide, these are specified in the configuration and you must load them yourself (using template.New().Parse() etc). Each of these layouts should have a template defined within them like so: {{template "authboss" .}} if you are going to use this layout for other pages that are not authboss-related, you can use an empty define at the end to prevent errors when the authboss template has not been provided: {{define "authboss"}}{{end}}

  • Layout (for html/views)
  • LayoutEmailHTML (for HTML e-mails)
  • LayoutEmailText (for Text e-mails)

Overriding Default Views: The default authboss views are loaded automatically, they can be overridden simply by specifying the ViewPath (default ./) in the configuration and placing files with the correct names in that directory.

Overiddable views are:

View Name
Login Page login.html.tpl
Register Page register.html.tpl
Recover Page recover.html.tpl
Recover New Password recover_complete.html.tpl
Confirmation Email (html) confirm_email.html.tpl
Confirmation Email (txt) confirm_email.txt.tpl
Recover Email (html) recover_email.html.tpl
Recover Email (txt) recover_email.txt.tpl

Example Layout Configuration

Example Overriden Templates:

Documentation

Overview

Package authboss is a modular authentication system for the web. It tries to remove as much boilerplate and "hard things" as possible so that each time you start a new web project in Go, you can plug it in, configure and be off to the races without having to think about how to store passwords or remember tokens.

Index

Constants

View Source
const (
	// SessionKey is the primarily used key by authboss.
	SessionKey = "uid"
	// SessionHalfAuthKey is used for sessions that have been authenticated by
	// the remember module. This serves as a way to force full authentication
	// by denying half-authed users acccess to sensitive areas.
	SessionHalfAuthKey = "halfauth"
	// SessionLastAction is the session key to retrieve the last action of a user.
	SessionLastAction = "last_action"
	// SessionOAuth2State is the xsrf protection key for oauth.
	SessionOAuth2State = "oauth2_state"
	// SessionOAuth2Params is the additional settings for oauth like redirection/remember.
	SessionOAuth2Params = "oauth2_params"

	// CookieRemember is used for cookies and form input names.
	CookieRemember = "rm"

	// FlashSuccessKey is used for storing sucess flash messages on the session
	FlashSuccessKey = "flash_success"
	// FlashErrorKey is used for storing sucess flash messages on the session
	FlashErrorKey = "flash_error"
)
View Source
const (
	StoreEmail    = "email"
	StoreUsername = "username"
	StorePassword = "password"
)

Data store constants for attribute names.

View Source
const (
	StoreOAuth2UID      = "oauth2_uid"
	StoreOAuth2Provider = "oauth2_provider"
	StoreOAuth2Token    = "oauth2_token"
	StoreOAuth2Refresh  = "oauth2_refresh"
	StoreOAuth2Expiry   = "oauth2_expiry"
)

Data store constants for OAuth2 attribute names.

View Source
const (
	// ConfirmPrefix is prepended to names of confirm fields.
	ConfirmPrefix = "confirm_"
)

Variables

View Source
var (
	FormValueRedirect    = "redir"
	FormValueOAuth2State = "state"
)

FormValue constants

View Source
var (
	// ErrUserNotFound should be returned from Get when the record is not found.
	ErrUserNotFound = errors.New("User not found")
	// ErrTokenNotFound should be returned from UseToken when the record is not found.
	ErrTokenNotFound = errors.New("Token not found")
	// ErrUserFound should be retruned from Create when the primaryID of the record is found.
	ErrUserFound = errors.New("User found")
)

Functions

func RegisterModule

func RegisterModule(name string, m Modularizer)

RegisterModule with the core providing all the necessary information to integrate into authboss.

func RegisteredModules

func RegisteredModules() []string

RegisteredModules returns a list of modules that are currently registered.

Types

type After

type After func(*Context) error

After is a request callback that happens after the event.

type AttributeErr

type AttributeErr struct {
	Name     string
	WantKind DataType
	GotKind  string
}

AttributeErr represents a failure to retrieve a critical piece of data from the storer.

func NewAttributeErr

func NewAttributeErr(name string, kind DataType, val interface{}) AttributeErr

NewAttributeErr creates a new attribute err type. Useful for when you want to have a type mismatch error.

func (AttributeErr) Error

func (a AttributeErr) Error() string

type AttributeMeta

type AttributeMeta map[string]DataType

AttributeMeta stores type information for attributes.

func (AttributeMeta) Names

func (a AttributeMeta) Names() []string

Names returns the names of all the attributes.

type Attributes

type Attributes map[string]interface{}

Attributes is just a key-value mapping of data.

func Unbind

func Unbind(intf interface{}) Attributes

Unbind is the opposite of Bind, taking a struct in and producing a list of attributes.

func (Attributes) Bind

func (a Attributes) Bind(strct interface{}, ignoreMissing bool) error

Bind the data in the attributes to the given struct. This means the struct creator must have read the documentation and decided what fields will be needed ahead of time. Ignore missing ignores attributes for which a struct attribute equivalent can not be found.

func (Attributes) Bool

func (a Attributes) Bool(key string) (val bool, ok bool)

Bool returns a single value as a bool.

func (Attributes) BoolErr

func (a Attributes) BoolErr(key string) (val bool, err error)

BoolErr returns a single value as a bool.

func (Attributes) DateTime

func (a Attributes) DateTime(key string) (time.Time, bool)

DateTime returns a single value as a time.Time

func (Attributes) DateTimeErr

func (a Attributes) DateTimeErr(key string) (val time.Time, err error)

DateTimeErr returns a single value as a time.Time

func (Attributes) Int64

func (a Attributes) Int64(key string) (int64, bool)

Int64 returns a single value as a int64

func (Attributes) Int64Err

func (a Attributes) Int64Err(key string) (val int64, err error)

Int64Err returns a single value as a int

func (Attributes) Names

func (a Attributes) Names() []string

Names returns the names of all the attributes.

func (Attributes) String

func (a Attributes) String(key string) (string, bool)

String returns a single value as a string

func (Attributes) StringErr

func (a Attributes) StringErr(key string) (val string, err error)

StringErr returns a single value as a string

type Authboss

type Authboss struct {
	Config
	Callbacks *Callbacks
	// contains filtered or unexported fields
}

Authboss contains a configuration and other details for running.

func New

func New() *Authboss

New makes a new instance of authboss with a default configuration.

func (*Authboss) ContextFromRequest

func (a *Authboss) ContextFromRequest(r *http.Request) (*Context, error)

ContextFromRequest creates a context from an http request.

func (*Authboss) CurrentUser

func (a *Authboss) CurrentUser(w http.ResponseWriter, r *http.Request) (interface{}, error)

CurrentUser retrieves the current user from the session and the database.

func (*Authboss) CurrentUserP

func (a *Authboss) CurrentUserP(w http.ResponseWriter, r *http.Request) interface{}

CurrentUserP retrieves the current user but panics if it's not available for any reason.

func (*Authboss) ExpireMiddleware

func (a *Authboss) ExpireMiddleware(next http.Handler) http.Handler

ExpireMiddleware ensures that the user's expiry information is kept up-to-date on each request. Deletes the SessionKey from the session if the user is expired (a.ExpireAfter duration since SessionLastAction). This middleware conflicts with use of the Remember module, don't enable both at the same time.

func (*Authboss) FlashError

func (a *Authboss) FlashError(w http.ResponseWriter, r *http.Request) string

FlashError returns FlashError from the session and removes it.

func (*Authboss) FlashSuccess

func (a *Authboss) FlashSuccess(w http.ResponseWriter, r *http.Request) string

FlashSuccess returns FlashSuccessKey from the session and removes it.

func (*Authboss) Init

func (a *Authboss) Init(modulesToLoad ...string) error

Init authboss and the requested modules. modulesToLoad is left empty all registered modules will be loaded.

func (*Authboss) IsLoaded

func (a *Authboss) IsLoaded(mod string) bool

IsLoaded checks if a specific module is loaded.

func (*Authboss) LoadedModules

func (a *Authboss) LoadedModules() []string

LoadedModules returns a list of modules that are currently loaded.

func (*Authboss) NewContext

func (a *Authboss) NewContext() *Context

NewContext is exported for testing modules.

func (*Authboss) NewRouter

func (a *Authboss) NewRouter() http.Handler

NewRouter returns a router to be mounted at some mountpoint.

func (*Authboss) RefreshExpiry

func (a *Authboss) RefreshExpiry(w http.ResponseWriter, r *http.Request)

RefreshExpiry updates the last action for the user, so he doesn't become expired.

func (*Authboss) SendMail

func (a *Authboss) SendMail(data Email) error

SendMail uses the currently configured mailer to deliver e-mails.

func (*Authboss) TimeToExpiry

func (a *Authboss) TimeToExpiry(w http.ResponseWriter, r *http.Request) time.Duration

TimeToExpiry returns zero if the user session is expired else the time until expiry.

func (*Authboss) UpdatePassword

func (a *Authboss) UpdatePassword(w http.ResponseWriter, r *http.Request,
	ptPassword string, user interface{}, updater func() error) error

UpdatePassword should be called to recalculate hashes and do any cleanup that should occur on password resets. Updater should return an error if the update to the user failed (for reasons say like validation, duplicate primary key, etc...). In that case the cleanup will not be performed.

The w and r parameters are for establishing session and cookie storers.

The ptPassword parameter is the new password to update to. updater is called regardless if this is empty or not, but if it is empty, it will not set a new password before calling updater.

The user parameter is the user struct which will have it's Password string/sql.NullString value set to the new bcrypted password. Therefore it must be passed in as a pointer with the Password field exported or an error will be returned.

The error returned is returned either from the updater if that produced an error or from the cleanup routines.

type Before

type Before func(*Context) (Interrupt, error)

Before callbacks can interrupt the flow by returning a bool. This is used to stop the callback chain and the original handler from continuing execution. The execution should also stopped if there is an error (and therefore if error is set the bool is automatically considered set).

type Callbacks

type Callbacks struct {
	// contains filtered or unexported fields
}

Callbacks is a collection of callbacks that fire before and after certain methods.

func NewCallbacks

func NewCallbacks() *Callbacks

NewCallbacks creates a new set of before and after callbacks. Called only by authboss internals and for testing.

func (*Callbacks) After

func (c *Callbacks) After(e Event, f After)

After event, call f.

func (*Callbacks) Before

func (c *Callbacks) Before(e Event, f Before)

Before event, call f.

func (*Callbacks) FireAfter

func (c *Callbacks) FireAfter(e Event, ctx *Context) (err error)

FireAfter event to all the callbacks with a context. The error can safely be ignored as it is logged.

func (*Callbacks) FireBefore

func (c *Callbacks) FireBefore(e Event, ctx *Context) (interrupt Interrupt, err error)

FireBefore event to all the callbacks with a context. The error should be passed up despite being logged once here already so it can write an error out to the HTTP Client. If err is nil then check the value of interrupted. If error is nil then the interrupt value should be checked. If it is not InterruptNone then there is a reason the current process should stop it's course of action.

type ClientDataErr

type ClientDataErr struct {
	Name string
}

ClientDataErr represents a failure to retrieve a critical piece of client information such as a cookie or session value.

func (ClientDataErr) Error

func (c ClientDataErr) Error() string

type ClientStorer

type ClientStorer interface {
	Put(key, value string)
	Get(key string) (string, bool)
	Del(key string)
}

ClientStorer should be able to store values on the clients machine. Cookie and Session storers are built with this interface.

type ClientStorerErr

type ClientStorerErr interface {
	ClientStorer
	GetErr(key string) (string, error)
}

ClientStorerErr is a wrapper to return error values from failed Gets.

type Config

type Config struct {
	// MountPath is the path to mount authboss's routes at (eg /auth).
	MountPath string
	// ViewsPath is the path to search for overridden templates.
	ViewsPath string
	// RootURL is the scheme+host+port of the web application (eg https://www.happiness.com:8080) for url generation.  No trailing slash.
	RootURL string
	// BCryptCost is the cost of the bcrypt password hashing function.
	BCryptCost int

	// PrimaryID is the primary identifier of the user. Set to one of:
	// authboss.StoreEmail, authboss.StoreUsername (StoreEmail is default)
	PrimaryID string

	// Layout that all authboss views will be inserted into.
	Layout *template.Template
	// LayoutHTMLEmail is for emails going out in HTML form, authbosses e-mail templates
	// will be inserted into this layout.
	LayoutHTMLEmail *template.Template
	// LayoutTextEmail is for emails going out in text form, authbosses e-mail templates
	// will be inserted into this layout.
	LayoutTextEmail *template.Template
	// LayoutDataMaker is a function that can provide authboss with the layout's
	// template data. It will be merged with the data being provided for the current
	// view in order to render the templates.
	LayoutDataMaker ViewDataMaker

	// OAuth2Providers lists all providers that can be used. See
	// OAuthProvider documentation for more details.
	OAuth2Providers map[string]OAuth2Provider

	// ErrorHandler handles would be 500 errors.
	ErrorHandler http.Handler
	// BadRequestHandler handles would be 400 errors.
	BadRequestHandler http.Handler
	// NotFoundHandler handles would be 404 errors.
	NotFoundHandler http.Handler

	// AuthLoginOKPath is the redirect path after a successful authentication.
	AuthLoginOKPath string
	// AuthLoginFailPath is the redirect path after a failed authentication.
	AuthLoginFailPath string
	// AuthLogoutOKPath is the redirect path after a log out.
	AuthLogoutOKPath string

	// RecoverOKPath is the redirect path after a successful recovery of a password.
	RecoverOKPath string
	// RecoverTokenDuration controls how long a token sent via email for password
	// recovery is valid for.
	RecoverTokenDuration time.Duration

	// RegisterOKPath is the redirect path after a successful registration.
	RegisterOKPath string

	// Policies control validation of form fields and are automatically run
	// against form posts that include the fields.
	Policies []Validator
	// ConfirmFields are fields that are supposed to be submitted with confirmation
	// fields alongside them, passwords, emails etc.
	ConfirmFields []string
	// PreserveFields are fields used with registration that are to be rendered when
	// post fails.
	PreserveFields []string

	// ExpireAfter controls the time an account is idle before being logged out
	// by the ExpireMiddleware.
	ExpireAfter time.Duration

	// LockAfter this many tries.
	LockAfter int
	// LockWindow is the waiting time before the number of attemps are reset.
	LockWindow time.Duration
	// LockDuration is how long an account is locked for.
	LockDuration time.Duration

	// EmailFrom is the email address authboss e-mails come from.
	EmailFrom string
	// EmailSubjectPrefix is used to add something to the front of the authboss
	// email subjects.
	EmailSubjectPrefix string

	// XSRFName is the name of the xsrf token to put in the hidden form fields.
	XSRFName string
	// XSRFMaker is a function that returns an xsrf token for the current non-POST request.
	XSRFMaker XSRF

	// Storer is the interface through which Authboss accesses the web apps database.
	Storer Storer
	// OAuth2Storer is a different kind of storer only meant for OAuth2.
	OAuth2Storer OAuth2Storer
	// CookieStoreMaker must be defined to provide an interface capapable of storing cookies
	// for the given response, and reading them from the request.
	CookieStoreMaker CookieStoreMaker
	// SessionStoreMaker must be defined to provide an interface capable of storing session-only
	// values for the given response, and reading them from the request.
	SessionStoreMaker SessionStoreMaker
	// LogWriter is written to when errors occur, as well as on startup to show which modules are loaded
	// and which routes they registered. By default writes to io.Discard.
	LogWriter io.Writer
	// Mailer is the mailer being used to send e-mails out. Authboss defines two loggers for use
	// LogMailer and SMTPMailer, the default is a LogMailer to io.Discard.
	Mailer Mailer
}

Config holds all the configuration for both authboss and it's modules.

func (*Config) Defaults

func (c *Config) Defaults()

Defaults sets the configuration's default values.

type Context

type Context struct {
	*Authboss

	SessionStorer ClientStorerErr
	CookieStorer  ClientStorerErr
	User          Attributes
	// contains filtered or unexported fields
}

Context provides context for module operations and callbacks. One obvious need for context is a request's session store. It is not safe for use by multiple goroutines.

func (*Context) Attributes

func (c *Context) Attributes() (Attributes, error)

Attributes converts the post form values into an attributes map.

func (*Context) FirstFormValue

func (c *Context) FirstFormValue(key string) (string, bool)

FirstFormValue gets the first form value from a context created with a request.

func (*Context) FirstFormValueErr

func (c *Context) FirstFormValueErr(key string) (string, error)

FirstFormValueErr gets the first form value from a context created with a request and additionally returns an error not a bool if it's not found.

func (*Context) FirstPostFormValue

func (c *Context) FirstPostFormValue(key string) (string, bool)

FirstPostFormValue gets the first form value from a context created with a request.

func (*Context) FirstPostFormValueErr

func (c *Context) FirstPostFormValueErr(key string) (string, error)

FirstPostFormValueErr gets the first form value from a context created with a request.

func (*Context) FormValue

func (c *Context) FormValue(key string) ([]string, bool)

FormValue gets a form value from a context created with a request.

func (*Context) LoadSessionUser

func (c *Context) LoadSessionUser() error

LoadSessionUser loads the user from the session if the user has not already been loaded.

func (*Context) LoadUser

func (c *Context) LoadUser(key string) error

LoadUser loads the user Attributes if they haven't already been loaded.

func (*Context) PostFormValue

func (c *Context) PostFormValue(key string) ([]string, bool)

PostFormValue gets a form value from a context created with a request.

func (*Context) SaveUser

func (c *Context) SaveUser() error

SaveUser saves the user Attributes.

func (*Context) Validate

func (ctx *Context) Validate(ruleset []Validator, confirmFields ...string) ErrorList

Validate validates a request using the given ruleset.

type CookieStoreMaker

type CookieStoreMaker func(http.ResponseWriter, *http.Request) ClientStorer

CookieStoreMaker is used to create a cookie storer from an http request. Keep in mind security considerations for your implementation, Secure, HTTP-Only, etc flags.

type DataType

type DataType int

DataType represents the various types that clients must be able to store.

const (
	Integer DataType = iota
	String
	Bool
	DateTime
)

DataType constants

func (DataType) String

func (d DataType) String() string

String returns a string for the DataType representation.

type DefaultLogger

type DefaultLogger log.Logger

DefaultLogger is a basic logger.

func NewDefaultLogger

func NewDefaultLogger() *DefaultLogger

NewDefaultLogger creates a logger to stdout.

func (*DefaultLogger) Write

func (d *DefaultLogger) Write(b []byte) (int, error)

Write writes to the internal logger.

type Email

type Email struct {
	To, Cc, Bcc                []string
	ToNames, CcNames, BccNames []string
	FromName, From             string
	ReplyToName, ReplyTo       string
	Subject                    string

	TextBody string
	HTMLBody string
}

Email all the things. The ToNames and friends are parallel arrays and must be 0-length or the same length as their counterpart. To omit a name for a user at an index in To simply use an empty string at that index in ToNames.

type ErrAndRedirect

type ErrAndRedirect struct {
	Err          error
	Location     string
	FlashSuccess string
	FlashError   string
}

ErrAndRedirect represents a general error whose response should be to redirect.

func (ErrAndRedirect) Error

func (e ErrAndRedirect) Error() string

type ErrorList

type ErrorList []error

ErrorList is simply a slice of errors with helpers.

func (ErrorList) Error

func (e ErrorList) Error() string

Error satisfies the error interface.

func (ErrorList) Map

func (e ErrorList) Map() map[string][]string

Map groups errors by their field name

type Event

type Event int

Event is used for callback registration.

const (
	EventRegister Event = iota
	EventAuth
	EventOAuth
	EventAuthFail
	EventOAuthFail
	EventRecoverStart
	EventRecoverEnd
	EventGet
	EventGetUserSession
	EventPasswordReset
)

Event values

func (Event) String

func (i Event) String() string

type FieldError

type FieldError struct {
	Name string
	Err  error
}

FieldError represents an error that occurs during validation and is always attached to field on a form.

func (FieldError) Error

func (f FieldError) Error() string

type HTMLData

type HTMLData map[string]interface{}

HTMLData is used to render templates with.

func NewHTMLData

func NewHTMLData(data ...interface{}) HTMLData

NewHTMLData creates HTMLData from key-value pairs. The input is a key-value slice, where odd elements are keys, and the following even element is their value.

func (HTMLData) Merge

func (h HTMLData) Merge(other HTMLData) HTMLData

Merge adds the data from other to h. If there are conflicting keys they are overwritten by other's values.

func (HTMLData) MergeKV

func (h HTMLData) MergeKV(data ...interface{}) HTMLData

MergeKV adds extra key-values to the HTMLData. The input is a key-value slice, where odd elements are keys, and the following even element is their value.

type HandlerFunc

type HandlerFunc func(*Context, http.ResponseWriter, *http.Request) error

HandlerFunc augments http.HandlerFunc with a context and error handling.

type Interrupt

type Interrupt int

Interrupt is used to signal to callback mechanisms that the current process should not continue.

const (
	// InterruptNone means there was no interrupt present and the process should continue.
	InterruptNone Interrupt = iota
	// InterruptAccountLocked occurs if a user's account has been locked
	// by the lock module.
	InterruptAccountLocked
	// InterruptAccountNotConfirmed occurs if a user's account is not confirmed
	// and therefore cannot be used yet.
	InterruptAccountNotConfirmed
	// InterruptSessionExpired occurs when the user's account has had no activity for the
	// configured duration.
	InterruptSessionExpired
)

Interrupt values

func (Interrupt) String

func (i Interrupt) String() string

type Mailer

type Mailer interface {
	Send(Email) error
}

Mailer is a type that is capable of sending an e-mail.

func LogMailer

func LogMailer(writer io.Writer) Mailer

LogMailer creates a mailer that doesn't deliver e-mails but simply logs them.

func SMTPMailer

func SMTPMailer(server string, auth smtp.Auth) Mailer

SMTPMailer creates an SMTP Mailer to send emails with.

type Modularizer

type Modularizer interface {
	Initialize(*Authboss) error
	Routes() RouteTable
	Storage() StorageOptions
}

Modularizer should be implemented by all the authboss modules.

type OAuth2Provider

type OAuth2Provider struct {
	OAuth2Config     *oauth2.Config
	AdditionalParams url.Values
	Callback         func(oauth2.Config, *oauth2.Token) (Attributes, error)
}

OAuth2Provider is the entire configuration required to authenticate with this provider.

The OAuth2Config does not need a redirect URL because it will be automatically created by the route registration in the oauth2 module.

AdditionalParams can be used to specify extra parameters to tack on to the end of the initial request, this allows for provider specific oauth options like access_type=offline to be passed to the provider.

Callback gives the config and the token allowing an http client using the authenticated token to be created. Because each OAuth2 implementation has a different API this must be handled for each provider separately. It is used to return two things specifically: UID (the ID according to the provider) and the Email address. The UID must be passed back or there will be an error as it is the means of identifying the user in the system, e-mail is optional but should be returned in systems using emailing. The keys authboss.StoreOAuth2UID and authboss.StoreEmail can be used to set these values in the authboss.Attributes map returned by the callback.

In addition to the required values mentioned above any additional values that you wish to have in your user struct can be included here, such as the Name of the user at the endpoint. Keep in mind that only types that are valid for the Attributes type should be used: string, bool, time.Time, int64, or any type that implements database/driver.Valuer.

type OAuth2Storer

type OAuth2Storer interface {
	// PutOAuth creates or updates an existing record (unlike Storer.Put)
	// because in the OAuth flow there is no separate create/update.
	PutOAuth(uid, provider string, attr Attributes) error
	GetOAuth(uid, provider string) (interface{}, error)
}

OAuth2Storer is a replacement (or addition) to the Storer interface. It allows users to be stored and fetched via a uid/provider combination.

type RenderErr

type RenderErr struct {
	TemplateName string
	Data         interface{}
	Err          error
}

RenderErr represents an error that occured during rendering of a template.

func (RenderErr) Error

func (r RenderErr) Error() string

type RouteTable

type RouteTable map[string]HandlerFunc

RouteTable is a routing table from a path to a handlerfunc.

type Rules

type Rules struct {
	// FieldName is the name of the field this is intended to validate.
	FieldName string
	// MatchError describes the MustMatch regexp to a user.
	Required             bool
	MatchError           string
	MustMatch            *regexp.Regexp
	MinLength, MaxLength int
	MinLetters           int
	MinLower, MinUpper   int
	MinNumeric           int
	MinSymbols           int
	AllowWhitespace      bool
}

Rules defines a ruleset by which a string can be validated.

func (Rules) Errors

func (r Rules) Errors(toValidate string) ErrorList

Errors returns an array of errors for each validation error that is present in the given string. Returns nil if there are no errors.

func (Rules) Field

func (r Rules) Field() string

Field names the field this ruleset applies to.

func (Rules) IsValid

func (r Rules) IsValid(toValidate string) bool

IsValid checks toValidate to make sure it's valid according to the rules.

func (Rules) Rules

func (r Rules) Rules() []string

Rules returns an array of strings describing the rules.

type SessionStoreMaker

type SessionStoreMaker func(http.ResponseWriter, *http.Request) ClientStorer

SessionStoreMaker is used to create a session storer from an http request. It must be implemented to satisfy certain modules (auth, remember primarily). It should be a secure storage of the session. This means if it represents a cookie-based session storage these cookies should be signed in order to prevent tampering, or they should be encrypted.

type StorageOptions

type StorageOptions map[string]DataType

StorageOptions is a map depicting the things a module must be able to store.

type Storer

type Storer interface {
	// Put is for storing the attributes passed in using the key. This is an
	// update only method and should not store if it does not find the key.
	Put(key string, attr Attributes) error
	// Get is for retrieving attributes for a given key. The return value
	// must be a struct that contains all fields with the correct types as shown
	// by attrMeta. If the key is not found in the data store simply
	// return nil, ErrUserNotFound.
	Get(key string) (interface{}, error)
}

Storer must be implemented in order to store the user's attributes somewhere. The type of store is up to the developer implementing it, and all it has to do is be able to store several simple types.

type Validator

type Validator interface {
	Field() string
	Errors(in string) ErrorList
	Rules() []string
}

Validator is anything that can validate a string and provide a list of errors and describe its set of rules.

func FilterValidators

func FilterValidators(validators []Validator, fields ...string) []Validator

FilterValidators returns a subset of registered validators

type ViewDataMaker

type ViewDataMaker func(http.ResponseWriter, *http.Request) HTMLData

ViewDataMaker asks for an HTMLData object to assist with rendering.

type XSRF

type XSRF func(http.ResponseWriter, *http.Request) (token string)

XSRF returns a token that should be written to forms to prevent xsrf attacks.

Directories

Path Synopsis
Package auth implements password based user logins.
Package auth implements password based user logins.
Package confirm implements confirmation of user registration via e-mail
Package confirm implements confirmation of user registration via e-mail
internal
mocks
Package mocks defines implemented interfaces for testing modules
Package mocks defines implemented interfaces for testing modules
response
Package response is responsible for loading and rendering authboss templates.
Package response is responsible for loading and rendering authboss templates.
Package lock implements user locking after N bad sign-in attempts.
Package lock implements user locking after N bad sign-in attempts.
Package recover implements password reset via e-mail.
Package recover implements password reset via e-mail.
Package register allows for user registration.
Package register allows for user registration.
Package remember implements persistent logins through the cookie storer.
Package remember implements persistent logins through the cookie storer.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL