oauth2-proxy/pkg/apis/options/cookie.go

108 lines
3.4 KiB
Go

package options
import (
"fmt"
"time"
"github.com/oauth2-proxy/oauth2-proxy/v7/pkg/util/ptr"
"go.yaml.in/yaml/v3"
)
const (
// DefaultCookieInsecure is the default value for Cookie.Insecure
DefaultCookieInsecure bool = false
// DefaultCookieNotHttpOnly is the default value for Cookie.NotHttpOnly
DefaultCookieNotHttpOnly bool = false
// DefaultCSRFPerRequest is the default value for Cookie.CSRFPerRequest
DefaultCSRFPerRequest bool = false
)
type SameSiteMode string
const (
SameSiteLax SameSiteMode = "lax"
SameSiteStrict SameSiteMode = "strict"
SameSiteNone SameSiteMode = "none"
SameSiteDefault SameSiteMode = ""
)
// Cookie contains configuration options relating session and CSRF cookies
type Cookie struct {
// Name is the name of the cookie
Name string `yaml:"name,omitempty"`
// Secret is the secret source used to encrypt/sign the cookie value
Secret SecretSource `yaml:"secret,omitempty"`
// Domains is a list of domains for which the cookie is valid
Domains []string `yaml:"domains,omitempty"`
// Path is the path for which the cookie is valid
Path string `yaml:"path,omitempty"`
// Expire is the duration before the cookie expires
Expire time.Duration `yaml:"expire,omitempty"`
// Insecure indicates whether the cookie allows to be sent over HTTP
// Default is false, which requires HTTPS
Insecure *bool `yaml:"insecure,omitempty"`
// NotHttpOnly is the inverse of HTTPOnly; indicates whether the cookie is accessible to JavaScript
// Default is false, which helps mitigate certain XSS attacks
NotHttpOnly *bool `yaml:"notHttpOnly,omitempty"`
// SameSite sets the SameSite attribute on the cookie
SameSite SameSiteMode `yaml:"sameSite,omitempty"`
// CSRFPerRequest indicates whether a unique CSRF token is generated for each request
// Enables parallel requests from clients (e.g., multiple tabs)
// Default is false, which uses a single CSRF token per session
CSRFPerRequest *bool `yaml:"csrfPerRequest,omitempty"`
// CSRFPerRequestLimit sets a limit on the number of valid CSRF tokens when CSRFPerRequest is enabled
// Used to prevent unbounded memory growth from storing too many tokens
CSRFPerRequestLimit int `yaml:"csrfPerRequestLimit,omitempty"`
// CSRFExpire sets the duration before a CSRF token expires
CSRFExpire time.Duration `yaml:"csrfExpire,omitempty"`
}
func (m *SameSiteMode) UnmarshalYAML(value *yaml.Node) error {
var s string
if err := value.Decode(&s); err != nil {
return err
}
switch SameSiteMode(s) {
case SameSiteLax, SameSiteStrict, SameSiteNone, SameSiteDefault:
*m = SameSiteMode(s)
return nil
default:
return fmt.Errorf("invalid same site mode: %s", s)
}
}
// GetSecret returns the cookie secret as a string from the SecretSource
func (c *Cookie) GetSecret() (string, error) {
secret, err := c.Secret.GetSecretValue()
if err != nil {
return "", fmt.Errorf("error getting cookie secret: %w", err)
}
return string(secret), nil
}
// EnsureDefaults sets any default values for the Cookie configuration
func (c *Cookie) EnsureDefaults() {
if c.Name == "" {
c.Name = "_oauth2_proxy"
}
if c.Path == "" {
c.Path = "/"
}
if c.Expire == 0 {
c.Expire = time.Duration(168) * time.Hour
}
if c.Insecure == nil {
c.Insecure = ptr.To(DefaultCookieInsecure)
}
if c.NotHttpOnly == nil {
c.NotHttpOnly = ptr.To(DefaultCookieNotHttpOnly)
}
if c.CSRFPerRequest == nil {
c.CSRFPerRequest = ptr.To(DefaultCSRFPerRequest)
}
if c.CSRFExpire == 0 {
c.CSRFExpire = time.Duration(15) * time.Minute
}
}