security: 15-day session lifetime with 7-day auto-renewal
- Reduce SESSION_MAX_DURATION from 365 days to 15 days - Add SESSION_RENEWAL_THRESHOLD (7 days): sessions are only extended when fewer than 7 days remain, instead of refreshing on every request - Align cookie MaxAge with SESSION_MAX_DURATION (derived from the constant) - Enforce expiry in load(): expired sessions are deleted on first use and the caller receives an error, preventing Bearer-token replay of stale sessions that the securecookie age check would not catch Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
0803b3af61
commit
41fac845eb
2 changed files with 15 additions and 5 deletions
|
|
@ -50,7 +50,7 @@ func NewSessionStore(opts *happydns.Options, storage sessionUC.SessionStorage, k
|
|||
Codecs: securecookie.CodecsFromPairs(keyPairs...),
|
||||
options: &sessions.Options{
|
||||
Path: opts.BasePath + "/",
|
||||
MaxAge: 86400 * 30,
|
||||
MaxAge: int(sessionUC.SESSION_MAX_DURATION.Seconds()),
|
||||
Secure: opts.DevProxy == "" && opts.ExternalURL.Scheme != "http",
|
||||
HttpOnly: true,
|
||||
SameSite: http.SameSiteLaxMode,
|
||||
|
|
@ -171,6 +171,11 @@ func (s *SessionStore) load(session *sessions.Session) error {
|
|||
session.Values["created_on"] = mysession.IssuedAt
|
||||
}
|
||||
if !mysession.ExpiresOn.IsZero() {
|
||||
if mysession.ExpiresOn.Before(time.Now()) {
|
||||
// Session has expired; delete it and treat this as a new session.
|
||||
_ = s.storage.DeleteSession(session.ID)
|
||||
return fmt.Errorf("session has expired")
|
||||
}
|
||||
session.Values["expires_on"] = mysession.ExpiresOn
|
||||
}
|
||||
|
||||
|
|
@ -210,11 +215,12 @@ func (s *SessionStore) save(session *sessions.Session, ua string) error {
|
|||
}
|
||||
|
||||
if exOn == nil {
|
||||
expiresOn = time.Now().Add(time.Second * time.Duration(session.Options.MaxAge))
|
||||
expiresOn = time.Now().Add(sessionUC.SESSION_MAX_DURATION)
|
||||
} else {
|
||||
expiresOn = exOn.(time.Time)
|
||||
if expiresOn.Sub(time.Now().Add(time.Second*time.Duration(session.Options.MaxAge))) < 0 {
|
||||
expiresOn = time.Now().Add(time.Second * time.Duration(session.Options.MaxAge))
|
||||
// Auto-renew if the session expires within the renewal window.
|
||||
if time.Until(expiresOn) < sessionUC.SESSION_RENEWAL_THRESHOLD {
|
||||
expiresOn = time.Now().Add(sessionUC.SESSION_MAX_DURATION)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -33,7 +33,11 @@ import (
|
|||
"git.happydns.org/happyDomain/model"
|
||||
)
|
||||
|
||||
const SESSION_MAX_DURATION = 24 * 365 * time.Hour
|
||||
const SESSION_MAX_DURATION = 15 * 24 * time.Hour
|
||||
|
||||
// SESSION_RENEWAL_THRESHOLD is the remaining lifetime below which a session
|
||||
// is automatically renewed to SESSION_MAX_DURATION on the next request.
|
||||
const SESSION_RENEWAL_THRESHOLD = 7 * 24 * time.Hour
|
||||
|
||||
// Service handles all session-related operations.
|
||||
// This consolidates what were previously separate usecase structs into a single service.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue