mirror of
https://github.com/volatiletech/authboss.git
synced 2025-01-10 04:17:59 +02:00
100 lines
2.7 KiB
Go
100 lines
2.7 KiB
Go
/*
|
|
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.
|
|
*/
|
|
package authboss
|
|
|
|
import (
|
|
"context"
|
|
"net/http"
|
|
|
|
"github.com/pkg/errors"
|
|
"golang.org/x/crypto/bcrypt"
|
|
)
|
|
|
|
// Authboss contains a configuration and other details for running.
|
|
type Authboss struct {
|
|
Config
|
|
Events *Events
|
|
|
|
loadedModules map[string]Moduler
|
|
}
|
|
|
|
// New makes a new instance of authboss with a default
|
|
// configuration.
|
|
func New() *Authboss {
|
|
ab := &Authboss{}
|
|
|
|
ab.loadedModules = make(map[string]Moduler)
|
|
ab.Events = NewEvents()
|
|
|
|
ab.Config.Defaults()
|
|
return ab
|
|
}
|
|
|
|
// Init authboss, modules, renderers
|
|
func (a *Authboss) Init(modulesToLoad ...string) error {
|
|
if len(modulesToLoad) == 0 {
|
|
modulesToLoad = RegisteredModules()
|
|
}
|
|
|
|
for _, name := range modulesToLoad {
|
|
if err := a.loadModule(name); err != nil {
|
|
return errors.Errorf("module %s failed to load: %+v", name, err)
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// 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)
|
|
func (a *Authboss) UpdatePassword(ctx context.Context, user AuthableUser, newPassword string) error {
|
|
pass, err := bcrypt.GenerateFromPassword([]byte(newPassword), a.Config.Modules.BCryptCost)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
user.PutPassword(string(pass))
|
|
|
|
storer := a.Config.Storage.Server
|
|
if err := storer.Save(ctx, user); err != nil {
|
|
return err
|
|
}
|
|
|
|
rmStorer, ok := storer.(RememberingServerStorer)
|
|
if !ok {
|
|
return nil
|
|
}
|
|
|
|
return rmStorer.DelRememberTokens(user.GetPID())
|
|
}
|
|
|
|
// Middleware prevents someone from accessing a route by returning a 404 if they are not logged in.
|
|
// This middleware also loads the current user.
|
|
func Middleware(ab *Authboss) func(http.Handler) http.Handler {
|
|
return func(next http.Handler) http.Handler {
|
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
log := ab.RequestLogger(r)
|
|
if u, err := ab.LoadCurrentUser(&r); err != nil {
|
|
log.Errorf("error fetching current user: %+v", err)
|
|
w.WriteHeader(http.StatusInternalServerError)
|
|
return
|
|
} else if u == nil {
|
|
log.Infof("providing not found for unauthorized user at: %s", r.URL.Path)
|
|
w.WriteHeader(http.StatusNotFound)
|
|
return
|
|
} else {
|
|
next.ServeHTTP(w, r)
|
|
}
|
|
})
|
|
}
|
|
}
|