fix: use constant time in user lookups

This commit is contained in:
Stavros
2026-07-14 15:14:26 +03:00
parent e75605b2c5
commit 5c2cb08a7a
+39 -15
View File
@@ -89,21 +89,30 @@ func (controller *UserController) loginHandler(c *gin.Context) {
search, err := controller.auth.SearchUser(req.Username) search, err := controller.auth.SearchUser(req.Username)
if err != nil { if err != nil {
if errors.Is(err, service.ErrUserNotFound) { controller.constantTime(func() constantTimeRes {
controller.log.App.Warn().Str("username", req.Username).Msg("User not found during login attempt") if errors.Is(err, service.ErrUserNotFound) {
controller.auth.RecordLoginAttempt(req.Username, false) controller.log.App.Warn().Str("username", req.Username).Msg("User not found during login attempt")
controller.log.AuditLoginFailure(req.Username, "unknown", c.ClientIP(), "user not found") controller.auth.RecordLoginAttempt(req.Username, false)
c.JSON(401, gin.H{ controller.log.AuditLoginFailure(req.Username, "unknown", c.ClientIP(), "user not found")
"status": 401, return constantTimeRes{
"message": "Unauthorized", Code: 401,
}) Res: gin.H{
return "status": 401,
} "message": "Unauthorized",
controller.log.App.Error().Err(err).Str("username", req.Username).Msg("Error searching for user during login attempt") },
c.JSON(500, gin.H{ }
"status": 500, }
"message": "Internal Server Error", controller.log.App.Error().Err(err).Str("username", req.Username).Msg("Error searching for user during login attempt")
}) return constantTimeRes{
Code: 500,
Res: gin.H{
"status": 500,
"message": "Internal Server Error",
},
}
}, func(res constantTimeRes) {
c.JSON(res.Code, res.Res)
}, time.Millisecond*45)
return return
} }
@@ -466,3 +475,18 @@ func (controller *UserController) tailscaleHandler(c *gin.Context) {
"message": "Login successful", "message": "Login successful",
}) })
} }
type constantTimeRes struct {
Code int
Res any
}
func (controller *UserController) constantTime(f func() constantTimeRes, rf func(res constantTimeRes), targetTime time.Duration) {
tStart := time.Now()
res := f()
tEnd := time.Now()
if tEnd.Sub(tStart) < targetTime {
time.Sleep(targetTime - tEnd.Sub(tStart))
}
rf(res)
}