Skip to content

Commit b0ef640

Browse files
Merge pull request #182 from k-wall/samesite
Add configuration for cookie 'SameSite' value.
2 parents b1d20e6 + d63fac9 commit b0ef640

File tree

5 files changed

+49
-1
lines changed

5 files changed

+49
-1
lines changed

README.md

+2
Original file line numberDiff line numberDiff line change
@@ -231,6 +231,7 @@ Usage of oauth-proxy:
231231
-cookie-httponly: set HttpOnly cookie flag (default true)
232232
-cookie-name string: the name of the cookie that the oauth_proxy creates (default "_oauth2_proxy")
233233
-cookie-refresh duration: refresh the cookie after this duration; 0 to disable
234+
-cookie-samesite string | set SameSite cookie attribute (ie: `"lax"`, `"strict"`, `"none"`, or `""`)
234235
-cookie-secret string: the seed string for secure cookies (optionally base64 encoded)
235236
-cookie-secret-file string: same as "-cookie-secret" but read it from a file
236237
-cookie-secure: set secure (HTTPS) cookie flag (default true)
@@ -285,6 +286,7 @@ The following environment variables can be used in place of the corresponding co
285286
- `OAUTH2_PROXY_CLIENT_ID`
286287
- `OAUTH2_PROXY_CLIENT_SECRET`
287288
- `OAUTH2_PROXY_COOKIE_NAME`
289+
- `OAUTH2_PROXY_COOKIE_SAMESITE`
288290
- `OAUTH2_PROXY_COOKIE_SECRET`
289291
- `OAUTH2_PROXY_COOKIE_DOMAIN`
290292
- `OAUTH2_PROXY_COOKIE_EXPIRE`

main.go

