2019-05-07 02:20:36 +03:00
package cookies
import (
2019-12-16 21:10:04 +03:00
"fmt"
2019-05-07 02:20:36 +03:00
"net"
"net/http"
"strings"
"time"
2020-09-29 19:44:42 +03:00
"github.com/oauth2-proxy/oauth2-proxy/v7/pkg/apis/options"
"github.com/oauth2-proxy/oauth2-proxy/v7/pkg/logger"
2021-01-03 00:16:01 +03:00
requestutil "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/requests/util"
2019-05-07 02:20:36 +03:00
)
2021-04-21 12:33:27 +03:00
// MakeCookieFromOptions constructs a cookie based on the given *options.CookieOptions,
// value and creation time
func MakeCookieFromOptions ( req * http . Request , name string , value string , opts * options . Cookie , expiration time . Duration , now time . Time ) * http . Cookie {
domain := GetCookieDomain ( req , opts . Domains )
// If nothing matches, create the cookie with the shortest domain
if domain == "" && len ( opts . Domains ) > 0 {
logger . Errorf ( "Warning: request host %q did not match any of the specific cookie domains of %q" ,
requestutil . GetRequestHost ( req ) ,
strings . Join ( opts . Domains , "," ) ,
)
domain = opts . Domains [ len ( opts . Domains ) - 1 ]
2019-05-07 02:20:36 +03:00
}
2021-04-21 12:33:27 +03:00
c := & http . Cookie {
2019-05-07 02:20:36 +03:00
Name : name ,
Value : value ,
2021-04-21 12:33:27 +03:00
Path : opts . Path ,
2019-05-07 02:20:36 +03:00
Domain : domain ,
2021-04-21 12:33:27 +03:00
HttpOnly : opts . HTTPOnly ,
Secure : opts . Secure ,
SameSite : ParseSameSite ( opts . SameSite ) ,
2019-05-07 02:20:36 +03:00
}
2019-05-13 18:01:28 +03:00
2023-08-16 14:23:02 +03:00
if expiration != time . Duration ( 0 ) {
c . Expires = now . Add ( expiration )
}
2021-04-21 12:33:27 +03:00
warnInvalidDomain ( c , req )
2020-04-12 14:00:44 +03:00
2021-04-21 12:33:27 +03:00
return c
2020-04-12 14:00:44 +03:00
}
// 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 {
2021-01-03 00:16:01 +03:00
host := requestutil . GetRequestHost ( req )
2020-04-12 14:00:44 +03:00
for _ , domain := range cookieDomains {
if strings . HasSuffix ( host , domain ) {
return domain
}
}
return ""
}
2019-12-16 21:10:04 +03:00
// 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 "" :
2021-02-17 23:59:46 +03:00
return 0
2019-12-16 21:10:04 +03:00
default :
panic ( fmt . Sprintf ( "Invalid value for SameSite: %s" , v ) )
}
2019-05-13 18:01:28 +03:00
}
2021-04-21 12:33:27 +03:00
// warnInvalidDomain logs a warning if the request host and cookie domain are
// mismatched.
func warnInvalidDomain ( c * http . Cookie , req * http . Request ) {
if c . Domain == "" {
return
}
host := requestutil . GetRequestHost ( req )
if h , _ , err := net . SplitHostPort ( host ) ; err == nil {
host = h
}
if ! strings . HasSuffix ( host , c . Domain ) {
logger . Errorf ( "Warning: request host is %q but using configured cookie domain of %q" , host , c . Domain )
}
}