From 87393d3c6417cf092399be81cad4bb41f43be88b Mon Sep 17 00:00:00 2001 From: Stavros Date: Wed, 5 Feb 2025 19:08:23 +0200 Subject: [PATCH] feat: add session expiry inside cookie (breaking) --- cmd/root.go | 8 ++++---- internal/auth/auth.go | 20 ++++++++++++++++---- internal/types/types.go | 2 +- 3 files changed, 21 insertions(+), 9 deletions(-) diff --git a/cmd/root.go b/cmd/root.go index 32af3a6..9cab4c9 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -89,7 +89,7 @@ var rootCmd = &cobra.Command{ HandleError(dockerErr, "Failed to initialize docker") // Create auth service - auth := auth.NewAuth(docker, users, oauthWhitelist) + auth := auth.NewAuth(docker, users, oauthWhitelist, config.SessionExpiry) // Create OAuth providers service providers := providers.NewProviders(oauthConfig) @@ -108,7 +108,7 @@ var rootCmd = &cobra.Command{ AppURL: config.AppURL, CookieSecure: config.CookieSecure, DisableContinue: config.DisableContinue, - CookieExpiry: config.CookieExpiry, + CookieExpiry: config.SessionExpiry, }, hooks, auth, providers) // Setup routes @@ -162,7 +162,7 @@ func init() { rootCmd.Flags().String("generic-user-url", "", "Generic OAuth user info URL.") rootCmd.Flags().Bool("disable-continue", false, "Disable continue screen and redirect to app directly.") rootCmd.Flags().String("oauth-whitelist", "", "Comma separated list of email addresses to whitelist when using OAuth.") - rootCmd.Flags().Int("cookie-expiry", 86400, "Cookie expiration time in seconds.") + rootCmd.Flags().Int("session-expiry", 86400, "Session (cookie) expiration time in seconds.") rootCmd.Flags().Int("log-level", 1, "Log level.") viper.BindEnv("port", "PORT") viper.BindEnv("address", "ADDRESS") @@ -190,7 +190,7 @@ func init() { viper.BindEnv("generic-user-url", "GENERIC_USER_URL") viper.BindEnv("disable-continue", "DISABLE_CONTINUE") viper.BindEnv("oauth-whitelist", "OAUTH_WHITELIST") - viper.BindEnv("cookie-expiry", "COOKIE_EXPIRY") + viper.BindEnv("session-expiry", "SESSION_EXPIRY") viper.BindEnv("log-level", "LOG_LEVEL") viper.BindPFlags(rootCmd.Flags()) } diff --git a/internal/auth/auth.go b/internal/auth/auth.go index dcedee7..8a1dfd3 100644 --- a/internal/auth/auth.go +++ b/internal/auth/auth.go @@ -3,6 +3,7 @@ package auth import ( "slices" "strings" + "time" "tinyauth/internal/docker" "tinyauth/internal/types" "tinyauth/internal/utils" @@ -13,11 +14,12 @@ import ( "golang.org/x/crypto/bcrypt" ) -func NewAuth(docker *docker.Docker, userList types.Users, oauthWhitelist []string) *Auth { +func NewAuth(docker *docker.Docker, userList types.Users, oauthWhitelist []string, sessionExpiry int) *Auth { return &Auth{ Docker: docker, Users: userList, OAuthWhitelist: oauthWhitelist, + SessionExpiry: sessionExpiry, } } @@ -25,6 +27,7 @@ type Auth struct { Users types.Users Docker *docker.Docker OAuthWhitelist []string + SessionExpiry int } func (auth *Auth) GetUser(username string) *types.User { @@ -59,6 +62,7 @@ func (auth *Auth) CreateSessionCookie(c *gin.Context, data *types.SessionCookie) log.Debug().Msg("Setting session cookie") sessions.Set("username", data.Username) sessions.Set("provider", data.Provider) + sessions.Set("expiry", time.Now().Add(time.Duration(auth.SessionExpiry)*time.Second).Unix()) sessions.Save() } @@ -75,17 +79,25 @@ func (auth *Auth) GetSessionCookie(c *gin.Context) (types.SessionCookie, error) cookieUsername := sessions.Get("username") cookieProvider := sessions.Get("provider") + cookieExpiry := sessions.Get("expiry") username, usernameOk := cookieUsername.(string) provider, providerOk := cookieProvider.(string) + expiry, expiryOk := cookieExpiry.(int64) - log.Debug().Str("username", username).Str("provider", provider).Msg("Parsed cookie") - - if !usernameOk || !providerOk { + if !usernameOk || !providerOk || !expiryOk { log.Warn().Msg("Session cookie invalid") return types.SessionCookie{}, nil } + if time.Now().Unix() > expiry { + log.Warn().Msg("Session cookie expired") + auth.DeleteSessionCookie(c) + return types.SessionCookie{}, nil + } + + log.Debug().Str("username", username).Str("provider", provider).Int64("expiry", expiry).Msg("Parsed cookie") + return types.SessionCookie{ Username: username, Provider: provider, diff --git a/internal/types/types.go b/internal/types/types.go index ef1afe4..defeca2 100644 --- a/internal/types/types.go +++ b/internal/types/types.go @@ -45,7 +45,7 @@ type Config struct { GenericUserURL string `mapstructure:"generic-user-url"` DisableContinue bool `mapstructure:"disable-continue"` OAuthWhitelist string `mapstructure:"oauth-whitelist"` - CookieExpiry int `mapstructure:"cookie-expiry"` + SessionExpiry int `mapstructure:"session-expiry"` LogLevel int8 `mapstructure:"log-level" validate:"min=-1,max=5"` }