Add 2FA code grace time

This commit is contained in:
Taras Kushnir
2026-01-30 08:29:13 +02:00
parent 70d3bf9de1
commit 6d405eec80
4 changed files with 9 additions and 6 deletions

View File

@@ -221,6 +221,7 @@ func run(ctx context.Context, cfg common.ConfigStore, stderr io.Writer, listener
UserLimiter: userLimiter,
SubscriptionLimits: subscriptionLimits,
EmailVerifier: &portal.PortalEmailVerifier{},
TwoFactorDuration: 10*time.Minute + 5*time.Minute,
}
templatesBuilder := portal.NewTemplatesBuilder()

View File

@@ -153,6 +153,7 @@ type Server struct {
AuditLogParser AuditLogParser
SubscriptionLimits db.SubscriptionLimits
EmailVerifier common.EmailVerifier
TwoFactorDuration time.Duration
}
func (s *Server) createSettingsTabs() []*SettingsTab {
@@ -206,6 +207,11 @@ func (s *Server) Init(ctx context.Context, templateBuilder *TemplatesBuilder, gi
s.PlatformCtx = platformCtx
if s.TwoFactorDuration == 0 {
// 10 minutes + grace time (just like usual TOTP)
s.TwoFactorDuration = 10*time.Minute + 5*time.Minute
}
return nil
}

View File

@@ -352,7 +352,7 @@ func (s *Server) putGeneralSettings(w http.ResponseWriter, r *http.Request) (*Vi
_ = sess.Delete(ctx, session.KeyTwoFactorCode)
_ = sess.Delete(ctx, session.KeyTwoFactorCodeTimestamp)
if enteredCode, err := strconv.Atoi(formCode); !hasSentCode || (err != nil) || (enteredCode != sentCode) || (!codeTimestamp.IsZero() && tnow.After(codeTimestamp.Add(twoFactorCodeDuration))) {
if enteredCode, err := strconv.Atoi(formCode); !hasSentCode || (err != nil) || (enteredCode != sentCode) || (!codeTimestamp.IsZero() && tnow.After(codeTimestamp.Add(s.TwoFactorDuration))) {
slog.WarnContext(ctx, "Code verification failed", "actual", formCode, "expected", sentCode, "timestamp", codeTimestamp, common.ErrAttr(err))
renderCtx.TwoFactorError = "Code is not valid."
return &ViewModel{Model: renderCtx, View: settingsGeneralFormTemplate}, nil

View File

@@ -13,10 +13,6 @@ import (
"github.com/PrivateCaptcha/PrivateCaptcha/pkg/session"
)
const (
twoFactorCodeDuration = 10 * time.Minute
)
var (
renderContextNothing = struct{}{}
)
@@ -82,7 +78,7 @@ func (s *Server) postTwoFactor(w http.ResponseWriter, r *http.Request) {
}
formCode := strings.TrimSpace(r.FormValue(common.ParamVerificationCode))
if enteredCode, err := strconv.Atoi(formCode); (err != nil) || (enteredCode != sentCode) || (!codeTimestamp.IsZero() && tnow.After(codeTimestamp.Add(twoFactorCodeDuration))) {
if enteredCode, err := strconv.Atoi(formCode); (err != nil) || (enteredCode != sentCode) || (!codeTimestamp.IsZero() && tnow.After(codeTimestamp.Add(s.TwoFactorDuration))) {
data.CodeError = "Code is not valid."
slog.WarnContext(ctx, "Code verification failed", "actual", formCode, "expected", sentCode, "timestamp", codeTimestamp, common.ErrAttr(err))
s.render(w, r, "login/twofactor-form.html", data)