Merge SEC-03: require token proximity for renewal

# Conflicts:
#	internal/server/server_test.go
This commit is contained in:
2026-03-13 01:07:34 -07:00
5 changed files with 99 additions and 15 deletions

View File

@@ -18,6 +18,7 @@ import (
"log/slog"
"net"
"net/http"
"time"
"git.wntrmute.dev/kyle/mcias/internal/audit"
"git.wntrmute.dev/kyle/mcias/internal/auth"
@@ -350,6 +351,15 @@ func (s *Server) handleLogout(w http.ResponseWriter, r *http.Request) {
func (s *Server) handleRenew(w http.ResponseWriter, r *http.Request) {
claims := middleware.ClaimsFromContext(r.Context())
// Security: only allow renewal when the token has consumed at least 50% of
// its lifetime. This prevents indefinite renewal of stolen tokens (SEC-03).
totalLifetime := claims.ExpiresAt.Sub(claims.IssuedAt)
elapsed := time.Since(claims.IssuedAt)
if elapsed < totalLifetime/2 {
middleware.WriteError(w, http.StatusBadRequest, "token is not yet eligible for renewal", "renewal_too_early")
return
}
// Load account to get current roles (they may have changed since token issuance).
acct, err := s.db.GetAccountByUUID(claims.Subject)
if err != nil {