Security Audit Fixes: Session fixation prevention, SameSite cookies, audit log redaction, backup integrity, Docker hardening, error sanitization, rate limiting, trusted proxies, and config hardening
This commit is contained in:
parent
7fc90524b5
commit
b587fb87a9
18 changed files with 987 additions and 87 deletions
|
|
@ -64,6 +64,10 @@ func (h *AuthHandler) Login(c *gin.Context) {
|
|||
}
|
||||
auth.DefaultLoginLimiter.RecordSuccess(clientIP)
|
||||
|
||||
// INVALIDATE ANY EXISTING SESSION FOR THIS USER
|
||||
// Delete any old sessions for this user before creating new one
|
||||
h.sessionRepo.DeleteByUserID(user.ID)
|
||||
|
||||
sessionData, err := auth.NewSessionData(user.ID)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to create session"})
|
||||
|
|
@ -122,22 +126,12 @@ func (h *AuthHandler) Me(c *gin.Context) {
|
|||
c.JSON(http.StatusUnauthorized, gin.H{"error": "not authenticated"})
|
||||
return
|
||||
}
|
||||
// Include current CSRF token for bootstrap after page reload
|
||||
var csrfToken string
|
||||
if sVal, exists := c.Get("session"); exists {
|
||||
if s, ok := sVal.(*models.Session); ok && s != nil {
|
||||
csrfToken = s.CSRFToken
|
||||
}
|
||||
}
|
||||
resp := gin.H{
|
||||
"id": user.ID,
|
||||
"username": user.Username,
|
||||
"email": user.Email,
|
||||
"role": user.Role,
|
||||
}
|
||||
if csrfToken != "" {
|
||||
resp["csrf_token"] = csrfToken
|
||||
}
|
||||
c.JSON(http.StatusOK, resp)
|
||||
}
|
||||
|
||||
|
|
@ -151,25 +145,28 @@ func (h *AuthHandler) GetCSRF(c *gin.Context) {
|
|||
}
|
||||
|
||||
func (h *AuthHandler) setSessionCookie(c *gin.Context, sessionID string, expiresAt time.Time) {
|
||||
c.SetCookie(
|
||||
SessionCookieName,
|
||||
sessionID,
|
||||
int(time.Until(expiresAt).Seconds()),
|
||||
"/",
|
||||
h.cookieDomain,
|
||||
h.cookieSecure,
|
||||
true, // HttpOnly
|
||||
)
|
||||
http.SetCookie(c.Writer, &http.Cookie{
|
||||
Name: SessionCookieName,
|
||||
Value: sessionID,
|
||||
MaxAge: int(time.Until(expiresAt).Seconds()),
|
||||
Path: "/",
|
||||
Domain: h.cookieDomain,
|
||||
Secure: h.cookieSecure,
|
||||
HttpOnly: true,
|
||||
SameSite: http.SameSiteStrictMode,
|
||||
Expires: expiresAt,
|
||||
})
|
||||
}
|
||||
|
||||
func (h *AuthHandler) clearSessionCookie(c *gin.Context) {
|
||||
c.SetCookie(
|
||||
SessionCookieName,
|
||||
"",
|
||||
-1,
|
||||
"/",
|
||||
h.cookieDomain,
|
||||
h.cookieSecure,
|
||||
true,
|
||||
)
|
||||
http.SetCookie(c.Writer, &http.Cookie{
|
||||
Name: SessionCookieName,
|
||||
Value: "",
|
||||
MaxAge: -1,
|
||||
Path: "/",
|
||||
Domain: h.cookieDomain,
|
||||
Secure: h.cookieSecure,
|
||||
HttpOnly: true,
|
||||
SameSite: http.SameSiteStrictMode,
|
||||
})
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue