mirror of
https://github.com/lukaszraczylo/traefikoidc.git
synced 2026-10-16 04:29:15 +00:00
feat: add cookiePath config to scope session cookies to subpath (#143)
Fixes #122. Co-authored-by: Hermes Agent <[email protected]> Co-authored-by: copilot-swe-agent[bot] <[email protected]>
This commit is contained in:
@@ -121,6 +121,7 @@ Full reference in [docs/CONFIGURATION.md](docs/CONFIGURATION.md).
|
|||||||
| `enablePKCE` | `false` | PKCE on the auth code flow. |
|
| `enablePKCE` | `false` | PKCE on the auth code flow. |
|
||||||
| `cookieDomain` | auto | Set explicitly for multi-subdomain setups (`.example.com`). |
|
| `cookieDomain` | auto | Set explicitly for multi-subdomain setups (`.example.com`). |
|
||||||
| `cookiePrefix` | `_oidc_raczylo_` | Unique prefix per middleware instance to isolate sessions. |
|
| `cookiePrefix` | `_oidc_raczylo_` | Unique prefix per middleware instance to isolate sessions. |
|
||||||
|
| `cookiePath` | `/` | Restrict cookies to a path prefix. Set to the middleware's path (e.g. `/app`) to prevent the browser from sending OIDC cookies to unprotected paths, avoiding 431 "Request Header Or Cookie Too Large" errors on mixed-use domains. |
|
||||||
| `sessionMaxAge` | `86400` | Session lifetime in seconds. |
|
| `sessionMaxAge` | `86400` | Session lifetime in seconds. |
|
||||||
| `refreshGracePeriodSeconds` | `60` | Proactively refresh tokens this many seconds before expiry. |
|
| `refreshGracePeriodSeconds` | `60` | Proactively refresh tokens this many seconds before expiry. |
|
||||||
| `maxRefreshTokenAgeSeconds` | `21600` | Heuristic max stored refresh-token lifetime (6h). Past this, the plugin treats the RT as expired without contacting the IdP — returns 401 to AJAX, full re-auth on navigations. Set `0` to disable. Tune to match your IdP's RT TTL. |
|
| `maxRefreshTokenAgeSeconds` | `21600` | Heuristic max stored refresh-token lifetime (6h). Past this, the plugin treats the RT as expired without contacting the IdP — returns 401 to AJAX, full re-auth on navigations. Set `0` to disable. Tune to match your IdP's RT TTL. |
|
||||||
|
|||||||
@@ -419,6 +419,10 @@ func NewWithContext(ctx context.Context, config *Config, next http.Handler, name
|
|||||||
return nil, fmt.Errorf("failed to create session manager: %w", err)
|
return nil, fmt.Errorf("failed to create session manager: %w", err)
|
||||||
}
|
}
|
||||||
t.sessionManager = sessionManager
|
t.sessionManager = sessionManager
|
||||||
|
if config.CookiePath != "" {
|
||||||
|
t.sessionManager.cookiePath = config.CookiePath
|
||||||
|
t.logger.Debugf("Using configured cookie path: %s", config.CookiePath)
|
||||||
|
}
|
||||||
t.errorRecoveryManager = NewErrorRecoveryManager(t.logger)
|
t.errorRecoveryManager = NewErrorRecoveryManager(t.logger)
|
||||||
|
|
||||||
// Initialize token resilience manager with default configuration
|
// Initialize token resilience manager with default configuration
|
||||||
|
|||||||
+7
-1
@@ -423,6 +423,7 @@ type SessionManager struct {
|
|||||||
cancel context.CancelFunc
|
cancel context.CancelFunc
|
||||||
cookieDomain string
|
cookieDomain string
|
||||||
cookiePrefix string
|
cookiePrefix string
|
||||||
|
cookiePath string
|
||||||
sessionMaxAge time.Duration
|
sessionMaxAge time.Duration
|
||||||
activeSessions int64
|
activeSessions int64
|
||||||
poolHits int64
|
poolHits int64
|
||||||
@@ -905,7 +906,12 @@ func (sm *SessionManager) EnhanceSessionSecurity(options *sessions.Options, r *h
|
|||||||
}
|
}
|
||||||
|
|
||||||
options.HttpOnly = true
|
options.HttpOnly = true
|
||||||
options.Path = "/" // Ensure cookies are available on all paths for OAuth flow
|
// Use configured cookie path (default "/" for backward compatibility)
|
||||||
|
cookiePath := sm.cookiePath
|
||||||
|
if cookiePath == "" {
|
||||||
|
cookiePath = "/"
|
||||||
|
}
|
||||||
|
options.Path = cookiePath
|
||||||
|
|
||||||
if sm.cookieDomain != "" {
|
if sm.cookieDomain != "" {
|
||||||
options.Domain = sm.cookieDomain
|
options.Domain = sm.cookieDomain
|
||||||
|
|||||||
+24
-17
@@ -75,23 +75,30 @@ type Config struct {
|
|||||||
// IdPs do not expose RT TTL on the wire, so this is intentionally a
|
// IdPs do not expose RT TTL on the wire, so this is intentionally a
|
||||||
// conservative heuristic; tune to match your provider configuration.
|
// conservative heuristic; tune to match your provider configuration.
|
||||||
// Default 21600 (6h). Set to 0 to disable the check.
|
// Default 21600 (6h). Set to 0 to disable the check.
|
||||||
MaxRefreshTokenAgeSeconds int `json:"maxRefreshTokenAgeSeconds"`
|
MaxRefreshTokenAgeSeconds int `json:"maxRefreshTokenAgeSeconds"`
|
||||||
SessionMaxAge int `json:"sessionMaxAge"`
|
SessionMaxAge int `json:"sessionMaxAge"`
|
||||||
RateLimit int `json:"rateLimit"`
|
RateLimit int `json:"rateLimit"`
|
||||||
OverrideScopes bool `json:"overrideScopes"`
|
OverrideScopes bool `json:"overrideScopes"`
|
||||||
DisableReplayDetection bool `json:"disableReplayDetection,omitempty"`
|
DisableReplayDetection bool `json:"disableReplayDetection,omitempty"`
|
||||||
RequireTokenIntrospection bool `json:"requireTokenIntrospection,omitempty"`
|
RequireTokenIntrospection bool `json:"requireTokenIntrospection,omitempty"`
|
||||||
AllowOpaqueTokens bool `json:"allowOpaqueTokens,omitempty"`
|
AllowOpaqueTokens bool `json:"allowOpaqueTokens,omitempty"`
|
||||||
StrictAudienceValidation bool `json:"strictAudienceValidation,omitempty"`
|
StrictAudienceValidation bool `json:"strictAudienceValidation,omitempty"`
|
||||||
EnablePKCE bool `json:"enablePKCE"`
|
EnablePKCE bool `json:"enablePKCE"`
|
||||||
ForceHTTPS bool `json:"forceHTTPS"`
|
ForceHTTPS bool `json:"forceHTTPS"`
|
||||||
AllowPrivateIPAddresses bool `json:"allowPrivateIPAddresses,omitempty"`
|
AllowPrivateIPAddresses bool `json:"allowPrivateIPAddresses,omitempty"`
|
||||||
MinimalHeaders bool `json:"minimalHeaders,omitempty"`
|
MinimalHeaders bool `json:"minimalHeaders,omitempty"`
|
||||||
StripAuthCookies bool `json:"stripAuthCookies,omitempty"`
|
StripAuthCookies bool `json:"stripAuthCookies,omitempty"`
|
||||||
EnableBackchannelLogout bool `json:"enableBackchannelLogout,omitempty"`
|
// CookiePath restricts session cookies to a specific path prefix instead of "/".
|
||||||
EnableFrontchannelLogout bool `json:"enableFrontchannelLogout,omitempty"`
|
// When traefikoidc protects some but not all paths on a domain, set this to the
|
||||||
BackchannelLogoutURL string `json:"backchannelLogoutURL,omitempty"`
|
// middleware's path prefix (e.g. "/app-protegido") so the browser does not send
|
||||||
FrontchannelLogoutURL string `json:"frontchannelLogoutURL,omitempty"`
|
// the OIDC session cookies to unprotected paths — preventing "Request Header
|
||||||
|
// Or Cookie Too Large" (431) errors on those paths.
|
||||||
|
// Default "/" (all paths, current behaviour).
|
||||||
|
CookiePath string `json:"cookiePath,omitempty"`
|
||||||
|
EnableBackchannelLogout bool `json:"enableBackchannelLogout,omitempty"`
|
||||||
|
EnableFrontchannelLogout bool `json:"enableFrontchannelLogout,omitempty"`
|
||||||
|
BackchannelLogoutURL string `json:"backchannelLogoutURL,omitempty"`
|
||||||
|
FrontchannelLogoutURL string `json:"frontchannelLogoutURL,omitempty"`
|
||||||
// CACertPath is an optional filesystem path to a PEM-encoded CA bundle used
|
// CACertPath is an optional filesystem path to a PEM-encoded CA bundle used
|
||||||
// to verify the OIDC provider's TLS certificate. Use this when the provider
|
// to verify the OIDC provider's TLS certificate. Use this when the provider
|
||||||
// is signed by an internal/private CA that is not in the system trust store.
|
// is signed by an internal/private CA that is not in the system trust store.
|
||||||
|
|||||||
Reference in New Issue
Block a user