fix auth pending session hardening

This commit is contained in:
IanShaw027
2026-04-21 01:45:25 +08:00
parent 1d8432b8a4
commit 7c6491c2d3
12 changed files with 490 additions and 32 deletions

View File

@@ -1,6 +1,7 @@
package handler
import (
"context"
"log/slog"
"strings"
@@ -105,6 +106,34 @@ func (h *AuthHandler) respondWithTokenPair(c *gin.Context, user *service.User) {
})
}
func (h *AuthHandler) ensureBackendModeAllowsUser(ctx context.Context, user *service.User) error {
if user == nil {
return infraerrors.Unauthorized("INVALID_USER", "user not found")
}
if h == nil || !h.isBackendModeEnabled(ctx) || user.IsAdmin() {
return nil
}
return infraerrors.Forbidden("BACKEND_MODE_ADMIN_ONLY", "Backend mode is active. Only admin login is allowed.")
}
func (h *AuthHandler) ensureBackendModeAllowsNewUserLogin(ctx context.Context) error {
if h == nil || !h.isBackendModeEnabled(ctx) {
return nil
}
return infraerrors.Forbidden("BACKEND_MODE_ADMIN_ONLY", "Backend mode is active. Only admin login is allowed.")
}
func (h *AuthHandler) isBackendModeEnabled(ctx context.Context) bool {
if h == nil || h.settingSvc == nil {
return false
}
settings, err := h.settingSvc.GetPublicSettings(ctx)
if err == nil && settings != nil {
return settings.BackendModeEnabled
}
return h.settingSvc.IsBackendModeEnabled(ctx)
}
// Register handles user registration
// POST /api/v1/auth/register
func (h *AuthHandler) Register(c *gin.Context) {
@@ -178,6 +207,11 @@ func (h *AuthHandler) Login(c *gin.Context) {
}
_ = token // token 由 authService.Login 返回但此处由 respondWithTokenPair 重新生成
if err := h.ensureBackendModeAllowsUser(c.Request.Context(), user); err != nil {
response.ErrorFrom(c, err)
return
}
// Check if TOTP 2FA is enabled for this user
if h.totpService != nil && h.settingSvc.IsTotpEnabled(c.Request.Context()) && user.TotpEnabled {
// Create a temporary login session for 2FA
@@ -195,11 +229,7 @@ func (h *AuthHandler) Login(c *gin.Context) {
return
}
// Backend mode: only admin can login
if h.settingSvc.IsBackendModeEnabled(c.Request.Context()) && !user.IsAdmin() {
response.Forbidden(c, "Backend mode is active. Only admin login is allowed.")
return
}
h.authService.RecordSuccessfulLogin(c.Request.Context(), user.ID)
h.respondWithTokenPair(c, user)
}
@@ -264,9 +294,8 @@ func (h *AuthHandler) Login2FA(c *gin.Context) {
return
}
// Backend mode: only admin can login (check BEFORE deleting session)
if h.settingSvc.IsBackendModeEnabled(c.Request.Context()) && !user.IsAdmin() {
response.Forbidden(c, "Backend mode is active. Only admin login is allowed.")
if err := h.ensureBackendModeAllowsUser(c.Request.Context(), user); err != nil {
response.ErrorFrom(c, err)
return
}
@@ -330,6 +359,10 @@ func (h *AuthHandler) Login2FA(c *gin.Context) {
// Delete the login session (only after all checks pass)
_ = h.totpService.DeleteLoginSession(c.Request.Context(), req.TempToken)
if session.PendingOAuthBind == nil {
h.authService.RecordSuccessfulLogin(c.Request.Context(), user.ID)
}
h.respondWithTokenPair(c, user)
}