mirror of
https://github.com/lordmathis/lemma.git
synced 2025-11-06 07:54:22 +00:00
Update session and cookie managers
This commit is contained in:
@@ -5,8 +5,8 @@ import (
|
||||
"net/http"
|
||||
)
|
||||
|
||||
// CookieService interface defines methods for generating cookies
|
||||
type CookieService interface {
|
||||
// CookieManager interface defines methods for generating cookies
|
||||
type CookieManager interface {
|
||||
GenerateAccessTokenCookie(token string) *http.Cookie
|
||||
GenerateRefreshTokenCookie(token string) *http.Cookie
|
||||
GenerateCSRFCookie(token string) *http.Cookie
|
||||
@@ -14,14 +14,14 @@ type CookieService interface {
|
||||
}
|
||||
|
||||
// CookieService
|
||||
type cookieService struct {
|
||||
type cookieManager struct {
|
||||
Domain string
|
||||
Secure bool
|
||||
SameSite http.SameSite
|
||||
}
|
||||
|
||||
// NewCookieService creates a new cookie service
|
||||
func NewCookieService(isDevelopment bool, domain string) CookieService {
|
||||
func NewCookieService(isDevelopment bool, domain string) CookieManager {
|
||||
secure := !isDevelopment
|
||||
var sameSite http.SameSite
|
||||
|
||||
@@ -31,7 +31,7 @@ func NewCookieService(isDevelopment bool, domain string) CookieService {
|
||||
sameSite = http.SameSiteStrictMode
|
||||
}
|
||||
|
||||
return &cookieService{
|
||||
return &cookieManager{
|
||||
Domain: domain,
|
||||
Secure: secure,
|
||||
SameSite: sameSite,
|
||||
@@ -39,7 +39,7 @@ func NewCookieService(isDevelopment bool, domain string) CookieService {
|
||||
}
|
||||
|
||||
// GenerateAccessTokenCookie creates a new cookie for the access token
|
||||
func (c *cookieService) GenerateAccessTokenCookie(token string) *http.Cookie {
|
||||
func (c *cookieManager) GenerateAccessTokenCookie(token string) *http.Cookie {
|
||||
return &http.Cookie{
|
||||
Name: "access_token",
|
||||
Value: token,
|
||||
@@ -52,7 +52,7 @@ func (c *cookieService) GenerateAccessTokenCookie(token string) *http.Cookie {
|
||||
}
|
||||
|
||||
// GenerateRefreshTokenCookie creates a new cookie for the refresh token
|
||||
func (c *cookieService) GenerateRefreshTokenCookie(token string) *http.Cookie {
|
||||
func (c *cookieManager) GenerateRefreshTokenCookie(token string) *http.Cookie {
|
||||
return &http.Cookie{
|
||||
Name: "refresh_token",
|
||||
Value: token,
|
||||
@@ -65,7 +65,7 @@ func (c *cookieService) GenerateRefreshTokenCookie(token string) *http.Cookie {
|
||||
}
|
||||
|
||||
// GenerateCSRFCookie creates a new cookie for the CSRF token
|
||||
func (c *cookieService) GenerateCSRFCookie(token string) *http.Cookie {
|
||||
func (c *cookieManager) GenerateCSRFCookie(token string) *http.Cookie {
|
||||
return &http.Cookie{
|
||||
Name: "csrf_token",
|
||||
Value: token,
|
||||
@@ -78,7 +78,7 @@ func (c *cookieService) GenerateCSRFCookie(token string) *http.Cookie {
|
||||
}
|
||||
|
||||
// InvalidateCookie creates a new cookie with a MaxAge of -1 to invalidate the cookie
|
||||
func (c *cookieService) InvalidateCookie(cookieType string) *http.Cookie {
|
||||
func (c *cookieManager) InvalidateCookie(cookieType string) *http.Cookie {
|
||||
return &http.Cookie{
|
||||
Name: cookieType,
|
||||
Value: "",
|
||||
|
||||
@@ -9,13 +9,17 @@ import (
|
||||
|
||||
// Middleware handles JWT authentication for protected routes
|
||||
type Middleware struct {
|
||||
jwtManager JWTManager
|
||||
jwtManager JWTManager
|
||||
sessionManager SessionManager
|
||||
cookieManager CookieManager
|
||||
}
|
||||
|
||||
// NewMiddleware creates a new authentication middleware
|
||||
func NewMiddleware(jwtManager JWTManager) *Middleware {
|
||||
func NewMiddleware(jwtManager JWTManager, sessionManager SessionManager, cookieManager CookieManager) *Middleware {
|
||||
return &Middleware{
|
||||
jwtManager: jwtManager,
|
||||
jwtManager: jwtManager,
|
||||
sessionManager: sessionManager,
|
||||
cookieManager: cookieManager,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,6 +46,16 @@ func (m *Middleware) Authenticate(next http.Handler) http.Handler {
|
||||
return
|
||||
}
|
||||
|
||||
// Check if session is still valid in database
|
||||
session, err := m.sessionManager.ValidateSession(claims.ID)
|
||||
if err != nil || session == nil {
|
||||
m.cookieManager.InvalidateCookie("access_token")
|
||||
m.cookieManager.InvalidateCookie("refresh_token")
|
||||
m.cookieManager.InvalidateCookie("csrf_token")
|
||||
http.Error(w, "Session invalid or expired", http.StatusUnauthorized)
|
||||
return
|
||||
}
|
||||
|
||||
// Add CSRF check for non-GET requests
|
||||
if r.Method != http.MethodGet && r.Method != http.MethodHead && r.Method != http.MethodOptions {
|
||||
csrfCookie, err := r.Cookie("csrf_token")
|
||||
|
||||
@@ -9,22 +9,30 @@ import (
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
// SessionService manages user sessions in the database
|
||||
type SessionService struct {
|
||||
type SessionManager interface {
|
||||
CreateSession(userID int, role string) (*models.Session, string, error)
|
||||
RefreshSession(refreshToken string) (string, error)
|
||||
ValidateSession(sessionID string) (*models.Session, error)
|
||||
InvalidateSession(token string) error
|
||||
CleanExpiredSessions() error
|
||||
}
|
||||
|
||||
// sessionManager manages user sessions in the database
|
||||
type sessionManager struct {
|
||||
db db.SessionStore // Database store for sessions
|
||||
jwtManager JWTManager // JWT Manager for token operations
|
||||
}
|
||||
|
||||
// NewSessionService creates a new session service with the given database and JWT manager
|
||||
func NewSessionService(db db.SessionStore, jwtManager JWTManager) *SessionService {
|
||||
return &SessionService{
|
||||
func NewSessionService(db db.SessionStore, jwtManager JWTManager) *sessionManager {
|
||||
return &sessionManager{
|
||||
db: db,
|
||||
jwtManager: jwtManager,
|
||||
}
|
||||
}
|
||||
|
||||
// CreateSession creates a new user session for a user with the given userID and role
|
||||
func (s *SessionService) CreateSession(userID int, role string) (*models.Session, string, error) {
|
||||
func (s *sessionManager) CreateSession(userID int, role string) (*models.Session, string, error) {
|
||||
// Generate both access and refresh tokens
|
||||
accessToken, err := s.jwtManager.GenerateAccessToken(userID, role)
|
||||
if err != nil {
|
||||
@@ -60,7 +68,7 @@ func (s *SessionService) CreateSession(userID int, role string) (*models.Session
|
||||
}
|
||||
|
||||
// RefreshSession creates a new access token using a refreshToken
|
||||
func (s *SessionService) RefreshSession(refreshToken string) (string, error) {
|
||||
func (s *sessionManager) RefreshSession(refreshToken string) (string, error) {
|
||||
// Get session from database first
|
||||
session, err := s.db.GetSessionByRefreshToken(refreshToken)
|
||||
if err != nil {
|
||||
@@ -82,8 +90,20 @@ func (s *SessionService) RefreshSession(refreshToken string) (string, error) {
|
||||
return s.jwtManager.GenerateAccessToken(claims.UserID, claims.Role)
|
||||
}
|
||||
|
||||
// ValidateSession checks if a session with the given sessionID is valid
|
||||
func (s *sessionManager) ValidateSession(sessionID string) (*models.Session, error) {
|
||||
|
||||
// Get the session from the database
|
||||
session, err := s.db.GetSessionByID(sessionID)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to get session: %w", err)
|
||||
}
|
||||
|
||||
return session, nil
|
||||
}
|
||||
|
||||
// InvalidateSession removes a session with the given sessionID from the database
|
||||
func (s *SessionService) InvalidateSession(token string) error {
|
||||
func (s *sessionManager) InvalidateSession(token string) error {
|
||||
// Parse the JWT to get the session info
|
||||
claims, err := s.jwtManager.ValidateToken(token)
|
||||
if err != nil {
|
||||
@@ -94,6 +114,6 @@ func (s *SessionService) InvalidateSession(token string) error {
|
||||
}
|
||||
|
||||
// CleanExpiredSessions removes all expired sessions from the database
|
||||
func (s *SessionService) CleanExpiredSessions() error {
|
||||
func (s *sessionManager) CleanExpiredSessions() error {
|
||||
return s.db.CleanExpiredSessions()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user