From 4abe0a5dbab076dd091fbe82f8d7676f2a898fc7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miroslav=20=C5=A0ediv=C3=BD?= Date: Wed, 17 Mar 2021 14:09:10 +0100 Subject: [PATCH] move cookies to session + config. --- internal/api/session.go | 33 ++------------------------------ internal/config/session.go | 26 +++++++++++++++++++++++++ internal/session/auth.go | 39 +++++++++++++++++++++++++++++++++++--- internal/types/session.go | 2 ++ 4 files changed, 66 insertions(+), 34 deletions(-) diff --git a/internal/api/session.go b/internal/api/session.go index 9cbf9435..e45b8cc3 100644 --- a/internal/api/session.go +++ b/internal/api/session.go @@ -2,17 +2,12 @@ package api import ( "net/http" - "os" - "time" "demodesk/neko/internal/http/auth" "demodesk/neko/internal/types" "demodesk/neko/internal/utils" ) -var CookieExpirationDate = time.Now().Add(365 * 24 * time.Hour) -var UnsecureCookies = os.Getenv("DISABLE_SECURE_COOKIES") == "true" - type SessionLoginPayload struct { Username string `json:"username"` Password string `json:"password"` @@ -36,19 +31,7 @@ func (api *ApiManagerCtx) Login(w http.ResponseWriter, r *http.Request) { return } - sameSite := http.SameSiteNoneMode - if UnsecureCookies { - sameSite = http.SameSiteDefaultMode - } - - http.SetCookie(w, &http.Cookie{ - Name: "NEKO_SESSION", - Value: token, - Expires: CookieExpirationDate, - Secure: !UnsecureCookies, - SameSite: sameSite, - HttpOnly: true, - }) + api.sessions.CookieSetToken(w, token) utils.HttpSuccess(w, SessionDataPayload{ ID: session.ID(), @@ -66,19 +49,7 @@ func (api *ApiManagerCtx) Logout(w http.ResponseWriter, r *http.Request) { return } - sameSite := http.SameSiteNoneMode - if UnsecureCookies { - sameSite = http.SameSiteDefaultMode - } - - http.SetCookie(w, &http.Cookie{ - Name: "NEKO_SESSION", - Value: "", - Expires: time.Unix(0, 0), - Secure: !UnsecureCookies, - SameSite: sameSite, - HttpOnly: true, - }) + api.sessions.CookieClearToken(w) utils.HttpSuccess(w, true) } diff --git a/internal/config/session.go b/internal/config/session.go index 7fd88478..5cc946c9 100644 --- a/internal/config/session.go +++ b/internal/config/session.go @@ -1,6 +1,8 @@ package config import ( + "time" + "github.com/spf13/cobra" "github.com/spf13/viper" ) @@ -8,6 +10,10 @@ import ( type Session struct { ImplicitHosting bool APIToken string + + CookieName string + CookieExpiration time.Time + CookieSecure bool } func (Session) Init(cmd *cobra.Command) error { @@ -21,10 +27,30 @@ func (Session) Init(cmd *cobra.Command) error { return err } + // cookie + cmd.PersistentFlags().String("session.cookie.name", "NEKO_SESSION", "name of the cookie that holds token") + if err := viper.BindPFlag("session.cookie.name", cmd.PersistentFlags().Lookup("session.cookie.name")); err != nil { + return err + } + + cmd.PersistentFlags().Int("session.cookie.expiration", 365*24, "expiration of the cookie in hours") + if err := viper.BindPFlag("session.cookie.expiration", cmd.PersistentFlags().Lookup("session.cookie.expiration")); err != nil { + return err + } + + cmd.PersistentFlags().Bool("session.cookie.secure", true, "use secure cookies") + if err := viper.BindPFlag("session.cookie.secure", cmd.PersistentFlags().Lookup("session.cookie.secure")); err != nil { + return err + } + return nil } func (s *Session) Set() { s.ImplicitHosting = viper.GetBool("session.implicit_hosting") s.APIToken = viper.GetString("session.api_token") + + s.CookieName = viper.GetString("session.cookie.name") + s.CookieExpiration = time.Now().Add(time.Duration(viper.GetInt("session.cookie.expiration")) * time.Hour) + s.CookieSecure = viper.GetBool("session.cookie.secure") } diff --git a/internal/session/auth.go b/internal/session/auth.go index 99725cee..5619a234 100644 --- a/internal/session/auth.go +++ b/internal/session/auth.go @@ -4,12 +4,45 @@ import ( "fmt" "net/http" "strings" + "time" "demodesk/neko/internal/types" ) +func (manager *SessionManagerCtx) CookieSetToken(w http.ResponseWriter, token string) { + sameSite := http.SameSiteDefaultMode + if manager.config.CookieSecure { + sameSite = http.SameSiteNoneMode + } + + http.SetCookie(w, &http.Cookie{ + Name: manager.config.CookieName, + Value: token, + Expires: manager.config.CookieExpiration, + Secure: manager.config.CookieSecure, + SameSite: sameSite, + HttpOnly: true, + }) +} + +func (manager *SessionManagerCtx) CookieClearToken(w http.ResponseWriter) { + sameSite := http.SameSiteDefaultMode + if manager.config.CookieSecure { + sameSite = http.SameSiteNoneMode + } + + http.SetCookie(w, &http.Cookie{ + Name: manager.config.CookieName, + Value: "", + Expires: time.Unix(0, 0), + Secure: manager.config.CookieSecure, + SameSite: sameSite, + HttpOnly: true, + }) +} + func (manager *SessionManagerCtx) Authenticate(r *http.Request) (types.Session, error) { - token, ok := getToken(r) + token, ok := manager.getToken(r) if !ok { return nil, fmt.Errorf("no authentication provided") } @@ -26,7 +59,7 @@ func (manager *SessionManagerCtx) Authenticate(r *http.Request) (types.Session, return session, nil } -func getToken(r *http.Request) (string, bool) { +func (manager *SessionManagerCtx) getToken(r *http.Request) (string, bool) { // get from Header reqToken := r.Header.Get("Authorization") splitToken := strings.Split(reqToken, "Bearer ") @@ -35,7 +68,7 @@ func getToken(r *http.Request) (string, bool) { } // get from Cookie - cookie, err := r.Cookie("NEKO_SESSION") + cookie, err := r.Cookie(manager.config.CookieName) if err == nil { return cookie.Value, true } diff --git a/internal/types/session.go b/internal/types/session.go index 1a69f103..94a6c68a 100644 --- a/internal/types/session.go +++ b/internal/types/session.go @@ -50,5 +50,7 @@ type SessionManager interface { ImplicitHosting() bool + CookieSetToken(w http.ResponseWriter, token string) + CookieClearToken(w http.ResponseWriter) Authenticate(r *http.Request) (Session, error) }