authboss

package
v0.6.0 Latest Latest
Warning

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

Go to latest
Published: Aug 12, 2020 License: MIT Imports: 15 Imported by: 0

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 success flash messages on the session
	FlashSuccessKey = "flash_success"
	// FlashErrorKey is used for storing success flash messages on the session
	FlashErrorKey = "flash_error"
)
View Source
const (
	CTXKeyPID  contextKey = "pid"
	CTXKeyUser contextKey = "user"

	CTXKeySessionState contextKey = "session"
	CTXKeyCookieState  contextKey = "cookie"

	// CTXKeyData is a context key for the accumulating
	// map[string]interface{} (authboss.HTMLData) to pass to the
	// renderer
	CTXKeyData contextKey = "data"

	// CTXKeyValues is to pass the data submitted from API request or form
	// along in the context in case modules need it. The only module that needs
	// user information currently is remember so only auth/oauth2 are currently
	// going to use this.
	CTXKeyValues contextKey = "values"
)

CTX Keys for authboss

View Source
const (
	// DataErr is for one off errors that don't really belong to
	// a particular field. It should be a string.
	DataErr = "error"
	// DataValidation is for validation errors, it should always
	// have been created using the Map() style functions in the
	// validation method so that html/text template users don't
	// struggle in displaying them.
	//
	// It is: map[string][]string, where the key in the map is the field
	// and the []string on the other side is the list of problems
	// with that field.
	//
	// It's also important to note that if the errors that were Map()'d
	// did not implement FieldError or for generic errors
	// the empty string ("") is used as a key in the map for those
	// errors that couldn't be fit to a specific field.
	DataValidation = "errors"
	// DataPreserve preserves fields during large form exercises
	// like user registration so we don't have to re-type safe
	// information like addresses etc.
	//
	// This data looks like map[string]string, and is simply
	// keyed by the field name, and the value is the field value.
	DataPreserve = "preserve"
	// DataModules contains a map[string]bool of which modules are loaded
	// The bool is largely extraneous and can be ignored, if the module is
	// loaded it will be present in the map, if not it will be missing.
	DataModules = "modules"
)

Keys for use in HTMLData that are meaningful

View Source
const (
	// ConfirmPrefix is prepended to names of confirm fields.
	ConfirmPrefix = "confirm_"
)
View Source
const (
	// FormValueRedirect should be honored by HTTPRedirector implementations
	// as the value from the URL that overrides the typical redirect when
	// FollowRedirParam is set to true.
	FormValueRedirect = "redir"
)

Variables

View Source
var (
	// ErrUserFound should be returned from Create (see ConfirmUser)
	// when the primaryID of the record is found.
	ErrUserFound = errors.New("user found")
	// 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")
)

Functions

func DelAllSession

func DelAllSession(w http.ResponseWriter, whitelist []string)

DelAllSession deletes all variables in the session except for those on the whitelist.

The whitelist is typically provided directly from the authboss config.

This is the best way to ensure the session is cleaned up after use for a given user. An example is when a user is expired or logged out this method is called.

func DelCookie

func DelCookie(w http.ResponseWriter, key string)

DelCookie deletes a key-value from the session.

func DelKnownCookie

func DelKnownCookie(w http.ResponseWriter)

DelKnownCookie deletes all known cookie variables, which can be used to delete remember me pieces.

func DelSession

func DelSession(w http.ResponseWriter, key string)

DelSession deletes a key-value from the session.

func ErrorMap

func ErrorMap(e []error) map[string][]string

ErrorMap is a shortcut to change []error into ErrorList and call Map on it since this is a common operation.

func FlashError

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

FlashError returns FlashError from the session and removes it.

func FlashSuccess

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

FlashSuccess returns FlashSuccessKey from the session and removes it.

func GetCookie

func GetCookie(r *http.Request, key string) (string, bool)

GetCookie fetches a value from the session

func GetSession

func GetSession(r *http.Request, key string) (string, bool)

GetSession fetches a value from the session

func IsFullyAuthed

func IsFullyAuthed(r *http.Request) bool

IsFullyAuthed returns false if the user has a SessionHalfAuth in his session.

func MakeOAuth2PID

func MakeOAuth2PID(provider, uid string) string

MakeOAuth2PID is used to create a pid for users that don't have an e-mail address or username in the normal system. This allows all the modules to continue to working as intended without having a true primary id. As well as not having to divide the regular and oauth stuff all down the middle.

func MergeDataInRequest

func MergeDataInRequest(r **http.Request, other HTMLData)

MergeDataInRequest edits the request pointer to point to a new request with a modified context that contains the merged data.

func Middleware

func Middleware(ab *Authboss, requirements MWRequirements, failureResponse MWRespondOnFailure) func(http.Handler) http.Handler

Middleware prevents someone from accessing a route that should be only allowed for users who are logged in. It allows the user through if they are logged in (SessionKey is present in the session).

