From 19b2b6c2a9e9dcf737adebda8eb8ca8765b18baf Mon Sep 17 00:00:00 2001 From: Lou Knauer Date: Wed, 16 Feb 2022 11:50:25 +0100 Subject: [PATCH] Add config option for expiration of sessions/tokens --- auth/auth.go | 18 +++++++++++++++--- server.go | 15 +++++++++++++++ 2 files changed, 30 insertions(+), 3 deletions(-) diff --git a/auth/auth.go b/auth/auth.go index 57c16f8..6a6d6cd 100644 --- a/auth/auth.go +++ b/auth/auth.go @@ -12,6 +12,7 @@ import ( "net/http" "os" "strings" + "time" "github.com/ClusterCockpit/cc-backend/log" sq "github.com/Masterminds/squirrel" @@ -60,6 +61,10 @@ type Authentication struct { ldapConfig *LdapConfig ldapSyncUserPassword string + + // If zero, tokens/sessions do not expire. + SessionMaxAge time.Duration + JwtMaxAge time.Duration } func (auth *Authentication) Init(db *sqlx.DB, ldapConfig *LdapConfig) error { @@ -208,7 +213,9 @@ func (auth *Authentication) Login(onsuccess http.Handler, onfailure func(rw http return } - session.Options.MaxAge = 30 * 24 * 60 * 60 + if auth.SessionMaxAge != 0 { + session.Options.MaxAge = int(auth.SessionMaxAge.Seconds()) + } session.Values["username"] = user.Username session.Values["roles"] = user.Roles if err := auth.sessionStore.Save(r, rw, session); err != nil { @@ -320,10 +327,15 @@ func (auth *Authentication) ProvideJWT(user *User) (string, error) { return "", errors.New("environment variable 'JWT_PRIVATE_KEY' not set") } - tok := jwt.NewWithClaims(jwt.SigningMethodEdDSA, jwt.MapClaims{ + claims := jwt.MapClaims{ "sub": user.Username, "roles": user.Roles, - }) + } + if auth.JwtMaxAge != 0 { + claims["exp"] = time.Now().Add(auth.JwtMaxAge).Unix() + } + + tok := jwt.NewWithClaims(jwt.SigningMethodEdDSA, claims) return tok.SignedString(auth.jwtPrivateKey) } diff --git a/server.go b/server.go index da4fe92..7099ade 100644 --- a/server.go +++ b/server.go @@ -71,6 +71,12 @@ type ProgramConfig struct { // For LDAP Authentication and user syncronisation. LdapConfig *auth.LdapConfig `json:"ldap"` + // Specifies for how long a session or JWT shall be valid + // as a string parsable by time.ParseDuration(). + // If 0 or empty, the session/token does not expire! + SessionMaxAge string `json:"session-max-age"` + JwtMaxAge string `json:"jwt-max-age"` + // If both those options are not empty, use HTTPS using those certificates. HttpsCertFile string `json:"https-cert-file"` HttpsKeyFile string `json:"https-key-file"` @@ -92,6 +98,8 @@ var programConfig ProgramConfig = ProgramConfig{ JobArchive: "./var/job-archive", DisableArchive: false, LdapConfig: nil, + SessionMaxAge: "168h", + JwtMaxAge: "0", HttpsCertFile: "", HttpsKeyFile: "", UiDefaults: map[string]interface{}{ @@ -250,6 +258,13 @@ func main() { authentication := &auth.Authentication{} if !programConfig.DisableAuthentication { + if d, err := time.ParseDuration(programConfig.SessionMaxAge); err != nil { + authentication.SessionMaxAge = d + } + if d, err := time.ParseDuration(programConfig.JwtMaxAge); err != nil { + authentication.JwtMaxAge = d + } + if err := authentication.Init(db, programConfig.LdapConfig); err != nil { log.Fatal(err) }