Added SESSION_MAX_DURATION param

Added created_at field to the session
This commit is contained in:
0xCA 2024-01-03 18:48:30 +05:00
parent 9f527d18ac
commit a4d17ac489
5 changed files with 46 additions and 21 deletions

View file

@ -42,6 +42,7 @@ docker-compose up
| `BIND_ADDRESS` | The addresses that can access to the web interface and the port, use unix:///abspath/to/file.socket for unix domain socket. | 0.0.0.0:80 | | `BIND_ADDRESS` | The addresses that can access to the web interface and the port, use unix:///abspath/to/file.socket for unix domain socket. | 0.0.0.0:80 |
| `SESSION_SECRET` | The secret key used to encrypt the session cookies. Set this to a random value | N/A | | `SESSION_SECRET` | The secret key used to encrypt the session cookies. Set this to a random value | N/A |
| `SESSION_SECRET_FILE` | Optional filepath for the secret key used to encrypt the session cookies. Leave `SESSION_SECRET` blank to take effect | N/A | | `SESSION_SECRET_FILE` | Optional filepath for the secret key used to encrypt the session cookies. Leave `SESSION_SECRET` blank to take effect | N/A |
| `SESSION_MAX_DURATION` | Max time in days a remembered session is refreshed and valid. Non-refreshed session is valid for 7 days max, regardless of this setting. | 90 |
| `SUBNET_RANGES` | The list of address subdivision ranges. Format: `SR Name:10.0.1.0/24; SR2:10.0.2.0/24,10.0.3.0/24` Each CIDR must be inside one of the server interfaces. | N/A | | `SUBNET_RANGES` | The list of address subdivision ranges. Format: `SR Name:10.0.1.0/24; SR2:10.0.2.0/24,10.0.3.0/24` Each CIDR must be inside one of the server interfaces. | N/A |
| `WGUI_USERNAME` | The username for the login page. Used for db initialization only | `admin` | | `WGUI_USERNAME` | The username for the login page. Used for db initialization only | `admin` |
| `WGUI_PASSWORD` | The password for the user on the login page. Will be hashed automatically. Used for db initialization only | `admin` | | `WGUI_PASSWORD` | The password for the user on the login page. Will be hashed automatically. Used for db initialization only | `admin` |

View file

