Skip to content

Commit

Permalink
Merge pull request oauth2-proxy#414 from ti-mo/cookie-secret-cipher-x…
Browse files Browse the repository at this point in the history
…authrequest

Always encrypt sessions regardless of configuration
  • Loading branch information
JoelSpeed authored May 24, 2020
2 parents 0c9795a + 276d1c6 commit 03a0e1a
Show file tree
Hide file tree
Showing 4 changed files with 49 additions and 40 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,11 @@
- Multiple cookie domains may now be configured. The longest domain that matches will be used.
- The config options `cookie_domain` is now `cookie_domains`
- The environment variable `OAUTH2_PROXY_COOKIE_DOMAIN` is now `OAUTH2_PROXY_COOKIE_DOMAINS`
- [#414](https://github.com/oauth2-proxy/oauth2-proxy/pull/414) Always encrypt sessions regardless of config
- Previously, sessions were encrypted only when certain options were configured.
This lead to confusion and misconfiguration as it was not obvious when a session should be encrypted.
- Cookie Secrets must now be 16, 24 or 32 bytes.
- If you need to change your secret, this will force users to reauthenticate.

## Changes since v5.1.1

Expand Down Expand Up @@ -86,6 +91,7 @@
- [#488](https://github.com/oauth2-proxy/oauth2-proxy/pull/488) Set-Basic-Auth should default to false (@JoelSpeed)
- [#494](https://github.com/oauth2-proxy/oauth2-proxy/pull/494) Upstream websockets TLS certificate validation now depends on ssl-upstream-insecure-skip-verify (@yaroslavros)
- [#497](https://github.com/oauth2-proxy/oauth2-proxy/pull/497) Restrict access using Github collaborators (@jsclayton)
- [#414](https://github.com/oauth2-proxy/oauth2-proxy/pull/414) Always encrypt sessions regardless of config (@ti-mo)

# v5.1.1

Expand Down
19 changes: 13 additions & 6 deletions oauthproxy_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,13 @@ import (
"golang.org/x/net/websocket"
)

const (
// The rawCookieSecret is 32 bytes and the base64CookieSecret is the base64
// encoded version of this.
rawCookieSecret = "secretthirtytwobytes+abcdefghijk"
base64CookieSecret = "c2VjcmV0dGhpcnR5dHdvYnl0ZXMrYWJjZGVmZ2hpamsK"
)

func init() {
logger.SetFlags(logger.Lshortfile)

Expand Down Expand Up @@ -166,7 +173,7 @@ func TestRobotsTxt(t *testing.T) {
opts := options.NewOptions()
opts.ClientID = "asdlkjx"
opts.ClientSecret = "alkgks"
opts.Cookie.Secret = "asdkugkj"
opts.Cookie.Secret = rawCookieSecret
validation.Validate(opts)

proxy := NewOAuthProxy(opts, func(string) bool { return true })
Expand All @@ -181,7 +188,7 @@ func TestIsValidRedirect(t *testing.T) {
opts := options.NewOptions()
opts.ClientID = "skdlfj"
opts.ClientSecret = "fgkdsgj"
opts.Cookie.Secret = "ljgiogbj"
opts.Cookie.Secret = base64CookieSecret
// Should match domains that are exactly foo.bar and any subdomain of bar.foo
opts.WhitelistDomains = []string{
"foo.bar",
Expand Down Expand Up @@ -794,7 +801,7 @@ func NewSignInPageTest(skipProvider bool) *SignInPageTest {
var sipTest SignInPageTest

sipTest.opts = options.NewOptions()
sipTest.opts.Cookie.Secret = "adklsj2"
sipTest.opts.Cookie.Secret = rawCookieSecret
sipTest.opts.ClientID = "lkdgj"
sipTest.opts.ClientSecret = "sgiufgoi"
sipTest.opts.SkipProviderButton = skipProvider
Expand Down Expand Up @@ -1208,7 +1215,7 @@ func TestAuthSkippedForPreflightRequests(t *testing.T) {
opts.Upstreams = append(opts.Upstreams, upstream.URL)
opts.ClientID = "aljsal"
opts.ClientSecret = "jglkfsdgj"
opts.Cookie.Secret = "dkfjgdls"
opts.Cookie.Secret = base64CookieSecret
opts.SkipAuthPreflight = true
validation.Validate(opts)

Expand Down Expand Up @@ -1255,7 +1262,7 @@ type SignatureTest struct {

func NewSignatureTest() *SignatureTest {
opts := options.NewOptions()
opts.Cookie.Secret = "cookie secret"
opts.Cookie.Secret = rawCookieSecret
opts.ClientID = "client ID"
opts.ClientSecret = "client secret"
opts.EmailDomains = []string{"acm.org"}
Expand Down Expand Up @@ -1402,7 +1409,7 @@ type ajaxRequestTest struct {
func newAjaxRequestTest() *ajaxRequestTest {
test := &ajaxRequestTest{}
test.opts = options.NewOptions()
test.opts.Cookie.Secret = "sdflsw"
test.opts.Cookie.Secret = base64CookieSecret
test.opts.ClientID = "gkljfdl"
test.opts.ClientSecret = "sdflkjs"
validation.Validate(test.opts)
Expand Down
62 changes: 29 additions & 33 deletions pkg/validation/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ import (
"regexp"
"sort"
"strings"
"time"

"github.com/coreos/go-oidc"
"github.com/dgrijalva/jwt-go"
Expand All @@ -39,9 +38,38 @@ func Validate(o *options.Options) error {
}

msgs := make([]string, 0)

var cipher *encryption.Cipher
if o.Cookie.Secret == "" {
msgs = append(msgs, "missing setting: cookie-secret")
} else {
validCookieSecretSize := false
for _, i := range []int{16, 24, 32} {
if len(encryption.SecretBytes(o.Cookie.Secret)) == i {
validCookieSecretSize = true
}
}
var decoded bool
if string(encryption.SecretBytes(o.Cookie.Secret)) != o.Cookie.Secret {
decoded = true
}
if !validCookieSecretSize {
var suffix string
if decoded {
suffix = " note: cookie secret was base64 decoded"
}
msgs = append(msgs,
fmt.Sprintf("Cookie secret must be 16, 24, or 32 bytes to create an AES cipher. Got %d bytes.%s",
len(encryption.SecretBytes(o.Cookie.Secret)), suffix))
} else {
var err error
cipher, err = encryption.NewCipher(encryption.SecretBytes(o.Cookie.Secret))
if err != nil {
msgs = append(msgs, fmt.Sprintf("cookie-secret error: %v", err))
}
}
}

if o.ClientID == "" {
msgs = append(msgs, "missing setting: client-id")
}
Expand Down Expand Up @@ -195,38 +223,6 @@ func Validate(o *options.Options) error {
}
msgs = parseProviderInfo(o, msgs)

var cipher *encryption.Cipher
if o.PassAccessToken || o.SetAuthorization || o.PassAuthorization || (o.Cookie.Refresh != time.Duration(0)) {
validCookieSecretSize := false
for _, i := range []int{16, 24, 32} {
if len(encryption.SecretBytes(o.Cookie.Secret)) == i {
validCookieSecretSize = true
}
}
var decoded bool
if string(encryption.SecretBytes(o.Cookie.Secret)) != o.Cookie.Secret {
decoded = true
}
if !validCookieSecretSize {
var suffix string
if decoded {
suffix = fmt.Sprintf(" note: cookie secret was base64 decoded from %q", o.Cookie.Secret)
}
msgs = append(msgs, fmt.Sprintf(
"cookie_secret must be 16, 24, or 32 bytes "+
"to create an AES cipher when "+
"pass_access_token == true or "+
"cookie_refresh != 0, but is %d bytes.%s",
len(encryption.SecretBytes(o.Cookie.Secret)), suffix))
} else {
var err error
cipher, err = encryption.NewCipher(encryption.SecretBytes(o.Cookie.Secret))
if err != nil {
msgs = append(msgs, fmt.Sprintf("cookie-secret error: %v", err))
}
}
}

o.Session.Cipher = cipher
sessionStore, err := sessions.NewSessionStore(&o.Session, &o.Cookie)
if err != nil {
Expand Down
2 changes: 1 addition & 1 deletion pkg/validation/options_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import (
)

const (
cookieSecret = "foobar"
cookieSecret = "secretthirtytwobytes+abcdefghijk"
clientID = "bazquux"
clientSecret = "xyzzyplugh"
)
Expand Down

0 comments on commit 03a0e1a

Please sign in to comment.