Add session cookie handling for authentication

This commit is contained in:
Luis Eduardo Jeréz Girón
2024-07-22 21:12:03 -06:00
parent de0d448b88
commit a3743eac02
5 changed files with 68 additions and 3 deletions
+6
View File
@@ -1,10 +1,16 @@
package auth
import (
"time"
"github.com/eduardolat/pgbackweb/internal/config"
"github.com/eduardolat/pgbackweb/internal/database/dbgen"
)
const (
maxSessionAge = time.Hour * 12
)
type Service struct {
env *config.Env
dbgen *dbgen.Queries
+23
View File
@@ -0,0 +1,23 @@
package auth
import (
"net/http"
"github.com/eduardolat/pgbackweb/internal/database/dbgen"
"github.com/labstack/echo/v4"
)
const (
sessionCookieName = "pbw_session"
)
func (s *Service) SetSessionCookie(c echo.Context, session dbgen.Session) {
cookie := http.Cookie{
Name: sessionCookieName,
Value: session.Token,
MaxAge: int(maxSessionAge.Seconds()),
HttpOnly: true,
SameSite: http.SameSiteStrictMode,
}
c.SetCookie(&cookie)
}
@@ -7,8 +7,6 @@ import (
"github.com/eduardolat/pgbackweb/internal/logger"
)
const maxSessionAge = time.Hour * 12
func (s *Service) DeleteOldSessions() {
ctx := context.Background()
dateThreshold := time.Now().Add(-maxSessionAge)
+38 -1
View File
@@ -4,8 +4,11 @@ import (
"net/http"
lucide "github.com/eduardolat/gomponents-lucide"
"github.com/eduardolat/pgbackweb/internal/logger"
"github.com/eduardolat/pgbackweb/internal/util/echoutil"
"github.com/eduardolat/pgbackweb/internal/validate"
"github.com/eduardolat/pgbackweb/internal/view/web/component"
"github.com/eduardolat/pgbackweb/internal/view/web/htmx"
"github.com/eduardolat/pgbackweb/internal/view/web/layout"
"github.com/labstack/echo/v4"
"github.com/maragudk/gomponents"
@@ -21,6 +24,8 @@ func loginPage() gomponents.Node {
component.H1Text("Login"),
html.Form(
htmx.HxPost("/auth/login"),
htmx.HxDisabledELT("find button"),
html.Class("mt-4 space-y-2"),
component.InputControl(component.InputControlParams{
@@ -42,7 +47,8 @@ func loginPage() gomponents.Node {
}),
html.Div(
html.Class("pt-2 grid place-items-end"),
html.Class("pt-2 flex justify-end items-center space-x-2"),
component.HxLoadingMd(),
html.Button(
html.Class("btn btn-primary"),
html.Type("submit"),
@@ -58,3 +64,34 @@ func loginPage() gomponents.Node {
Body: content,
})
}
func (h *handlers) loginHandler(c echo.Context) error {
ctx := c.Request().Context()
var formData struct {
Email string `form:"email" validate:"required,email"`
Password string `form:"password" validate:"required,max=50"`
}
if err := c.Bind(&formData); err != nil {
return htmx.RespondToastError(c, err.Error())
}
if err := validate.Struct(&formData); err != nil {
return htmx.RespondToastError(c, err.Error())
}
session, err := h.servs.AuthService.Login(
ctx, formData.Email, formData.Password, c.RealIP(), c.Request().UserAgent(),
)
if err != nil {
logger.Error("login failed", logger.KV{
"email": formData.Email,
"ip": c.RealIP(),
"ua": c.Request().UserAgent(),
"err": err,
})
return htmx.RespondToastError(c, "Login failed")
}
h.servs.AuthService.SetSessionCookie(c, session)
return htmx.RespondRedirect(c, "/dashboard")
}
+1
View File
@@ -16,4 +16,5 @@ func MountRouter(parent *echo.Group, servs *service.Service) {
parent.POST("/create-first-user", h.createFirstUserHandler)
parent.GET("/login", h.loginPageHandler)
parent.POST("/login", h.loginHandler)
}