mirror of
https://github.com/lukaszraczylo/traefikoidc.git
synced 2026-10-13 04:07:37 +00:00
Add redis support for distributed caching (#83)
* Add redis support for distributed caching * Move towards the self-provided Redis connection pool and RESP protocol implementation. Official redis client library won't work with yaegi. * fixup! Move towards the self-provided Redis connection pool and RESP protocol implementation. Official redis client library won't work with yaegi. * fixup! fixup! Move towards the self-provided Redis connection pool and RESP protocol implementation. Official redis client library won't work with yaegi. * fixup! fixup! fixup! Move towards the self-provided Redis connection pool and RESP protocol implementation. Official redis client library won't work with yaegi. * fixup! fixup! fixup! fixup! Move towards the self-provided Redis connection pool and RESP protocol implementation. Official redis client library won't work with yaegi. * fixup! fixup! fixup! fixup! fixup! Move towards the self-provided Redis connection pool and RESP protocol implementation. Official redis client library won't work with yaegi. * ... and another all nighter. * fixup! ... and another all nighter. * fixup! fixup! ... and another all nighter. * fixup! fixup! fixup! ... and another all nighter. * Resolve issue #85 by adding ability to set custom claims in JWT tokens * Remove redundant validation in auth middleware ( issue #89 ) * Add ability to set cookie prefix for session cookies ( #87 ) * fixup! Add ability to set cookie prefix for session cookies ( #87 ) * Add ability to set cookie max age - issue #91 * Potential fix for code scanning alert no. 10: Size computation for allocation may overflow Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com> * fixup! Merge main into 0.8.0-redis: resolve conflicts --------- Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
This commit is contained in:
co-authored by
Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
parent
5fcbd54955
commit
e64fc7f730
+29
-13
@@ -237,6 +237,8 @@ type SessionManager struct {
|
||||
logger *Logger
|
||||
chunkManager *ChunkManager
|
||||
cookieDomain string
|
||||
cookiePrefix string // Prefix for cookie names (default: "_oidc_raczylo_")
|
||||
sessionMaxAge time.Duration // Maximum session age (default: 24 hours)
|
||||
cleanupMutex sync.RWMutex
|
||||
forceHTTPS bool
|
||||
cleanupDone bool
|
||||
@@ -256,26 +258,40 @@ type SessionManager struct {
|
||||
// - encryptionKey: The key for encrypting session cookies (minimum 32 bytes).
|
||||
// - forceHTTPS: Whether to force HTTPS-only cookies regardless of request scheme.
|
||||
// - cookieDomain: The domain for session cookies (empty for auto-detection).
|
||||
// - cookiePrefix: Prefix for session cookie names (empty for default "_oidc_raczylo_").
|
||||
// - sessionMaxAge: Maximum session age duration (0 for default 24 hours).
|
||||
// - logger: Logger instance for debug and error logging.
|
||||
//
|
||||
// Returns:
|
||||
// - The configured SessionManager instance.
|
||||
// - An error if the encryption key does not meet minimum length requirements.
|
||||
func NewSessionManager(encryptionKey string, forceHTTPS bool, cookieDomain string, logger *Logger) (*SessionManager, error) {
|
||||
func NewSessionManager(encryptionKey string, forceHTTPS bool, cookieDomain string, cookiePrefix string, sessionMaxAge time.Duration, logger *Logger) (*SessionManager, error) {
|
||||
if len(encryptionKey) < minEncryptionKeyLength {
|
||||
return nil, fmt.Errorf("encryption key must be at least %d bytes long", minEncryptionKeyLength)
|
||||
}
|
||||
|
||||
// Set default cookie prefix if not provided
|
||||
if cookiePrefix == "" {
|
||||
cookiePrefix = "_oidc_raczylo_"
|
||||
}
|
||||
|
||||
// Set default session max age if not provided (24 hours for backward compatibility)
|
||||
if sessionMaxAge == 0 {
|
||||
sessionMaxAge = absoluteSessionTimeout
|
||||
}
|
||||
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
|
||||
sm := &SessionManager{
|
||||
store: sessions.NewCookieStore([]byte(encryptionKey)),
|
||||
forceHTTPS: forceHTTPS,
|
||||
cookieDomain: cookieDomain,
|
||||
logger: logger,
|
||||
chunkManager: NewChunkManager(logger),
|
||||
ctx: ctx,
|
||||
cancel: cancel,
|
||||
store: sessions.NewCookieStore([]byte(encryptionKey)),
|
||||
forceHTTPS: forceHTTPS,
|
||||
cookieDomain: cookieDomain,
|
||||
cookiePrefix: cookiePrefix,
|
||||
sessionMaxAge: sessionMaxAge,
|
||||
logger: logger,
|
||||
chunkManager: NewChunkManager(logger),
|
||||
ctx: ctx,
|
||||
cancel: cancel,
|
||||
}
|
||||
|
||||
// Initialize global memory monitoring (singleton)
|
||||
@@ -607,7 +623,7 @@ func (sm *SessionManager) GetSessionMetrics() map[string]interface{} {
|
||||
metrics := make(map[string]interface{})
|
||||
metrics["session_manager_type"] = "CookieStore"
|
||||
metrics["force_https"] = sm.forceHTTPS
|
||||
metrics["absolute_timeout_hours"] = absoluteSessionTimeout.Hours()
|
||||
metrics["absolute_timeout_hours"] = sm.sessionMaxAge.Hours()
|
||||
metrics["max_cookie_size"] = maxCookieSize
|
||||
metrics["max_browser_cookie_size"] = maxBrowserCookieSize
|
||||
|
||||
@@ -641,7 +657,7 @@ func (sm *SessionManager) EnhanceSessionSecurity(options *sessions.Options, r *h
|
||||
userAgent := r.Header.Get("User-Agent")
|
||||
if userAgent == "" {
|
||||
sm.logger.Debugf("Request from %s missing User-Agent header", r.RemoteAddr)
|
||||
options.MaxAge = int((absoluteSessionTimeout / 2).Seconds())
|
||||
options.MaxAge = int((sm.sessionMaxAge / 2).Seconds())
|
||||
}
|
||||
|
||||
if r.Header.Get("X-Forwarded-Proto") == "https" || r.TLS != nil || sm.forceHTTPS {
|
||||
@@ -691,7 +707,7 @@ func (sm *SessionManager) getSessionOptions(isSecure bool) *sessions.Options {
|
||||
HttpOnly: true,
|
||||
Secure: isSecure || sm.forceHTTPS,
|
||||
SameSite: http.SameSiteLaxMode,
|
||||
MaxAge: int(absoluteSessionTimeout.Seconds()),
|
||||
MaxAge: int(sm.sessionMaxAge.Seconds()),
|
||||
Path: "/",
|
||||
Domain: sm.cookieDomain,
|
||||
}
|
||||
@@ -821,7 +837,7 @@ func (sm *SessionManager) GetSession(r *http.Request) (*SessionData, error) {
|
||||
}
|
||||
|
||||
if createdAt, ok := sessionData.mainSession.Values["created_at"].(int64); ok {
|
||||
if time.Since(time.Unix(createdAt, 0)) > absoluteSessionTimeout {
|
||||
if time.Since(time.Unix(createdAt, 0)) > sm.sessionMaxAge {
|
||||
_ = sessionData.Clear(r, nil) // Safe to ignore: session is being invalidated
|
||||
return handleError(fmt.Errorf("session timeout"), "session expired")
|
||||
}
|
||||
@@ -1130,7 +1146,7 @@ func (sd *SessionData) getAuthenticatedUnsafe() bool {
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
return time.Since(time.Unix(createdAt, 0)) <= absoluteSessionTimeout
|
||||
return time.Since(time.Unix(createdAt, 0)) <= sd.manager.sessionMaxAge
|
||||
}
|
||||
|
||||
// SetAuthenticated sets the authentication status and manages session security.
|
||||
|
||||
Reference in New Issue
Block a user