88 lines
2.7 KiB
Go
88 lines
2.7 KiB
Go
package hwsauth
|
|
|
|
import (
|
|
"net/http"
|
|
"time"
|
|
|
|
"git.haelnorr.com/h/golib/hws"
|
|
"github.com/pkg/errors"
|
|
)
|
|
|
|
// LoginReq returns a middleware that requires the user to be authenticated.
|
|
// If the user is not authenticated, it returns a 401 Unauthorized error page.
|
|
//
|
|
// Example:
|
|
//
|
|
// protectedHandler := auth.LoginReq(http.HandlerFunc(dashboardHandler))
|
|
// server.AddRoute("GET", "/dashboard", protectedHandler)
|
|
func (auth *Authenticator[T, TX]) LoginReq(next http.Handler) http.Handler {
|
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
_, ok := getAuthorizedModel[T](r.Context())
|
|
if !ok {
|
|
err := auth.server.ThrowError(w, r, hws.HWSError{
|
|
Error: errors.New("Login required"),
|
|
Message: "Please login to view this page",
|
|
StatusCode: http.StatusUnauthorized,
|
|
RenderErrorPage: true,
|
|
})
|
|
if err != nil {
|
|
auth.server.ThrowFatal(w, err)
|
|
}
|
|
return
|
|
}
|
|
next.ServeHTTP(w, r)
|
|
})
|
|
}
|
|
|
|
// LogoutReq returns a middleware that redirects authenticated users to the landing page.
|
|
// Use this for login and registration pages to prevent logged-in users from accessing them.
|
|
//
|
|
// Example:
|
|
//
|
|
// loginPageHandler := auth.LogoutReq(http.HandlerFunc(showLoginPage))
|
|
// server.AddRoute("GET", "/login", loginPageHandler)
|
|
func (auth *Authenticator[T, TX]) LogoutReq(next http.Handler) http.Handler {
|
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
_, ok := getAuthorizedModel[T](r.Context())
|
|
if ok {
|
|
http.Redirect(w, r, auth.LandingPage, http.StatusFound)
|
|
return
|
|
}
|
|
next.ServeHTTP(w, r)
|
|
})
|
|
}
|
|
|
|
// FreshReq returns a middleware that requires a fresh authentication token.
|
|
// If the token is not fresh (recently issued), it returns a 444 status code.
|
|
// Use this for sensitive operations like password changes or account deletions.
|
|
//
|
|
// Example:
|
|
//
|
|
// changePasswordHandler := auth.FreshReq(http.HandlerFunc(handlePasswordChange))
|
|
// server.AddRoute("POST", "/change-password", changePasswordHandler)
|
|
//
|
|
// The 444 status code can be used by the client to prompt for re-authentication.
|
|
func (auth *Authenticator[T, TX]) FreshReq(next http.Handler) http.Handler {
|
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
model, ok := getAuthorizedModel[T](r.Context())
|
|
if !ok {
|
|
err := auth.server.ThrowError(w, r, hws.HWSError{
|
|
Error: errors.New("Login required"),
|
|
Message: "Please login to view this page",
|
|
StatusCode: http.StatusUnauthorized,
|
|
RenderErrorPage: true,
|
|
})
|
|
if err != nil {
|
|
auth.server.ThrowFatal(w, err)
|
|
}
|
|
return
|
|
}
|
|
isFresh := time.Now().Before(time.Unix(model.fresh, 0))
|
|
if !isFresh {
|
|
w.WriteHeader(444)
|
|
return
|
|
}
|
|
next.ServeHTTP(w, r)
|
|
})
|
|
}
|