requirements are set by logical or'ing together requirements. eg:

authboss.RequireFullAuth

failureResponse is how the middleware rejects the users that don't meet the criteria. This should be chosen from the MWRespondOnFailure constants.

func ModuleListMiddleware

func ModuleListMiddleware(ab *Authboss) func(http.Handler) http.Handler

ModuleListMiddleware puts a map in the data that can be used to provide the renderer with information about which pieces of the views to show. The bool is extraneous, as presence in the map is the indication of wether or not the module is loaded. Data looks like: map[modulename] = true

oauth2 providers are also listed here using the syntax: oauth2.google for an example. Be careful since this doesn't actually mean that the oauth2 module has been loaded so you should do a conditional that checks for both.

func MountedMiddleware

func MountedMiddleware(ab *Authboss, mountPathed bool, reqs MWRequirements, failResponse MWRespondOnFailure) func(http.Handler) http.Handler

MountedMiddleware hides an option from typical users in "mountPathed". Normal routes should never need this only authboss routes (since they are behind mountPath typically). This method is exported only for use by Authboss modules, normal users should use Middleware instead.

If mountPathed is true, then before redirecting to a URL it will add the mountpath to the front of it.

func ParseOAuth2PID

func ParseOAuth2PID(pid string) (provider, uid string, err error)

ParseOAuth2PID returns the uid and provider for a given OAuth2 pid

func ParseOAuth2PIDP

func ParseOAuth2PIDP(pid string) (provider, uid string)

ParseOAuth2PIDP returns the uid and provider for a given OAuth2 pid

func PutCookie

func PutCookie(w http.ResponseWriter, key, val string)

PutCookie puts a value into the session

func PutSession

func PutSession(w http.ResponseWriter, key, val string)

PutSession puts a value into the session

func RegisterModule

func RegisterModule(name string, m Moduler)

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.

func VerifyPassword

func VerifyPassword(user AuthableUser, password string) error

VerifyPassword uses authboss mechanisms to check that a password is correct. Returns nil on success otherwise there will be an error. Simply a helper to do the bcrypt comparison.

Types

type ArbitraryUser

type ArbitraryUser interface {
	User

	// GetArbitrary is used only to display the arbitrary data back to the user
	// when the form is reset.
	GetArbitrary() (arbitrary map[string]string)
	// PutArbitrary allows arbitrary fields defined by the authboss library
	// consumer to add fields to the user registration piece.
	PutArbitrary(arbitrary map[string]string)
}

ArbitraryUser allows arbitrary data from the web form through. You should definitely only pull the keys you want from the map, since this is unfiltered input from a web request and is an attack vector.

type ArbitraryValuer

type ArbitraryValuer interface {
	Validator

	GetValues() map[string]string
}

ArbitraryValuer provides the "rest" of the fields that aren't strictly needed for anything in particular, address, secondary e-mail, etc.

There are two important notes about this interface:

1. That this is composed with Validator, as these fields should both be validated and culled of invalid pieces as they will be passed into ArbitraryUser.PutArbitrary()

2. These values will also be culled according to the RegisterPreserveFields whitelist and sent back in the data under the key DataPreserve.

type AuthableUser

type AuthableUser interface {
	User

	GetPassword() (password string)
	PutPassword(password string)
}

AuthableUser is identified by a password

func MustBeAuthable

func MustBeAuthable(u User) AuthableUser

MustBeAuthable forces an upgrade to an AuthableUser or panic.

type Authboss

