1
0
mirror of https://github.com/volatiletech/authboss.git synced 2025-01-10 04:17:59 +02:00
authboss/auth/auth.go

150 lines
4.2 KiB
Go
Raw Normal View History

// Package auth implements password based user logins.
package auth
import (
"fmt"
"net/http"
"github.com/pkg/errors"
2017-07-31 04:39:33 +02:00
"github.com/volatiletech/authboss"
"github.com/volatiletech/authboss/internal/response"
"golang.org/x/crypto/bcrypt"
)
const (
tplLogin = "login.html.tpl"
2015-01-13 07:08:52 +02:00
)
2015-01-11 08:49:06 +02:00
func init() {
authboss.RegisterModule("auth", &Auth{})
}
2015-03-16 23:42:45 +02:00
// Auth module
2015-02-24 01:51:42 +02:00
type Auth struct {
2015-04-01 00:27:47 +02:00
*authboss.Authboss
}
// Init module
func (a *Auth) Init(ab *authboss.Authboss) (err error) {
2015-04-01 00:27:47 +02:00
a.Authboss = ab
if err := a.Authboss.Config.Core.ViewRenderer.Load(tplLogin); err != nil {
return err
2015-02-24 01:51:42 +02:00
}
var logoutRouteMethod func(string, http.Handler)
switch a.Authboss.Config.Modules.LogoutMethod {
case "GET":
logoutRouteMethod = a.Authboss.Config.Core.Router.Get
case "POST":
logoutRouteMethod = a.Authboss.Config.Core.Router.Post
case "DELETE":
logoutRouteMethod = a.Authboss.Config.Core.Router.Delete
default:
return errors.Errorf("auth wants to register a logout route but is given an invalid method: %s", a.Authboss.Config.Modules.LogoutMethod)
2015-02-25 01:01:56 +02:00
}
a.Authboss.Config.Core.Router.Get("/login", http.HandlerFunc(loginGet))
a.Authboss.Config.Core.Router.Post("/login", http.HandlerFunc(loginPost))
logoutRouteMethod("/logout", http.HandlerFunc(logout))
return nil
}
func (a *Auth) loginGet(w http.ResponseWriter, r *http.Request) error {
data := authboss.NewHTMLData(
"showRemember", a.IsLoaded("remember"),
"showRecover", a.IsLoaded("recover"),
"showRegister", a.IsLoaded("register"),
"primaryID", a.PrimaryID,
"primaryIDValue", "",
)
return a.templates.Render(ctx, w, r, tplLogin, data)
}
func (a *Auth) loginPost(w http.ResponseWriter, r *http.Request) error {
switch r.Method {
case methodGET:
case methodPOST:
key := r.FormValue(a.PrimaryID)
password := r.FormValue("password")
2015-01-16 00:01:01 +02:00
2015-02-21 09:33:35 +02:00
errData := authboss.NewHTMLData(
2015-04-01 00:27:47 +02:00
"error", fmt.Sprintf("invalid %s and/or password", a.PrimaryID),
"primaryID", a.PrimaryID,
2015-02-24 01:51:42 +02:00
"primaryIDValue", key,
2015-04-01 00:27:47 +02:00
"showRemember", a.IsLoaded("remember"),
"showRecover", a.IsLoaded("recover"),
"showRegister", a.IsLoaded("register"),
2015-02-21 09:33:35 +02:00
)
if valid, err := validateCredentials(ctx, key, password); err != nil {
errData["error"] = "Internal server error"
2016-05-07 08:12:20 +02:00
fmt.Fprintf(ctx.LogWriter, "auth: validate credentials failed: %v\n", err)
return a.templates.Render(ctx, w, r, tplLogin, errData)
} else if !valid {
if err := a.Events.FireAfter(authboss.EventAuthFail, ctx); err != nil {
2016-05-07 08:12:20 +02:00
fmt.Fprintf(ctx.LogWriter, "EventAuthFail callback error'd out: %v\n", err)
}
2015-02-21 09:33:35 +02:00
return a.templates.Render(ctx, w, r, tplLogin, errData)
2015-01-11 09:12:40 +02:00
}
interrupted, err := a.Events.FireBefore(authboss.EventAuth, ctx)
if err != nil {
return err
} else if interrupted != authboss.InterruptNone {
var reason string
switch interrupted {
case authboss.InterruptAccountLocked:
reason = "Your account has been locked."
case authboss.InterruptAccountNotConfirmed:
reason = "Your account has not been confirmed."
}
2015-04-01 00:27:47 +02:00
response.Redirect(ctx, w, r, a.AuthLoginFailPath, "", reason, false)
return nil
}
ctx.SessionStorer.Put(authboss.SessionKey, key)
ctx.SessionStorer.Del(authboss.SessionHalfAuthKey)
ctx.Values = map[string]string{authboss.CookieRemember: r.FormValue(authboss.CookieRemember)}
if err := a.Events.FireAfter(authboss.EventAuth, ctx); err != nil {
2015-02-26 09:20:02 +02:00
return err
}
2015-04-01 00:27:47 +02:00
response.Redirect(ctx, w, r, a.AuthLoginOKPath, "", "", true)
default:
w.WriteHeader(http.StatusMethodNotAllowed)
}
2015-02-21 09:33:35 +02:00
return nil
}
func validateCredentials(key, password string) (bool, error) {
if err := ctx.LoadUser(key); err == authboss.ErrUserNotFound {
return false, nil
} else if err != nil {
return false, err
}
2015-02-22 23:16:11 +02:00
actualPassword, err := ctx.User.StringErr(authboss.StorePassword)
2015-02-21 09:33:35 +02:00
if err != nil {
return false, err
}
2015-02-21 09:33:35 +02:00
if err := bcrypt.CompareHashAndPassword([]byte(actualPassword), []byte(password)); err != nil {
return false, nil
2015-01-11 08:49:06 +02:00
}
return true, nil
2015-01-11 08:49:06 +02:00
}
func (a *Auth) logout(w http.ResponseWriter, r *http.Request) error {
ctx.SessionStorer.Del(authboss.SessionKey)
ctx.CookieStorer.Del(authboss.CookieRemember)
ctx.SessionStorer.Del(authboss.SessionLastAction)
response.Redirect(ctx, w, r, a.AuthLogoutOKPath, "You have logged out", "", true)
2015-02-21 09:33:35 +02:00
return nil
}