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
+29 -5
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 {
controller.constantTime(func() constantTimeRes {
if errors.Is(err, service.ErrUserNotFound) { if errors.Is(err, service.ErrUserNotFound) {
controller.log.App.Warn().Str("username", req.Username).Msg("User not found during login attempt") controller.log.App.Warn().Str("username", req.Username).Msg("User not found during login attempt")
controller.auth.RecordLoginAttempt(req.Username, false) controller.auth.RecordLoginAttempt(req.Username, false)
controller.log.AuditLoginFailure(req.Username, "unknown", c.ClientIP(), "user not found") controller.log.AuditLoginFailure(req.Username, "unknown", c.ClientIP(), "user not found")
c.JSON(401, gin.H{ return constantTimeRes{
Code: 401,
Res: gin.H{
"status": 401, "status": 401,
"message": "Unauthorized", "message": "Unauthorized",
}) },
return }
} }
controller.log.App.Error().Err(err).Str("username", req.Username).Msg("Error searching for user during login attempt") controller.log.App.Error().Err(err).Str("username", req.Username).Msg("Error searching for user during login attempt")
c.JSON(500, gin.H{ return constantTimeRes{
Code: 500,
Res: gin.H{
"status": 500, "status": 500,
"message": "Internal Server Error", "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)
}