type Authboss struct {
	Config
	Events *Events
	// 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) CurrentUser

func (a *Authboss) CurrentUser(r *http.Request) (User, error)

CurrentUser retrieves the current user from the session and the database. Before the user is loaded from the database the context key is checked. If the session doesn't have the user ID ErrUserNotFound will be returned.

func (*Authboss) CurrentUserID

func (a *Authboss) CurrentUserID(r *http.Request) (string, error)

CurrentUserID retrieves the current user from the session. TODO(aarondl): This method never returns an error, one day we'll change the function signature.

func (*Authboss) CurrentUserIDP

func (a *Authboss) CurrentUserIDP(r *http.Request) string

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

func (*Authboss) CurrentUserP

func (a *Authboss) CurrentUserP(r *http.Request) User

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

func (*Authboss) Email

func (a *Authboss) Email(ctx context.Context, email Email, ro EmailResponseOptions) error

Email renders the e-mail templates for the given email and sends it using the mailer.

func (*Authboss) Init

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

Init authboss, modules, renderers

func (*Authboss) IsLoaded

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

IsLoaded checks if a specific module is loaded.

func (*Authboss) LoadClientState

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

LoadClientState loads the state from sessions and cookies into the ResponseWriter for later use.

func (*Authboss) LoadClientStateMiddleware

func (a *Authboss) LoadClientStateMiddleware(h http.Handler) http.Handler

LoadClientStateMiddleware wraps all requests with the ClientStateResponseWriter as well as loading the current client state into the context for use.

func (*Authboss) LoadCurrentUser

func (a *Authboss) LoadCurrentUser(r **http.Request) (User, error)

LoadCurrentUser takes a pointer to a pointer to the request in order to change the current method's request pointer itself to the new request that contains the new context that has the user in it. Calls LoadCurrentUserID so the primary id is also put in the context.

func (*Authboss) LoadCurrentUserID

func (a *Authboss) LoadCurrentUserID(r **http.Request) (string, error)

LoadCurrentUserID takes a pointer to a pointer to the request in order to change the current method's request pointer itself to the new request that contains the new context that has the pid in it.

func (*Authboss) LoadCurrentUserIDP

func (a *Authboss) LoadCurrentUserIDP(r **http.Request) string

LoadCurrentUserIDP loads the current user id and panics if it's not found

func (*Authboss) LoadCurrentUserP

func (a *Authboss) LoadCurrentUserP(r **http.Request) User

LoadCurrentUserP does the same as LoadCurrentUser but panics if the current user is not found.

func (*Authboss) LoadedModules

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

LoadedModules returns a list of modules that are currently loaded.

func (*Authboss) Logger

func (a *Authboss) Logger(ctx context.Context) FmtLogger

Logger returns an appopriate logger for the context: If context is nil, then it simply returns the configured logger. If context is not nil, then it will attempt to upgrade the configured logger to a ContextLogger, and create a context-specific logger for use.

func (*Authboss) NewResponse

NewResponse wraps the ResponseWriter with a ClientStateResponseWriter

func (*Authboss) RequestLogger

func (a *Authboss) RequestLogger(r *http.Request) FmtLogger

RequestLogger returns a request logger if possible, if not it calls Logger which tries to do a ContextLogger, and if that fails it will finally get a normal logger.

func (*Authboss) UpdatePassword

func (a *Authboss) UpdatePassword(ctx context.Context, user AuthableUser, newPassword string) error

UpdatePassword updates the password field of a user using the same semantics that register/auth do to create and verify passwords. It saves this using the storer.

In addition to that, it also invalidates any remember me tokens, if the storer supports that kind of operation.

If it's also desirable to log the user out, use: authboss.DelKnown(Session|Cookie)

type BodyReader

type BodyReader interface {
	Read(page string, r *http.Request) (Validator, error)
}

BodyReader reads data from the request and returns it in an abstract form. Typically used to decode JSON responses or Url Encoded request bodies.

The first parameter is the page that this request was made on so we can tell what kind of JSON object or form was present as well as create the proper validation mechanisms.

A typical example of this is taking the request and turning it into a JSON struct that knows how to validate itself and return certain fields.

type ClientState

type ClientState interface {
	Get(key string) (string, bool)
}

ClientState represents the client's current state and can answer queries about it.

type ClientStateEvent

type ClientStateEvent struct {
	Kind  ClientStateEventKind
	Key   string
	Value string
}

ClientStateEvent are the different events that can be recorded during a request.

type ClientStateEventKind

type ClientStateEventKind int

ClientStateEventKind is an enum.

const (
	// ClientStateEventPut means you should put the key-value pair into the
	// client state.
	ClientStateEventPut ClientStateEventKind = iota
	// ClientStateEventPut means you should delete the key-value pair from the
	// client state.
	ClientStateEventDel
	// ClientStateEventDelAll means you should delete EVERY key-value pair from
	// the client state - though a whitelist of keys that should not be deleted
	// may be passed through as a comma separated list of keys in
	// the ClientStateEvent.Key field.
	ClientStateEventDelAll
)

ClientStateEvent kinds

type ClientStateReadWriter

type ClientStateReadWriter interface {
	// ReadState should return a map like structure allowing it to look up
	// any values in the current session, or any cookie in the request
	ReadState(*http.Request) (ClientState, error)
	// WriteState can sometimes be called with a nil ClientState in the event
	// that no ClientState was read in from LoadClientState
	WriteState(http.ResponseWriter, ClientState, []ClientStateEvent) error
}

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

There's two major uses for this. To create session storage, and remember me cookies.

type ClientStateResponseWriter

type ClientStateResponseWriter struct {
	http.ResponseWriter
	// contains filtered or unexported fields
}

ClientStateResponseWriter is used to write out the client state at the last moment before the response code is written.

func MustClientStateResponseWriter

func MustClientStateResponseWriter(w http.ResponseWriter) *ClientStateResponseWriter

MustClientStateResponseWriter tries to find a csrw inside the response writer by using the UnderlyingResponseWriter interface.

func (ClientStateResponseWriter) Header

Header retrieves the underlying headers

func (ClientStateResponseWriter) Hijack

Hijack implements the http.Hijacker interface by calling the underlying implementation if available.

func (*ClientStateResponseWriter) UnderlyingResponseWriter

func (c *ClientStateResponseWriter) UnderlyingResponseWriter() http.ResponseWriter

UnderlyingResponseWriter for this instance

func (*ClientStateResponseWriter) Write

func (c *ClientStateResponseWriter) Write(b []byte) (int, error)

Write ensures that the client state is written before any writes to the body occur (before header flush to http client)

func (*ClientStateResponseWriter) WriteHeader

func (c *ClientStateResponseWriter) WriteHeader(code int)

WriteHeader writes the header, but in order to handle errors from the underlying ClientStateReadWriter, it has to panic.

type Config

type Config struct {
	Paths struct {
		// Mount is the path to mount authboss's routes at (eg /auth).
		Mount string

		// NotAuthorized is the default URL to kick users back to when
		// they attempt an action that requires them to be logged in and
		// they're not auth'd
		NotAuthorized string

		// AuthLoginOK is the redirect path after a successful authentication.
		AuthLoginOK string

		// ConfirmOK once a user has confirmed their account
		// this says where they should go
		ConfirmOK string
		// ConfirmNotOK is used by the middleware, when a user is still supposed
		// to confirm their account, this is where they should be redirected to.
		ConfirmNotOK string

		// LockNotOK is a path to go to when the user gets locked out
		LockNotOK string

		// LogoutOK is the redirect path after a log out.
		LogoutOK string

		// OAuth2LoginOK is the redirect path after a successful oauth2 login
		OAuth2LoginOK string
		// OAuth2LoginNotOK is the redirect path after
		// an unsuccessful oauth2 login
		OAuth2LoginNotOK string

		// RecoverOK is the redirect path after a successful recovery of a
		// password.
		RecoverOK string

		// RegisterOK is the redirect path after a successful registration.
		RegisterOK 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

		// TwoFactorEmailAuthNotOK is where a user is redirected when
		// the user attempts to add 2fa to their account without verifying
		// their e-mail OR when they've completed the first step towards
		// verification and need to check their e-mail to proceed.
		TwoFactorEmailAuthNotOK string
	}

	Modules struct {
		// BCryptCost is the cost of the bcrypt password hashing function.
		BCryptCost int

		// 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 attempts are reset.
		LockWindow time.Duration
		// LockDuration is how long an account is locked for.
		LockDuration time.Duration

		// LogoutMethod is the method the logout route should use
		// (default should be DELETE)
		LogoutMethod string

		// MailRouteMethod is used to set the type of request that's used for
		// routes that require a token from an e-mail link's query string.
		// This is things like confirm and two factor e-mail auth.
		//
		// You should probably set this to POST if you are building an API
		// so that the user goes to the frontend with their link & token
		// and the front-end calls the API with the token in a POST JSON body.
		MailRouteMethod string

		// MailNoGoroutine is used to prevent the mailer from being launched
		// in a goroutine by the Authboss modules.
		//
		// It's important that this is the case if you are using contexts
		// as the http request context will be cancelled by the Go http server
		// and it may interrupt your use of the context that the Authboss module
		// is passing to you, preventing proper use of it.
		MailNoGoroutine bool

		// RegisterPreserveFields are fields used with registration that are
		// to be rendered when post fails in a normal way
		// (for example validation errors), they will be passed back in the
		// data of the response under the key DataPreserve which
		// will be a map[string]string. This way the user does not have to
		// retype these whitelisted fields.
		//
		// All fields that are to be preserved must be able to be returned by
		// the ArbitraryValuer.GetValues()
		//
		// This means in order to have a field named "address" you would need
		// to have that returned by the ArbitraryValuer.GetValues() method and
		// then it would be available to be whitelisted by this
		// configuration variable.
		RegisterPreserveFields []string

		// RecoverTokenDuration controls how long a token sent via
		// email for password recovery is valid for.
		RecoverTokenDuration time.Duration
		// RecoverLoginAfterRecovery says for the recovery module after a
		// user has successfully recovered the password, are they simply
		// logged in, or are they redirected to the login page with an
		// "updated password" message.
		RecoverLoginAfterRecovery bool

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

		// TwoFactorEmailAuthRequired forces users to first confirm they have
		// access to their e-mail with the current device by clicking a link
		// and confirming a token stored in the session.
		TwoFactorEmailAuthRequired bool
	}

	Mail struct {
		// RootURL is a full path to an application that is hosting a front-end
		// Typically using a combination of Paths.RootURL and Paths.Mount
		// MailRoot will be assembled if not set.
		// Typically looks like: https://our-front-end.com/authenication
		// No trailing slash.
		RootURL string

		// From is the email address authboss e-mails come from.
		From string
		// FromName is the name authboss e-mails come from.
		FromName string
		// SubjectPrefix is used to add something to the front of the authboss
		// email subjects.
		SubjectPrefix string
	}

	Storage struct {
		// Storer is the interface through which Authboss accesses the web apps
		// database for user operations.
		Server ServerStorer

		// CookieState must be defined to provide an interface capapable of
		// storing cookies for the given response, and reading them from the
		// request.
		CookieState ClientStateReadWriter
		// SessionState must be defined to provide an interface capable of
		// storing session-only values for the given response, and reading them
		// from the request.
		SessionState ClientStateReadWriter

		// SessionStateWhitelistKeys are set to preserve keys in the session
		// when authboss.DelAllSession is called. A correct implementation
		// of ClientStateReadWriter will delete ALL session key-value pairs
		// unless that key is whitelisted here.
		SessionStateWhitelistKeys []string
	}

	Core struct {
		// Router is the entity that controls all routing to authboss routes
		// modules will register their routes with it.
		Router Router

		// ErrorHandler wraps http requests with centralized error handling.
		ErrorHandler ErrorHandler

		// Responder takes a generic response from a controller and prepares
		// the response, uses a renderer to create the body, and replies to the
		// http request.
		Responder HTTPResponder

		// Redirector can redirect a response, similar to Responder but
		// responsible only for redirection.
		Redirector HTTPRedirector

		// BodyReader reads validatable data from the body of a request to
		// be able to get data from the user's client.
		BodyReader BodyReader

		// ViewRenderer loads the templates for the application.
		ViewRenderer Renderer

		// MailRenderer loads the templates for mail
		MailRenderer Renderer

		// Mailer is the mailer being used to send e-mails out via smtp
		Mailer Mailer

		// Logger implies just a few log levels for use, can optionally
		// also implement the ContextLogger to be able to upgrade to a
		// request specific logger.
		Logger Logger
	}
}

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 ConfirmValuer

type ConfirmValuer interface {
	Validator

	GetToken() string
}

ConfirmValuer allows us to pull out the token from the request

func MustHaveConfirmValues

func MustHaveConfirmValues(v Validator) ConfirmValuer

MustHaveConfirmValues upgrades a validatable set of values to ones specific to a user that needs to be confirmed.

type ConfirmableUser

type ConfirmableUser interface {
	User

	GetEmail() (email string)
	GetConfirmed() (confirmed bool)
	GetConfirmSelector() (selector string)
	GetConfirmVerifier() (verifier string)

	PutEmail(email string)
	PutConfirmed(confirmed bool)
	PutConfirmSelector(selector string)
	PutConfirmVerifier(verifier string)
}

ConfirmableUser can be in a state of confirmed or not

func MustBeConfirmable

func MustBeConfirmable(u User) ConfirmableUser

MustBeConfirmable forces an upgrade to a ConfirmableUser or panic.

type ConfirmingServerStorer

type ConfirmingServerStorer interface {
	ServerStorer

	// LoadByConfirmSelector finds a user by his confirm selector field
	// and should return ErrUserNotFound if that user cannot be found.
	LoadByConfirmSelector(ctx context.Context, selector string) (ConfirmableUser, error)
}

ConfirmingServerStorer can find a user by a confirm token

func EnsureCanConfirm

func EnsureCanConfirm(storer ServerStorer) ConfirmingServerStorer

EnsureCanConfirm makes sure the server storer supports confirm-lookup operations

type ContextLogger

type ContextLogger interface {
	FromContext(context.Context) Logger
}

ContextLogger creates a logger from a request context

type CreatingServerStorer

type CreatingServerStorer interface {
	ServerStorer

	// New creates a blank user, it is not yet persisted in the database
	// but is just for storing data
	New(ctx context.Context) User
	// Create the user in storage, it should not overwrite a user
	// and should return ErrUserFound if it currently exists.
	Create(ctx context.Context, user User) error
}

CreatingServerStorer is used for creating new users like when Registration or OAuth2 is being done.

func EnsureCanCreate

func EnsureCanCreate(storer ServerStorer) CreatingServerStorer

EnsureCanCreate makes sure the server storer supports create operations

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 EmailResponseOptions

type EmailResponseOptions struct {
	Data         HTMLData
	HTMLTemplate string
	TextTemplate string
}

EmailResponseOptions controls how e-mails are rendered and sent

type ErrorHandler

type ErrorHandler interface {
	Wrap(func(w http.ResponseWriter, r *http.Request) error) http.Handler
}

ErrorHandler allows routing to http.HandlerFunc's that additionally return an error for a higher level error handling mechanism.

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 type is for describing events

const (
	EventRegister Event = iota
	EventAuth
	// EventAuthHijack is used to steal the authentication process after a
	// successful auth but before any session variable has been put in.
	// Most useful for defining an additional step for authentication
	// (like 2fa). It needs to be separate to EventAuth because other modules
	// do checks that would also interrupt event handlers with an authentication
	// failure so there's an ordering problem.
	EventAuthHijack
	EventOAuth2
	EventAuthFail
	EventOAuth2Fail
	EventRecoverStart
	EventRecoverEnd
	EventGetUser
	EventGetUserSession
	EventPasswordReset
	EventLogout
)

Event kinds

func (Event) String

func (i Event) String() string

type EventHandler

type EventHandler func(w http.ResponseWriter, r *http.Request, handled bool) (bool, error)

EventHandler reacts to events that are fired by Authboss controllers. These controllers will normally process a request by themselves, but if there is special consideration for example a successful login, but the user is locked, the lock module's controller may seize control over the request.

Very much a controller level middleware.

type Events

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

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

func NewEvents

func NewEvents() *Events

NewEvents creates a new set of before and after Events.

func (*Events) After

func (c *Events) After(e Event, f EventHandler)

After event, call f.

func (*Events) Before

func (c *Events) Before(e Event, f EventHandler)

Before event, call f.

func (*Events) FireAfter

func (c *Events) FireAfter(e Event, w http.ResponseWriter, r *http.Request) (bool, error)

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

func (*Events) FireBefore

func (c *Events) FireBefore(e Event, w http.ResponseWriter, r *http.Request) (bool, error)

FireBefore executes the handlers that were registered to fire before the event passed in.

If it encounters an error it will stop immediately without calling other handlers.

If a handler handles the request, it will pass this information both to handlers further down the chain (to let them know that w has been used) as well as set w to nil as a precaution.

type FieldError

type FieldError interface {
	error
	Name() string
	Err() error
}

FieldError describes an error on a field Typically .Error() has both Name() and Err() together, hence the reason for separation.

type FmtLogger

type FmtLogger struct {
	Logger
}

FmtLogger adds convenience functions on top of the logging methods for formatting.

func (FmtLogger) Errorf

func (f FmtLogger) Errorf(format string, values ...interface{})

Errorf prints to Error() with fmt.Printf semantics

func (FmtLogger) Infof

func (f FmtLogger) Infof(format string, values ...interface{})

Infof prints to Info() with fmt.Printf semantics

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 HTTPRedirector

type HTTPRedirector interface {
	Redirect(w http.ResponseWriter, r *http.Request, ro RedirectOptions) error
}

HTTPRedirector redirects http requests to a different url (must handle both json and html) When an authboss controller wants to redirect a user to a different path, it will use this interface.

type HTTPResponder

type HTTPResponder interface {
	Respond(w http.ResponseWriter, r *http.Request, code int, templateName string, data HTMLData) error
}

HTTPResponder knows how to respond to an HTTP request Must consider: - Flash messages - XSRF handling (template data) - Assembling template data from various sources

Authboss controller methods (like the one called in response to POST /auth/login) will call this method to write a response to the user.

type LockableUser

type LockableUser interface {
	User

	GetAttemptCount() (attempts int)
	GetLastAttempt() (last time.Time)
	GetLocked() (locked time.Time)

	PutAttemptCount(attempts int)
	PutLastAttempt(last time.Time)
	PutLocked(locked time.Time)
}

LockableUser is a user that can be locked

func MustBeLockable

func MustBeLockable(u User) LockableUser

MustBeLockable forces an upgrade to a LockableUser or panic.

type Logger

type Logger interface {
	Info(string)
	Error(string)
}

Logger is the basic logging structure that's required

type MWRequirements

type MWRequirements int

MWRequirements are user requirements for authboss.Middleware in order to access the routes in protects. Requirements is a bit-set integer to be able to easily combine requirements like so:

authboss.RequireFullAuth
const (
	RequireNone MWRequirements = 0x00
	// RequireFullAuth means half-authed users will also be rejected
	RequireFullAuth MWRequirements = 0x01
)

Middleware requirements

type MWRespondOnFailure

type MWRespondOnFailure int

MWRespondOnFailure tells authboss.Middleware how to respond to a failure to meet the requirements.

const (
	// RespondNotFound does not allow users who are not logged in to know a
	// route exists by responding with a 404.
	RespondNotFound MWRespondOnFailure = iota
	// RespondRedirect redirects users to the login page
	RespondRedirect
	// RespondUnauthorized provides a 401, this allows users to know the page
	// exists unlike the 404 option.
	RespondUnauthorized
)

Middleware response types

type Mailer

type Mailer interface {
	Send(context.Context, Email) error
}

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

type Moduler

type Moduler interface {
	// Init the module
	Init(*Authboss) error
}

Moduler should be implemented by all the authboss modules.

type OAuth2Provider

type OAuth2Provider struct {
	OAuth2Config     *oauth2.Config
	AdditionalParams url.Values
	FindUserDetails  func(context.Context, oauth2.Config, *oauth2.Token) (map[string]string, 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.

FindUserDetails gives the config and the token allowing an http client using the authenticated token to be created, a call is then made to a known endpoint that will return details about the user we've retrieved the token for. Those details are returned as a map[string]string and subsequently passed into OAuth2ServerStorer.NewFromOAuth2. API this must be handled for each provider separately.

type OAuth2ServerStorer

type OAuth2ServerStorer interface {
	ServerStorer

	// NewFromOAuth2 should return an OAuth2User from a set
	// of details returned from OAuth2Provider.FindUserDetails
	// A more in-depth explanation is that once we've got an access token
	// for the service in question (say a service that rhymes with book)
	// the FindUserDetails function does an http request to a known endpoint
	// that provides details about the user, those details are captured in a
	// generic way as map[string]string and passed into this function to be
	// turned into a real user.
	//
	// It's possible that the user exists in the database already, and so
	// an attempt should be made to look that user up using the details.
	// Any details that have changed should be updated. Do not save the user
	// since that will be done later by OAuth2ServerStorer.SaveOAuth2()
	NewFromOAuth2(ctx context.Context, provider string, details map[string]string) (OAuth2User, error)

	// SaveOAuth2 has different semantics from the typical ServerStorer.Save,
	// in this case we want to insert a user if they do not exist.
	// The difference must be made clear because in the non-oauth2 case,
	// we know exactly when we want to Create vs Update. However since we're
	// simply trying to persist a user that may have been in our database,
	// but if not should already be (since you can think of the operation as
	// a caching of what's on the oauth2 provider's servers).
	SaveOAuth2(ctx context.Context, user OAuth2User) error
}

OAuth2ServerStorer has the ability to create users from data from the provider.

A correct implementation of OAuth2ServerStorer will have a Load() method that special cases the key parameter to be aware of possible OAuth2 pids by using the ParseOAuth2PID method.

func EnsureCanOAuth2

func EnsureCanOAuth2(storer ServerStorer) OAuth2ServerStorer

EnsureCanOAuth2 makes sure the server storer supports oauth2 creation and lookup

type OAuth2User

type OAuth2User interface {
	User

	// IsOAuth2User checks to see if a user was registered in the site as an
	// oauth2 user.
	IsOAuth2User() bool

	GetOAuth2UID() (uid string)
	GetOAuth2Provider() (provider string)
	GetOAuth2AccessToken() (token string)
	GetOAuth2RefreshToken() (refreshToken string)
	GetOAuth2Expiry() (expiry time.Time)

	PutOAuth2UID(uid string)
	PutOAuth2Provider(provider string)
	PutOAuth2AccessToken(token string)
	PutOAuth2RefreshToken(refreshToken string)
	PutOAuth2Expiry(expiry time.Time)
}

OAuth2User allows reading and writing values relating to OAuth2 Also see MakeOAuthPID/ParseOAuthPID for helpers to fulfill the User part of the interface.

func MustBeOAuthable

func MustBeOAuthable(u User) OAuth2User

MustBeOAuthable forces an upgrade to an OAuth2User or panic.

type RecoverEndValuer

type RecoverEndValuer interface {
	Validator

	GetPassword() string
	GetToken() string
}

RecoverEndValuer is used to get data back from the final page of password recovery, the user will provide a password and it must be accompanied by the token to authorize the changing of that password. Contrary to the RecoverValuer, this should have validation errors for bad tokens.

func MustHaveRecoverEndValues

func MustHaveRecoverEndValues(v Validator) RecoverEndValuer

MustHaveRecoverEndValues upgrades a validatable set of values to ones specific to a user that needs to be recovered.

type RecoverMiddleValuer

type RecoverMiddleValuer interface {
	Validator

	GetToken() string
}

RecoverMiddleValuer provides the token that the user submitted via their link.

func MustHaveRecoverMiddleValues

func MustHaveRecoverMiddleValues(v Validator) RecoverMiddleValuer

MustHaveRecoverMiddleValues upgrades a validatable set of values to ones specific to a user that's attempting to recover.

type RecoverStartValuer

type RecoverStartValuer interface {
	Validator

	GetPID() string
}

RecoverStartValuer provides the PID entered by the user.

func MustHaveRecoverStartValues

func MustHaveRecoverStartValues(v Validator) RecoverStartValuer

MustHaveRecoverStartValues upgrades a validatable set of values to ones specific to a user that needs to be recovered.

type RecoverableUser

type RecoverableUser interface {
	AuthableUser

	GetEmail() (email string)
	GetRecoverSelector() (selector string)
	GetRecoverVerifier() (verifier string)
	GetRecoverExpiry() (expiry time.Time)

	PutEmail(email string)
	PutRecoverSelector(selector string)
	PutRecoverVerifier(verifier string)
	PutRecoverExpiry(expiry time.Time)
}

RecoverableUser is a user that can be recovered via e-mail

func MustBeRecoverable

func MustBeRecoverable(u User) RecoverableUser

MustBeRecoverable forces an upgrade to a RecoverableUser or panic.

type RecoveringServerStorer

type RecoveringServerStorer interface {
	ServerStorer

	// LoadByRecoverSelector finds a user by his recover selector field
	// and should return ErrUserNotFound if that user cannot be found.
	LoadByRecoverSelector(ctx context.Context, selector string) (RecoverableUser, error)
}

RecoveringServerStorer allows users to be recovered by a token

func EnsureCanRecover

func EnsureCanRecover(storer ServerStorer) RecoveringServerStorer

EnsureCanRecover makes sure the server storer supports confirm-lookup operations

type RedirectOptions

type RedirectOptions struct {
	// Success & Failure are used to set Flash messages / JSON messages
	// if set. They should be mutually exclusive.
	Success string
	Failure string

	// Code is used when it's an API request instead of 200.
	Code int

	// When a request should redirect a user somewhere on completion, these
	// should be set. RedirectURL tells it where to go. And optionally set
	// FollowRedirParam to override the RedirectURL if the form parameter
	// defined by FormValueRedirect is passed in the request.
	//
	// Redirecting works differently whether it's an API request or not.
	// If it's an API request, then it will leave the URL in a "redirect"
	// parameter.
	RedirectPath     string
	FollowRedirParam bool
}

RedirectOptions packages up all the pieces a module needs to write out a response.

type RememberValuer

type RememberValuer interface {

	// GetShouldRemember is the checkbox or what have you that
	// tells the remember module if it should remember that user's
	// authentication or not.
	GetShouldRemember() bool
}

RememberValuer allows auth/oauth2 to pass along the remember bool from the user to the remember module unobtrusively.

type RememberingServerStorer

type RememberingServerStorer interface {
	ServerStorer

	// AddRememberToken to a user
	AddRememberToken(ctx context.Context, pid, token string) error
	// DelRememberTokens removes all tokens for the given pid
	DelRememberTokens(ctx context.Context, pid string) error
	// UseRememberToken finds the pid-token pair and deletes it.
	// If the token could not be found return ErrTokenNotFound
	UseRememberToken(ctx context.Context, pid, token string) error
}

RememberingServerStorer allows users to be remembered across sessions

func EnsureCanRemember

func EnsureCanRemember(storer ServerStorer) RememberingServerStorer

EnsureCanRemember makes sure the server storer supports remember operations

type Renderer

type Renderer interface {
	// Load the given templates, will most likely be called multiple times
	Load(names ...string) error

	// Render the given template
	Render(ctx context.Context, page string, data HTMLData) (output []byte, contentType string, err error)
}

Renderer is a type that can render a given template with some data.

type RequestLogger

type RequestLogger interface {
	FromRequest(*http.Request) Logger
}

RequestLogger creates a logger from a request

type Router

type Router interface {
	http.Handler

	Get(path string, handler http.Handler)
	Post(path string, handler http.Handler)
	Delete(path string, handler http.Handler)
}

Router can register routes to later be used by the web application

type ServerStorer

type ServerStorer interface {
	// Load will look up the user based on the passed the PrimaryID. Under
	// normal circumstances this comes from GetPID() of the user.
	//
	// OAuth2 logins are special-cased to return an OAuth2 pid (combination of
	// provider:oauth2uid), and therefore key be special cased in a Load()
	// implementation to handle that form, use ParseOAuth2PID to see
	// if key is an OAuth2PID or not.
	Load(ctx context.Context, key string) (User, error)

	// Save persists the user in the database, this should never
	// create a user and instead return ErrUserNotFound if the user
	// does not exist.
	Save(ctx context.Context, user User) error
}

ServerStorer represents the data store that's capable of loading users and giving them a context with which to store themselves.

type UnderlyingResponseWriter

type UnderlyingResponseWriter interface {
	UnderlyingResponseWriter() http.ResponseWriter
}

UnderlyingResponseWriter retrieves the response writer underneath the current one. This allows us to wrap and later discover the particular one that we want. Keep in mind this should not be used to call the normal methods of a responsewriter, just additional ones particular to that type because it's possible to introduce subtle bugs otherwise.

type User

type User interface {
	GetPID() (pid string)
	PutPID(pid string)
}

User has functions for each piece of data it requires. Data should not be persisted on each function call. User has a PID (primary ID) that is used on the site as a single unique identifier to any given user (very typically e-mail or username).

User interfaces return no errors or bools to signal that a value was not present. Instead 0-value = null = not present, this puts the onus on Authboss code to check for this.

type UserValuer

type UserValuer interface {
	Validator

	GetPID() string
	GetPassword() string
}

UserValuer allows us to pull out the PID and Password from the request.

func MustHaveUserValues

func MustHaveUserValues(v Validator) UserValuer

MustHaveUserValues upgrades a validatable set of values to ones specific to an authenticating user.

type Validator

type Validator interface {
	// Validate makes the type validate itself and return
	// a list of validation errors.
	Validate() []error
}

Validator takes a form name and a set of inputs and returns any validation errors for the inputs.

Directories

Path Synopsis
Package defaults houses default implementations for the very many interfaces that authboss has.
Package defaults houses default implementations for the very many interfaces that authboss has.

Jump to

Keyboard shortcuts

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