+1
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ func main() {
8484
flagSet.Duration("cookie-refresh", time.Duration(0), "refresh the cookie after this duration; 0 to disable")
8585
flagSet.Bool("cookie-secure", true, "set secure (HTTPS) cookie flag")
8686
flagSet.Bool("cookie-httponly", true, "set HttpOnly cookie flag")
87+
flagSet.String("cookie-samesite", "", "set SameSite cookie attribute (ie: \"lax\", \"strict\", \"none\", or \"\"). ")
8788

8889
flagSet.Bool("request-logging", false, "Log requests to stdout")
8990

oauthproxy.go

+20-1
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ type OAuthProxy struct {
5151
CookieHttpOnly bool
5252
CookieExpire time.Duration
5353
CookieRefresh time.Duration
54+
CookieSameSite string
5455
Validator func(string) bool
5556

5657
RobotsPath string
@@ -236,7 +237,7 @@ func NewOAuthProxy(opts *Options, validator func(string) bool) *OAuthProxy {
236237
refresh = fmt.Sprintf("after %s", opts.CookieRefresh)
237238
}
238239

239-
log.Printf("Cookie settings: name:%s secure(https):%v httponly:%v expiry:%s domain:%s refresh:%s", opts.CookieName, opts.CookieSecure, opts.CookieHttpOnly, opts.CookieExpire, domain, refresh)
240+
log.Printf("Cookie settings: name:%s secure(https):%v httponly:%v expiry:%s domain:%s samesite:%s refresh:%s", opts.CookieName, opts.CookieSecure, opts.CookieHttpOnly, opts.CookieExpire, domain, opts.CookieSameSite, refresh)
240241

241242
var cipher *cookie.Cipher
242243
if opts.PassAccessToken || (opts.CookieRefresh != time.Duration(0)) {
@@ -260,6 +261,7 @@ func NewOAuthProxy(opts *Options, validator func(string) bool) *OAuthProxy {
260261
CookieHttpOnly: opts.CookieHttpOnly,
261262
CookieExpire: opts.CookieExpire,
262263
CookieRefresh: opts.CookieRefresh,
264+
CookieSameSite: opts.CookieSameSite,
263265
Validator: validator,
264266

265267
RobotsPath: "/robots.txt",
@@ -379,6 +381,7 @@ func (p *OAuthProxy) makeCookie(req *http.Request, name string, value string, ex
379381
HttpOnly: p.CookieHttpOnly,
380382
Secure: p.CookieSecure,
381383
Expires: now.Add(expiration),
384+
SameSite: parseSameSite(p.CookieSameSite),
382385
}
383386
}
384387

@@ -858,3 +861,19 @@ func (p *OAuthProxy) CheckRequestAuth(req *http.Request) (*providers.SessionStat
858861
// handle advanced validation
859862
return p.provider.ValidateRequest(req)
860863
}
864+
865+
// Parse a valid http.SameSite value from a user supplied string for use of making cookies.
866+
func parseSameSite(v string) http.SameSite {
867+
switch v {
868+
case "lax":
869+
return http.SameSiteLaxMode
870+
case "strict":
871+
return http.SameSiteStrictMode
872+
case "none":
873+
return http.SameSiteNoneMode
874+
case "":
875+
return http.SameSiteDefaultMode
876+
default:
877+
panic(fmt.Sprintf("Invalid value for SameSite: %s", v))
878+
}
879+
}

options.go

+7
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ type Options struct {
5858
CookieRefresh time.Duration `flag:"cookie-refresh" cfg:"cookie_refresh" env:"OAUTH2_PROXY_COOKIE_REFRESH"`
5959
CookieSecure bool `flag:"cookie-secure" cfg:"cookie_secure"`
6060
CookieHttpOnly bool `flag:"cookie-httponly" cfg:"cookie_httponly"`
61+
CookieSameSite string `flag:"cookie-samesite" cfg:"cookie_samesite" env:"OAUTH2_PROXY_COOKIE_SAMESITE"`
6162

6263
Upstreams []string `flag:"upstream" cfg:"upstreams"`
6364
BypassAuthExceptRegex []string `flag:"bypass-auth-except-for" cfg:"bypass_auth_except_for"`
@@ -299,6 +300,12 @@ func (o *Options) Validate(p providers.Provider) error {
299300
msgs = append(msgs, "tls-client-ca requires tls-key-file or tls-cert-file to be set to listen on tls")
300301
}
301302

303+
switch o.CookieSameSite {
304+
case "", "none", "lax", "strict":
305+
default:
306+
msgs = append(msgs, fmt.Sprintf("cookie_samesite (%q) must be one of ['', 'lax', 'strict', 'none']", o.CookieSameSite))
307+
}
308+
302309
msgs = parseSignatureKey(o, msgs)
303310
msgs = validateCookieName(o, msgs)
304311

options_test.go

+19
Original file line numberDiff line numberDiff line change
@@ -210,3 +210,22 @@ func TestValidateCookieBadName(t *testing.T) {
210210
assert.Equal(t, err.Error(), "Invalid configuration:\n"+
211211
fmt.Sprintf(" invalid cookie name: %q", o.CookieName))
212212
}
213+
214+
func TestValidateCookieSameSiteUnknown(t *testing.T) {
215+
o := testOptions()
216+
o.CookieSameSite = "foo"
217+
err := o.Validate(&testProvider{})
218+
assert.Equal(t, err.Error(), "Invalid configuration:\n"+
219+
fmt.Sprintf(" cookie_samesite (%q) must be one of ['', 'lax', 'strict', 'none']", o.CookieSameSite))
220+
}
221+
222+
func TestValidateCookieSameSite(t *testing.T) {
223+
testCases := []string{"", "lax", "strict", "none"}
224+
for _, tc := range testCases {
225+
t.Run(tc, func(t *testing.T) {
226+
o := testOptions()
227+
o.CookieSameSite = tc
228+
assert.Equal(t, nil, o.Validate(&testProvider{}))
229+
})
230+
}
231+
}

0 commit comments

Comments
 (0)