mirror of
https://github.com/steveiliop56/tinyauth.git
synced 2025-10-28 04:35:40 +00:00
refactor: store redirect URI in tinyauth session cookie
This commit is contained in:
@@ -2,7 +2,6 @@ package cmd
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
@@ -94,10 +93,8 @@ var rootCmd = &cobra.Command{
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Create handlers config
|
// Create handlers config
|
||||||
serverConfig := types.HandlersConfig{
|
handlersConfig := types.HandlersConfig{
|
||||||
AppURL: config.AppURL,
|
AppURL: config.AppURL,
|
||||||
Domain: fmt.Sprintf(".%s", domain),
|
|
||||||
CookieSecure: config.CookieSecure,
|
|
||||||
DisableContinue: config.DisableContinue,
|
DisableContinue: config.DisableContinue,
|
||||||
Title: config.Title,
|
Title: config.Title,
|
||||||
GenericName: config.GenericName,
|
GenericName: config.GenericName,
|
||||||
@@ -141,7 +138,7 @@ var rootCmd = &cobra.Command{
|
|||||||
hooks := hooks.NewHooks(auth, providers)
|
hooks := hooks.NewHooks(auth, providers)
|
||||||
|
|
||||||
// Create handlers
|
// Create handlers
|
||||||
handlers := handlers.NewHandlers(serverConfig, auth, hooks, providers, docker)
|
handlers := handlers.NewHandlers(handlersConfig, auth, hooks, providers, docker)
|
||||||
|
|
||||||
// Create API
|
// Create API
|
||||||
api := api.NewAPI(apiConfig, handlers)
|
api := api.NewAPI(apiConfig, handlers)
|
||||||
|
|||||||
@@ -28,8 +28,6 @@ var apiConfig = types.APIConfig{
|
|||||||
// Simple handlers config for tests
|
// Simple handlers config for tests
|
||||||
var handlersConfig = types.HandlersConfig{
|
var handlersConfig = types.HandlersConfig{
|
||||||
AppURL: "http://localhost:8080",
|
AppURL: "http://localhost:8080",
|
||||||
Domain: ".localhost",
|
|
||||||
CookieSecure: false,
|
|
||||||
DisableContinue: false,
|
DisableContinue: false,
|
||||||
Title: "Tinyauth",
|
Title: "Tinyauth",
|
||||||
GenericName: "Generic",
|
GenericName: "Generic",
|
||||||
|
|||||||
@@ -178,6 +178,7 @@ func (auth *Auth) CreateSessionCookie(c *gin.Context, data *types.SessionCookie)
|
|||||||
session.Values["provider"] = data.Provider
|
session.Values["provider"] = data.Provider
|
||||||
session.Values["expiry"] = time.Now().Add(time.Duration(sessionExpiry) * time.Second).Unix()
|
session.Values["expiry"] = time.Now().Add(time.Duration(sessionExpiry) * time.Second).Unix()
|
||||||
session.Values["totpPending"] = data.TotpPending
|
session.Values["totpPending"] = data.TotpPending
|
||||||
|
session.Values["redirectURI"] = data.RedirectURI
|
||||||
|
|
||||||
// Save session
|
// Save session
|
||||||
err = session.Save(c.Request, c.Writer)
|
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"]
|
cookieProvider := session.Values["provider"]
|
||||||
cookieExpiry := session.Values["expiry"]
|
cookieExpiry := session.Values["expiry"]
|
||||||
cookieTotpPending := session.Values["totpPending"]
|
cookieTotpPending := session.Values["totpPending"]
|
||||||
|
cookieRedirectURI := session.Values["redirectURI"]
|
||||||
|
|
||||||
// Convert interfaces to correct types
|
// Convert interfaces to correct types
|
||||||
username, usernameOk := cookieUsername.(string)
|
username, usernameOk := cookieUsername.(string)
|
||||||
provider, providerOk := cookieProvider.(string)
|
provider, providerOk := cookieProvider.(string)
|
||||||
expiry, expiryOk := cookieExpiry.(int64)
|
expiry, expiryOk := cookieExpiry.(int64)
|
||||||
totpPending, totpPendingOk := cookieTotpPending.(bool)
|
totpPending, totpPendingOk := cookieTotpPending.(bool)
|
||||||
|
redirectURI, redirectURIOk := cookieRedirectURI.(string)
|
||||||
|
|
||||||
// Check if the cookie is invalid
|
// Check if the cookie is invalid
|
||||||
if !usernameOk || !providerOk || !expiryOk || !totpPendingOk {
|
if !usernameOk || !providerOk || !expiryOk || !totpPendingOk || !redirectURIOk {
|
||||||
log.Warn().Msg("Session cookie invalid")
|
log.Warn().Msg("Session cookie invalid")
|
||||||
return types.SessionCookie{}, nil
|
return types.SessionCookie{}, nil
|
||||||
}
|
}
|
||||||
@@ -262,6 +265,7 @@ func (auth *Auth) GetSessionCookie(c *gin.Context) (types.SessionCookie, error)
|
|||||||
Username: username,
|
Username: username,
|
||||||
Provider: provider,
|
Provider: provider,
|
||||||
TotpPending: totpPending,
|
TotpPending: totpPending,
|
||||||
|
RedirectURI: redirectURI,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -248,16 +248,16 @@ func (h *Handlers) LoginHandler(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
log.Debug().Msg("Got login request")
|
log.Debug().Msg("Got login request")
|
||||||
|
|
||||||
// Get client IP for rate limiting
|
// Get client IP for rate limiting
|
||||||
clientIP := c.ClientIP()
|
clientIP := c.ClientIP()
|
||||||
|
|
||||||
// Create an identifier for rate limiting (username or IP if username doesn't exist yet)
|
// Create an identifier for rate limiting (username or IP if username doesn't exist yet)
|
||||||
rateIdentifier := login.Username
|
rateIdentifier := login.Username
|
||||||
if rateIdentifier == "" {
|
if rateIdentifier == "" {
|
||||||
rateIdentifier = clientIP
|
rateIdentifier = clientIP
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if the account is locked due to too many failed attempts
|
// Check if the account is locked due to too many failed attempts
|
||||||
locked, remainingTime := h.Auth.IsAccountLocked(rateIdentifier)
|
locked, remainingTime := h.Auth.IsAccountLocked(rateIdentifier)
|
||||||
if locked {
|
if locked {
|
||||||
@@ -299,7 +299,7 @@ func (h *Handlers) LoginHandler(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
log.Debug().Msg("Password correct, checking totp")
|
log.Debug().Msg("Password correct, checking totp")
|
||||||
|
|
||||||
// Record successful login attempt (will reset failed attempt counter)
|
// Record successful login attempt (will reset failed attempt counter)
|
||||||
h.Auth.RecordLoginAttempt(rateIdentifier, true)
|
h.Auth.RecordLoginAttempt(rateIdentifier, true)
|
||||||
|
|
||||||
@@ -420,9 +420,6 @@ func (h *Handlers) LogoutHandler(c *gin.Context) {
|
|||||||
|
|
||||||
log.Debug().Msg("Cleaning up redirect cookie")
|
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
|
// Return logged out
|
||||||
c.JSON(200, gin.H{
|
c.JSON(200, gin.H{
|
||||||
"status": 200,
|
"status": 200,
|
||||||
@@ -529,7 +526,9 @@ func (h *Handlers) OauthUrlHandler(c *gin.Context) {
|
|||||||
// Set redirect cookie if redirect URI is provided
|
// Set redirect cookie if redirect URI is provided
|
||||||
if redirectURI != "" {
|
if redirectURI != "" {
|
||||||
log.Debug().Str("redirectURI", redirectURI).Msg("Setting redirect cookie")
|
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
|
// 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")
|
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{
|
h.Auth.CreateSessionCookie(c, &types.SessionCookie{
|
||||||
Username: email,
|
Username: email,
|
||||||
Provider: providerName.Provider,
|
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 it is empty it means that no redirect_uri was provided to the login screen so we just log in
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.Redirect(http.StatusPermanentRedirect, h.Config.AppURL)
|
c.Redirect(http.StatusPermanentRedirect, h.Config.AppURL)
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Debug().Str("redirectURI", redirectURI).Msg("Got redirect URI")
|
log.Debug().Str("redirectURI", cookie.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)
|
|
||||||
|
|
||||||
// Build query
|
// Build query
|
||||||
queries, err := query.Values(types.LoginQuery{
|
queries, err := query.Values(types.LoginQuery{
|
||||||
RedirectURI: redirectURI,
|
RedirectURI: cookie.RedirectURI,
|
||||||
})
|
})
|
||||||
|
|
||||||
log.Debug().Msg("Got redirect query")
|
log.Debug().Msg("Got redirect query")
|
||||||
|
|||||||
@@ -40,8 +40,6 @@ type Config struct {
|
|||||||
// Server configuration
|
// Server configuration
|
||||||
type HandlersConfig struct {
|
type HandlersConfig struct {
|
||||||
AppURL string
|
AppURL string
|
||||||
Domain string
|
|
||||||
CookieSecure bool
|
|
||||||
DisableContinue bool
|
DisableContinue bool
|
||||||
GenericName string
|
GenericName string
|
||||||
Title string
|
Title string
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ type SessionCookie struct {
|
|||||||
Username string
|
Username string
|
||||||
Provider string
|
Provider string
|
||||||
TotpPending bool
|
TotpPending bool
|
||||||
|
RedirectURI string
|
||||||
}
|
}
|
||||||
|
|
||||||
// TinyauthLabels is the labels for the tinyauth container
|
// TinyauthLabels is the labels for the tinyauth container
|
||||||
|
|||||||
Reference in New Issue
Block a user