92 lines
		
	
	
		
			2.9 KiB
		
	
	
	
		
			Go
		
	
	
	
			
		
		
	
	
			92 lines
		
	
	
		
			2.9 KiB
		
	
	
	
		
			Go
		
	
	
	
| package cookies
 | |
| 
 | |
| import (
 | |
| 	"fmt"
 | |
| 	"net"
 | |
| 	"net/http"
 | |
| 	"strings"
 | |
| 	"time"
 | |
| 
 | |
| 	"github.com/oauth2-proxy/oauth2-proxy/pkg/apis/options"
 | |
| 	"github.com/oauth2-proxy/oauth2-proxy/pkg/logger"
 | |
| )
 | |
| 
 | |
| // MakeCookie constructs a cookie from the given parameters,
 | |
| // discovering the domain from the request if not specified.
 | |
| func MakeCookie(req *http.Request, name string, value string, path string, domain string, httpOnly bool, secure bool, expiration time.Duration, now time.Time, sameSite http.SameSite) *http.Cookie {
 | |
| 	if domain != "" {
 | |
| 		host := req.Host
 | |
| 		if h, _, err := net.SplitHostPort(host); err == nil {
 | |
| 			host = h
 | |
| 		}
 | |
| 		if !strings.HasSuffix(host, domain) {
 | |
| 			logger.Printf("Warning: request host is %q but using configured cookie domain of %q", host, domain)
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	return &http.Cookie{
 | |
| 		Name:     name,
 | |
| 		Value:    value,
 | |
| 		Path:     path,
 | |
| 		Domain:   domain,
 | |
| 		HttpOnly: httpOnly,
 | |
| 		Secure:   secure,
 | |
| 		Expires:  now.Add(expiration),
 | |
| 		SameSite: sameSite,
 | |
| 	}
 | |
| }
 | |
| 
 | |
| // MakeCookieFromOptions constructs a cookie based on the given *options.CookieOptions,
 | |
| // value and creation time
 | |
| func MakeCookieFromOptions(req *http.Request, name string, value string, cookieOpts *options.CookieOptions, expiration time.Duration, now time.Time) *http.Cookie {
 | |
| 	domain := GetCookieDomain(req, cookieOpts.Domains)
 | |
| 
 | |
| 	if domain != "" {
 | |
| 		return MakeCookie(req, name, value, cookieOpts.Path, domain, cookieOpts.HTTPOnly, cookieOpts.Secure, expiration, now, ParseSameSite(cookieOpts.SameSite))
 | |
| 	}
 | |
| 	// If nothing matches, create the cookie with the shortest domain
 | |
| 	logger.Printf("Warning: request host %q did not match any of the specific cookie domains of %q", GetRequestHost(req), strings.Join(cookieOpts.Domains, ","))
 | |
| 	defaultDomain := ""
 | |
| 	if len(cookieOpts.Domains) > 0 {
 | |
| 		defaultDomain = cookieOpts.Domains[len(cookieOpts.Domains)-1]
 | |
| 	}
 | |
| 	return MakeCookie(req, name, value, cookieOpts.Path, defaultDomain, cookieOpts.HTTPOnly, cookieOpts.Secure, expiration, now, ParseSameSite(cookieOpts.SameSite))
 | |
| }
 | |
| 
 | |
| // GetCookieDomain returns the correct cookie domain given a list of domains
 | |
| // by checking the X-Fowarded-Host and host header of an an http request
 | |
| func GetCookieDomain(req *http.Request, cookieDomains []string) string {
 | |
| 	host := GetRequestHost(req)
 | |
| 	for _, domain := range cookieDomains {
 | |
| 		if strings.HasSuffix(host, domain) {
 | |
| 			return domain
 | |
| 		}
 | |
| 	}
 | |
| 	return ""
 | |
| }
 | |
| 
 | |
| // GetRequestHost return the request host header or X-Forwarded-Host if present
 | |
| func GetRequestHost(req *http.Request) string {
 | |
| 	host := req.Header.Get("X-Forwarded-Host")
 | |
| 	if host == "" {
 | |
| 		host = req.Host
 | |
| 	}
 | |
| 	return host
 | |
| }
 | |
| 
 | |
| // Parse a valid http.SameSite value from a user supplied string for use of making cookies.
 | |
| func ParseSameSite(v string) http.SameSite {
 | |
| 	switch v {
 | |
| 	case "lax":
 | |
| 		return http.SameSiteLaxMode
 | |
| 	case "strict":
 | |
| 		return http.SameSiteStrictMode
 | |
| 	case "none":
 | |
| 		return http.SameSiteNoneMode
 | |
| 	case "":
 | |
| 		return http.SameSiteDefaultMode
 | |
| 	default:
 | |
| 		panic(fmt.Sprintf("Invalid value for SameSite: %s", v))
 | |
| 	}
 | |
| }
 |