-
-
Notifications
You must be signed in to change notification settings - Fork 1.3k
Allow provide session max life #3567
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: develop
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||
|---|---|---|---|---|---|---|---|---|
|
|
@@ -47,8 +47,8 @@ func getSession(r *http.Request) (*db.Session, bool) { | |||||||
| return nil, false | ||||||||
| } | ||||||||
|
|
||||||||
| if time.Since(session.LastActive).Hours() > 7*24 { | ||||||||
| // more than week old unused session | ||||||||
| if time.Since(session.LastActive).Hours() > float64(util.Config.Auth.MaxSessionLifeHours) { | ||||||||
|
||||||||
| if time.Since(session.LastActive).Hours() > float64(util.Config.Auth.MaxSessionLifeHours) { | |
| if util.Config.Auth != nil && util.Config.Auth.MaxSessionLifeHours > 0 && | |
| time.Since(session.LastActive).Hours() > float64(util.Config.Auth.MaxSessionLifeHours) { |
| Original file line number | Diff line number | Diff line change | ||
|---|---|---|---|---|
|
|
@@ -40,10 +40,10 @@ require ( | |||
| github.com/sirupsen/logrus v1.9.3 // indirect | ||||
| github.com/skeema/knownhosts v1.3.1 // indirect | ||||
| github.com/xanzy/ssh-agent v0.3.3 // indirect | ||||
| golang.org/x/crypto v0.45.0 // indirect | ||||
| golang.org/x/crypto v0.46.0 // indirect | ||||
| golang.org/x/exp v0.0.0-20250620022241-b7579e27df2b // indirect | ||||
| golang.org/x/net v0.47.0 // indirect | ||||
| golang.org/x/sys v0.38.0 // indirect | ||||
| golang.org/x/sys v0.39.0 // indirect | ||||
|
||||
| golang.org/x/sys v0.39.0 // indirect |
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -49,8 +49,8 @@ func (s *sessionServiceImpl) GetSession(cookie http.Cookie) (*db.Session, bool) | |||||
| return nil, false | ||||||
| } | ||||||
|
|
||||||
| if time.Since(session.LastActive).Hours() > 7*24 { | ||||||
| // more than week old unused session | ||||||
| if time.Since(session.LastActive).Hours() > float64(util.Config.Auth.MaxSessionLifeHours) { | ||||||
|
||||||
| if time.Since(session.LastActive).Hours() > float64(util.Config.Auth.MaxSessionLifeHours) { | |
| if util.Config.Auth != nil && time.Since(session.LastActive).Hours() > float64(util.Config.Auth.MaxSessionLifeHours) { |
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -16,4 +16,9 @@ type EmailAuthConfig struct { | |||||
| type AuthConfig struct { | ||||||
| Totp *TotpConfig `json:"totp,omitempty"` | ||||||
| Email *EmailAuthConfig `json:"email,omitempty"` | ||||||
|
|
||||||
| // MaxSessionLifeHours defines the maximum lifetime of a session in hours. | ||||||
| // After this period of inactivity, the session will expire. | ||||||
|
||||||
| // After this period of inactivity, the session will expire. | |
| // When the time elapsed since the session was last active exceeds this value, the session will expire. |
Copilot
AI
Jan 19, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Missing input validation for MaxSessionLifeHours. Zero or negative values would cause sessions to never expire or behave unexpectedly. Consider adding a validation rule in the struct tag (similar to other fields like Port and MaxParallelTasks in config.go) to ensure the value is positive, or add validation logic in the validateConfig function.
| MaxSessionLifeHours int `json:"max_session_life_hours,omitempty" default:"168" env:"SEMAPHORE_MAX_SESSION_LIFE_HOURS"` | |
| MaxSessionLifeHours int `json:"max_session_life_hours,omitempty" default:"168" env:"SEMAPHORE_MAX_SESSION_LIFE_HOURS" validate:"gt=0"` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If
auth.max_session_life_hoursis not set in config/env,MaxSessionLifeHoursremains0becauseloadDefaultsToObjectdoesn’t descend into pointer-to-struct fields (likeAuthConfig), so the new default tag never applies. With a zero value,time.Since(...).Hours() > 0becomes true for essentially every existing session, and this code expires sessions immediately on the next request. This is a regression for installs that don’t set the new field (including the default setup flow which doesn’t write anauthsection). Consider explicitly handling a zero value here or ensuring defaults are applied to pointer fields.Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@codex fix it
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Summary
GetMaxSessionLifeHours()with a default fallback (168) whenConfig.Authis nil or whenmax_session_life_hoursis unset/invalid (<= 0), preventing nil dereference and accidental immediate session expiry. Also clarified the field comment wording to match actual behavior. util/config_auth.goL16-L34util.GetMaxSessionLifeHours()instead of directly dereferencingutil.Config.Auth.MaxSessionLifeHours. api/auth.goL50-L56util.GetMaxSessionLifeHours(). services/session_svc.goL52-L56workin commit0ca8b1a, and created a follow-up PR viamake_prtitled "[Follow-up] Fix session lifetime fallback when auth config is unset".Testing
gofmt -w api/auth.go services/session_svc.go util/config_auth.gogo test ./services ./utilgo test ./api ./services ./util(fails in this environment becauseapi/router.goexpectspublic/*assets not present during test setup)python - <<'PY' ... urllib.request.urlopen('https://duckduckgo.com/html/?q=golang struct tag validate gt=0') ... PY(web search attempt blocked by proxy tunnel403 Forbidden)View task →