mirror of
https://github.com/teamhanko/hanko.git
synced 2025-10-26 13:27:57 +08:00
125 lines
3.3 KiB
Go
125 lines
3.3 KiB
Go
package handler
|
|
|
|
import (
|
|
"fmt"
|
|
echojwt "github.com/labstack/echo-jwt/v4"
|
|
"github.com/labstack/echo/v4"
|
|
"github.com/teamhanko/hanko/backend/v2/config"
|
|
"github.com/teamhanko/hanko/backend/v2/dto"
|
|
"github.com/teamhanko/hanko/backend/v2/persistence"
|
|
"github.com/teamhanko/hanko/backend/v2/session"
|
|
"net/http"
|
|
"time"
|
|
)
|
|
|
|
type SessionHandler struct {
|
|
persister persistence.Persister
|
|
sessionManager session.Manager
|
|
cfg config.Config
|
|
}
|
|
|
|
func NewSessionHandler(persister persistence.Persister, sessionManager session.Manager, cfg config.Config) *SessionHandler {
|
|
return &SessionHandler{
|
|
persister: persister,
|
|
sessionManager: sessionManager,
|
|
cfg: cfg,
|
|
}
|
|
}
|
|
|
|
func (h *SessionHandler) ValidateSession(c echo.Context) error {
|
|
lookup := fmt.Sprintf("header:Authorization:Bearer,cookie:%s", h.cfg.Session.Cookie.GetName())
|
|
extractors, err := echojwt.CreateExtractors(lookup)
|
|
|
|
if err != nil {
|
|
return c.JSON(http.StatusOK, dto.ValidateSessionResponse{IsValid: false})
|
|
}
|
|
|
|
for _, extractor := range extractors {
|
|
auths, extractorErr := extractor(c)
|
|
if extractorErr != nil {
|
|
continue
|
|
}
|
|
for _, auth := range auths {
|
|
token, tokenErr := h.sessionManager.Verify(auth)
|
|
if tokenErr != nil {
|
|
continue
|
|
}
|
|
|
|
claims, err := dto.GetClaimsFromToken(token)
|
|
if err != nil {
|
|
return echo.NewHTTPError(http.StatusBadRequest, fmt.Errorf("failed to parse token claims: %w", err))
|
|
}
|
|
|
|
sessionModel, err := h.persister.GetSessionPersister().Get(claims.SessionID)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to get session from database: %w", err)
|
|
}
|
|
if sessionModel == nil {
|
|
continue
|
|
}
|
|
|
|
// Update lastUsed field
|
|
sessionModel.LastUsed = time.Now().UTC()
|
|
err = h.persister.GetSessionPersister().Update(*sessionModel)
|
|
if err != nil {
|
|
return dto.ToHttpError(err)
|
|
}
|
|
|
|
return c.JSON(http.StatusOK, dto.ValidateSessionResponse{
|
|
IsValid: true,
|
|
Claims: claims,
|
|
ExpirationTime: &claims.Expiration,
|
|
UserID: &claims.Subject,
|
|
})
|
|
}
|
|
}
|
|
|
|
return c.JSON(http.StatusOK, dto.ValidateSessionResponse{IsValid: false})
|
|
}
|
|
|
|
func (h *SessionHandler) ValidateSessionFromBody(c echo.Context) error {
|
|
var request dto.ValidateSessionRequest
|
|
err := (&echo.DefaultBinder{}).BindBody(c, &request)
|
|
if err != nil {
|
|
return dto.ToHttpError(err)
|
|
}
|
|
|
|
err = c.Validate(request)
|
|
if err != nil {
|
|
return echo.NewHTTPError(http.StatusBadRequest, err)
|
|
}
|
|
|
|
token, err := h.sessionManager.Verify(request.SessionToken)
|
|
if err != nil {
|
|
return c.JSON(http.StatusOK, dto.ValidateSessionResponse{IsValid: false})
|
|
}
|
|
|
|
claims, err := dto.GetClaimsFromToken(token)
|
|
if err != nil {
|
|
return echo.NewHTTPError(http.StatusBadRequest, fmt.Errorf("failed to parse token claims: %w", err))
|
|
}
|
|
|
|
sessionModel, err := h.persister.GetSessionPersister().Get(claims.SessionID)
|
|
if err != nil {
|
|
return dto.ToHttpError(err)
|
|
}
|
|
|
|
if sessionModel == nil {
|
|
return c.JSON(http.StatusOK, dto.ValidateSessionResponse{IsValid: false})
|
|
}
|
|
|
|
// update lastUsed field
|
|
sessionModel.LastUsed = time.Now().UTC()
|
|
err = h.persister.GetSessionPersister().Update(*sessionModel)
|
|
if err != nil {
|
|
return dto.ToHttpError(err)
|
|
}
|
|
|
|
return c.JSON(http.StatusOK, dto.ValidateSessionResponse{
|
|
IsValid: true,
|
|
Claims: claims,
|
|
ExpirationTime: &claims.Expiration,
|
|
UserID: &claims.Subject,
|
|
})
|
|
}
|