diff --git a/cmd/root.go b/cmd/root.go index 6b52983..3cd4c1e 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -2,7 +2,6 @@ package cmd import ( "errors" - "fmt" "os" "strings" "time" @@ -94,10 +93,8 @@ var rootCmd = &cobra.Command{ } // Create handlers config - serverConfig := types.HandlersConfig{ + handlersConfig := types.HandlersConfig{ AppURL: config.AppURL, - Domain: fmt.Sprintf(".%s", domain), - CookieSecure: config.CookieSecure, DisableContinue: config.DisableContinue, Title: config.Title, GenericName: config.GenericName, @@ -141,7 +138,7 @@ var rootCmd = &cobra.Command{ hooks := hooks.NewHooks(auth, providers) // Create handlers - handlers := handlers.NewHandlers(serverConfig, auth, hooks, providers, docker) + handlers := handlers.NewHandlers(handlersConfig, auth, hooks, providers, docker) // Create API api := api.NewAPI(apiConfig, handlers) diff --git a/internal/api/api_test.go b/internal/api/api_test.go index c4477c2..6a122b0 100644 --- a/internal/api/api_test.go +++ b/internal/api/api_test.go @@ -28,8 +28,6 @@ var apiConfig = types.APIConfig{ // Simple handlers config for tests var handlersConfig = types.HandlersConfig{ AppURL: "http://localhost:8080", - Domain: ".localhost", - CookieSecure: false, DisableContinue: false, Title: "Tinyauth", GenericName: "Generic", diff --git a/internal/auth/auth.go b/internal/auth/auth.go index 100a248..327f637 100644 --- a/internal/auth/auth.go +++ b/internal/auth/auth.go @@ -178,6 +178,7 @@ func (auth *Auth) CreateSessionCookie(c *gin.Context, data *types.SessionCookie) session.Values["provider"] = data.Provider session.Values["expiry"] = time.Now().Add(time.Duration(sessionExpiry) * time.Second).Unix() session.Values["totpPending"] = data.TotpPending + session.Values["redirectURI"] = data.RedirectURI // Save session err = session.Save(c.Request, c.Writer) @@ -231,15 +232,17 @@ func (auth *Auth) GetSessionCookie(c *gin.Context) (types.SessionCookie, error) cookieProvider := session.Values["provider"] cookieExpiry := session.Values["expiry"] cookieTotpPending := session.Values["totpPending"] + cookieRedirectURI := session.Values["redirectURI"] // Convert interfaces to correct types username, usernameOk := cookieUsername.(string) provider, providerOk := cookieProvider.(string) expiry, expiryOk := cookieExpiry.(int64) totpPending, totpPendingOk := cookieTotpPending.(bool) + redirectURI, redirectURIOk := cookieRedirectURI.(string) // Check if the cookie is invalid - if !usernameOk || !providerOk || !expiryOk || !totpPendingOk { + if !usernameOk || !providerOk || !expiryOk || !totpPendingOk || !redirectURIOk { log.Warn().Msg("Session cookie invalid") return types.SessionCookie{}, nil } @@ -262,6 +265,7 @@ func (auth *Auth) GetSessionCookie(c *gin.Context) (types.SessionCookie, error) Username: username, Provider: provider, TotpPending: totpPending, + RedirectURI: redirectURI, }, nil } diff --git a/internal/handlers/handlers.go b/internal/handlers/handlers.go index d5eb5a7..185b45b 100644 --- a/internal/handlers/handlers.go +++ b/internal/handlers/handlers.go @@ -248,16 +248,16 @@ func (h *Handlers) LoginHandler(c *gin.Context) { } log.Debug().Msg("Got login request") - + // Get client IP for rate limiting clientIP := c.ClientIP() - + // Create an identifier for rate limiting (username or IP if username doesn't exist yet) rateIdentifier := login.Username if rateIdentifier == "" { rateIdentifier = clientIP } - + // Check if the account is locked due to too many failed attempts locked, remainingTime := h.Auth.IsAccountLocked(rateIdentifier) if locked { @@ -299,7 +299,7 @@ func (h *Handlers) LoginHandler(c *gin.Context) { } log.Debug().Msg("Password correct, checking totp") - + // Record successful login attempt (will reset failed attempt counter) h.Auth.RecordLoginAttempt(rateIdentifier, true) @@ -420,9 +420,6 @@ func (h *Handlers) LogoutHandler(c *gin.Context) { log.Debug().Msg("Cleaning up redirect cookie") - // Clean up redirect cookie if it exists - c.SetCookie("tinyauth_redirect_uri", "", -1, "/", h.Config.Domain, h.Config.CookieSecure, true) - // Return logged out c.JSON(200, gin.H{ "status": 200, @@ -529,7 +526,9 @@ func (h *Handlers) OauthUrlHandler(c *gin.Context) { // Set redirect cookie if redirect URI is provided if redirectURI != "" { log.Debug().Str("redirectURI", redirectURI).Msg("Setting redirect cookie") - c.SetCookie("tinyauth_redirect_uri", redirectURI, 3600, "/", h.Config.Domain, h.Config.CookieSecure, true) + h.Auth.CreateSessionCookie(c, &types.SessionCookie{ + RedirectURI: redirectURI, + }) } // Tailscale does not have an auth url so we create a random code (does not need to be secure) to avoid caching and send it @@ -651,28 +650,25 @@ func (h *Handlers) OauthCallbackHandler(c *gin.Context) { log.Debug().Msg("Email whitelisted") - // Create session cookie + // Get redirect URI + cookie, err := h.Auth.GetSessionCookie(c) + + // Create session cookie (also cleans up redirect cookie) h.Auth.CreateSessionCookie(c, &types.SessionCookie{ Username: email, Provider: providerName.Provider, }) - // Get redirect URI - redirectURI, err := c.Cookie("tinyauth_redirect_uri") - // If it is empty it means that no redirect_uri was provided to the login screen so we just log in if err != nil { c.Redirect(http.StatusPermanentRedirect, h.Config.AppURL) } - log.Debug().Str("redirectURI", redirectURI).Msg("Got redirect URI") - - // Clean up redirect cookie since we already have the value - c.SetCookie("tinyauth_redirect_uri", "", -1, "/", h.Config.Domain, h.Config.CookieSecure, true) + log.Debug().Str("redirectURI", cookie.RedirectURI).Msg("Got redirect URI") // Build query queries, err := query.Values(types.LoginQuery{ - RedirectURI: redirectURI, + RedirectURI: cookie.RedirectURI, }) log.Debug().Msg("Got redirect query") diff --git a/internal/types/config.go b/internal/types/config.go index ddb1a5d..8926edd 100644 --- a/internal/types/config.go +++ b/internal/types/config.go @@ -40,8 +40,6 @@ type Config struct { // Server configuration type HandlersConfig struct { AppURL string - Domain string - CookieSecure bool DisableContinue bool GenericName string Title string diff --git a/internal/types/types.go b/internal/types/types.go index 19d877d..652779a 100644 --- a/internal/types/types.go +++ b/internal/types/types.go @@ -27,6 +27,7 @@ type SessionCookie struct { Username string Provider string TotpPending bool + RedirectURI string } // TinyauthLabels is the labels for the tinyauth container