@ -110,12 +110,14 @@ func Login(db store.IStore) echo.HandlerFunc {
// set session_token // set session_token
tokenUID := xid.New().String() tokenUID := xid.New().String()
now := time.Now().UTC().Unix()
sess.Values["username"] = dbuser.Username sess.Values["username"] = dbuser.Username
sess.Values["user_hash"] = util.GetDBUserCRC32(dbuser) sess.Values["user_hash"] = util.GetDBUserCRC32(dbuser)
sess.Values["admin"] = dbuser.Admin sess.Values["admin"] = dbuser.Admin
sess.Values["session_token"] = tokenUID sess.Values["session_token"] = tokenUID
sess.Values["max_age"] = ageMax sess.Values["max_age"] = ageMax
sess.Values["updated_at"] = time.Now().UTC().Unix() sess.Values["created_at"] = now
sess.Values["updated_at"] = now
sess.Save(c.Request(), c.Response()) sess.Save(c.Request(), c.Response())
// set session_token in cookie // set session_token in cookie

View file

@ -53,6 +53,7 @@ func isValidSession(c echo.Context) bool {
} }
// Check time bounds // Check time bounds
createdAt := getCreatedAt(sess)
updatedAt := getUpdatedAt(sess) updatedAt := getUpdatedAt(sess)
maxAge := getMaxAge(sess) maxAge := getMaxAge(sess)
// Temporary session is considered valid within 24h if browser is not closed before // Temporary session is considered valid within 24h if browser is not closed before
@ -62,7 +63,7 @@ func isValidSession(c echo.Context) bool {
} }
expiration := updatedAt + int64(maxAge) expiration := updatedAt + int64(maxAge)
now := time.Now().UTC().Unix() now := time.Now().UTC().Unix()
if updatedAt > now || expiration < now { if updatedAt > now || expiration < now || createdAt+util.SessionMaxDuration < now {
return false return false
} }
@ -96,10 +97,11 @@ func doRefreshSession(c echo.Context) {
} }
// Refresh no sooner than 24h // Refresh no sooner than 24h
createdAt := getCreatedAt(sess)
updatedAt := getUpdatedAt(sess) updatedAt := getUpdatedAt(sess)
expiration := updatedAt + int64(getMaxAge(sess)) expiration := updatedAt + int64(getMaxAge(sess))
now := time.Now().UTC().Unix() now := time.Now().UTC().Unix()
if expiration < now || now-updatedAt < 86400 { if updatedAt > now || expiration < now || now-updatedAt < 86_400 || createdAt+util.SessionMaxDuration < now {
return return
} }
@ -140,6 +142,22 @@ func getMaxAge(sess *sessions.Session) int {
} }
} }
// Get a timestamp in seconds of the time the session was created
func getCreatedAt(sess *sessions.Session) int64 {
if util.DisableLogin {
return 0
}
createdAt := sess.Values["created_at"]
switch typedCreatedAt := createdAt.(type) {
case int64:
return typedCreatedAt
default:
return 0
}
}
// Get a timestamp in seconds of the last session update // Get a timestamp in seconds of the last session update
func getUpdatedAt(sess *sessions.Session) int64 { func getUpdatedAt(sess *sessions.Session) int64 {
if util.DisableLogin { if util.DisableLogin {

View file

@ -49,6 +49,7 @@ var (
flagTelegramAllowConfRequest = false flagTelegramAllowConfRequest = false
flagTelegramFloodWait = 60 flagTelegramFloodWait = 60
flagSessionSecret = util.RandomString(32) flagSessionSecret = util.RandomString(32)
flagSessionMaxDuration = 90
flagWgConfTemplate string flagWgConfTemplate string
flagBasePath string flagBasePath string
flagSubnetRanges string flagSubnetRanges string
@ -93,6 +94,7 @@ func init() {
flag.StringVar(&flagWgConfTemplate, "wg-conf-template", util.LookupEnvOrString("WG_CONF_TEMPLATE", flagWgConfTemplate), "Path to custom wg.conf template.") flag.StringVar(&flagWgConfTemplate, "wg-conf-template", util.LookupEnvOrString("WG_CONF_TEMPLATE", flagWgConfTemplate), "Path to custom wg.conf template.")
flag.StringVar(&flagBasePath, "base-path", util.LookupEnvOrString("BASE_PATH", flagBasePath), "The base path of the URL") flag.StringVar(&flagBasePath, "base-path", util.LookupEnvOrString("BASE_PATH", flagBasePath), "The base path of the URL")
flag.StringVar(&flagSubnetRanges, "subnet-ranges", util.LookupEnvOrString("SUBNET_RANGES", flagSubnetRanges), "IP ranges to choose from when assigning an IP for a client.") flag.StringVar(&flagSubnetRanges, "subnet-ranges", util.LookupEnvOrString("SUBNET_RANGES", flagSubnetRanges), "IP ranges to choose from when assigning an IP for a client.")
flag.IntVar(&flagSessionMaxDuration, "session-max-duration", util.LookupEnvOrInt("SESSION_MAX_DURATION", flagSessionMaxDuration), "Max time in days a remembered session is refreshed and valid.")
var ( var (
smtpPasswordLookup = util.LookupEnvOrString("SMTP_PASSWORD", flagSmtpPassword) smtpPasswordLookup = util.LookupEnvOrString("SMTP_PASSWORD", flagSmtpPassword)
@ -138,6 +140,7 @@ func init() {
util.EmailFrom = flagEmailFrom util.EmailFrom = flagEmailFrom
util.EmailFromName = flagEmailFromName util.EmailFromName = flagEmailFromName
util.SessionSecret = sha512.Sum512([]byte(flagSessionSecret)) util.SessionSecret = sha512.Sum512([]byte(flagSessionSecret))
util.SessionMaxDuration = int64(flagSessionMaxDuration) * 86_400 // Store in seconds
util.WgConfTemplate = flagWgConfTemplate util.WgConfTemplate = flagWgConfTemplate
util.BasePath = util.ParseBasePath(flagBasePath) util.BasePath = util.ParseBasePath(flagBasePath)
util.SubnetRanges = util.ParseSubnetRanges(flagSubnetRanges) util.SubnetRanges = util.ParseSubnetRanges(flagSubnetRanges)

View file

@ -9,24 +9,25 @@ import (
// Runtime config // Runtime config
var ( var (
DisableLogin bool DisableLogin bool
BindAddress string BindAddress string
SmtpHostname string SmtpHostname string
SmtpPort int SmtpPort int
SmtpUsername string SmtpUsername string
SmtpPassword string SmtpPassword string
SmtpNoTLSCheck bool SmtpNoTLSCheck bool
SmtpEncryption string SmtpEncryption string
SmtpAuthType string SmtpAuthType string
SmtpHelo string SmtpHelo string
SendgridApiKey string SendgridApiKey string
EmailFrom string EmailFrom string
EmailFromName string EmailFromName string
SessionSecret [64]byte SessionSecret [64]byte
WgConfTemplate string SessionMaxDuration int64
BasePath string WgConfTemplate string
SubnetRanges map[string]([]*net.IPNet) BasePath string
SubnetRangesOrder []string SubnetRanges map[string]([]*net.IPNet)
SubnetRangesOrder []string
) )
const ( const (