git.iko.soy/typeable/oauth2-proxy
on master help sign in
Refactor the utils package to other areas (#538)

* Refactor the utils package to other areas Move cookieSession functions to cookie session store & align the double implementation of SecretBytes to be united and housed under encryption * Remove unused Provider SessionFromCookie/CookieForSession These implementations aren't used, these are handled in the cookie store. * Add changelog entry for session/utils refactor

commitd228d5a928176575364e9e1fb4bb4e417c91de3f authorNick Meves <nick.meves@greenhouse.io> dateThu 14 May 2020, 02:16 (6 years ago) parent111d17e
8 files changed+41−89
CHANGELOG.md+1−1 options.go+4−28 pkg/encryption/cipher.go+23 pkg/sessions/cookie/session_store.go+12−3 pkg/sessions/session_store_test.go+1−2 pkg/sessions/utils/utils.go−41 providers/provider_default.go−11 providers/providers.go−3
CHANGELOG.md+1−1
@@ -34,7 +34,7 @@
3434 Use `--prefer-email-to-user` to restore falling back to the Email in these cases.
3535
3636## Changes since v5.1.1
37−
37+- [#538](https://github.com/oauth2-proxy/oauth2-proxy/pull/538) Refactor sessions/utils.go functionality to other areas (@NickMeves)
3838- [#503](https://github.com/oauth2-proxy/oauth2-proxy/pull/503) Implements --real-client-ip-header option to select the header from which to obtain a proxied client's IP (@Izzette)
3939- [#529](https://github.com/oauth2-proxy/oauth2-proxy/pull/529) Add local test environments for testing changes and new features (@JoelSpeed)
4040- [#537](https://github.com/oauth2-proxy/oauth2-proxy/pull/537) Drop Fallback to Email if User not set (@JoelSpeed)
options.go+4−28
@@ -4,7 +4,6 @@ import (
44 "context"
55 "crypto"
66 "crypto/tls"
7− "encoding/base64"
87 "fmt"
98 "io/ioutil"
109 "net/http"
@@ -386,12 +385,12 @@ func (o *Options) Validate() error {
386385 if o.PassAccessToken || o.SetAuthorization || o.PassAuthorization || (o.Cookie.Refresh != time.Duration(0)) {
387386 validCookieSecretSize := false
388387 for _, i := range []int{16, 24, 32} {
389− if len(secretBytes(o.Cookie.Secret)) == i {
388+ if len(encryption.SecretBytes(o.Cookie.Secret)) == i {
390389 validCookieSecretSize = true
391390 }
392391 }
393392 var decoded bool
394− if string(secretBytes(o.Cookie.Secret)) != o.Cookie.Secret {
393+ if string(encryption.SecretBytes(o.Cookie.Secret)) != o.Cookie.Secret {
395394 decoded = true
396395 }
397396 if !validCookieSecretSize {
@@ -404,10 +403,10 @@ func (o *Options) Validate() error {
404403 "to create an AES cipher when "+
405404 "pass_access_token == true or "+
406405 "cookie_refresh != 0, but is %d bytes.%s",
407− len(secretBytes(o.Cookie.Secret)), suffix))
406+ len(encryption.SecretBytes(o.Cookie.Secret)), suffix))
408407 } else {
409408 var err error
410− cipher, err = encryption.NewCipher(secretBytes(o.Cookie.Secret))
409+ cipher, err = encryption.NewCipher(encryption.SecretBytes(o.Cookie.Secret))
411410 if err != nil {
412411 msgs = append(msgs, fmt.Sprintf("cookie-secret error: %v", err))
413412 }
@@ -643,29 +642,6 @@ func validateCookieName(o *Options, msgs []string) []string {
643642 return msgs
644643}
645644
646−func addPadding(secret string) string {
647− padding := len(secret) % 4
648− switch padding {
649− case 1:
650− return secret + "==="
651− case 2:
652− return secret + "=="
653− case 3:
654− return secret + "="
655− default:
656− return secret
657− }
658−}
659−
660−// secretBytes attempts to base64 decode the secret, if that fails it treats the secret as binary
661−func secretBytes(secret string) []byte {
662− b, err := base64.URLEncoding.DecodeString(addPadding(secret))
663− if err == nil {
664− return []byte(addPadding(string(b)))
665− }
666− return []byte(secret)
667−}
668−
669645func setupLogger(o *Options, msgs []string) []string {
670646 // Setup the log file
671647 if len(o.LoggingFilename) > 0 {
pkg/encryption/cipher.go+23
@@ -17,6 +17,29 @@ import (
1717 "time"
1818)
1919
20+// SecretBytes attempts to base64 decode the secret, if that fails it treats the secret as binary
21+func SecretBytes(secret string) []byte {
22+ b, err := base64.URLEncoding.DecodeString(addPadding(secret))
23+ if err == nil {
24+ return []byte(addPadding(string(b)))
25+ }
26+ return []byte(secret)
27+}
28+
29+func addPadding(secret string) string {
30+ padding := len(secret) % 4
31+ switch padding {
32+ case 1:
33+ return secret + "==="
34+ case 2:
35+ return secret + "=="
36+ case 3:
37+ return secret + "="
38+ default:
39+ return secret
40+ }
41+}
42+
2043// cookies are stored in a 3 part (value + timestamp + signature) to enforce that the values are as originally set.
2144// additionally, the 'value' is encrypted so it's opaque to the browser
2245
pkg/sessions/cookie/session_store.go+12−3
@@ -13,7 +13,6 @@ import (
1313 "github.com/oauth2-proxy/oauth2-proxy/pkg/cookies"
1414 "github.com/oauth2-proxy/oauth2-proxy/pkg/encryption"
1515 "github.com/oauth2-proxy/oauth2-proxy/pkg/logger"
16− "github.com/oauth2-proxy/oauth2-proxy/pkg/sessions/utils"
1716)
1817
1918const (
@@ -38,7 +37,7 @@ func (s *SessionStore) Save(rw http.ResponseWriter, req *http.Request, ss *sessi
3837 if ss.CreatedAt.IsZero() {
3938 ss.CreatedAt = time.Now()
4039 }
41− value, err := utils.CookieForSession(ss, s.CookieCipher)
40+ value, err := cookieForSession(ss, s.CookieCipher)
4241 if err != nil {
4342 return err
4443 }
@@ -59,7 +58,7 @@ func (s *SessionStore) Load(req *http.Request) (*sessions.SessionState, error) {
5958 return nil, errors.New("cookie signature not valid")
6059 }
6160
62− session, err := utils.SessionFromCookie(val, s.CookieCipher)
61+ session, err := sessionFromCookie(val, s.CookieCipher)
6362 if err != nil {
6463 return nil, err
6564 }
@@ -83,6 +82,16 @@ func (s *SessionStore) Clear(rw http.ResponseWriter, req *http.Request) error {
8382 return nil
8483}
8584
85+// cookieForSession serializes a session state for storage in a cookie
86+func cookieForSession(s *sessions.SessionState, c *encryption.Cipher) (string, error) {
87+ return s.EncodeSessionState(c)
88+}
89+
90+// sessionFromCookie deserializes a session from a cookie value
91+func sessionFromCookie(v string, c *encryption.Cipher) (s *sessions.SessionState, err error) {
92+ return sessions.DecodeSessionState(v, c)
93+}
94+
8695// setSessionCookie adds the user's session cookie to the response
8796func (s *SessionStore) setSessionCookie(rw http.ResponseWriter, req *http.Request, val string, created time.Time) {
8897 for _, c := range s.makeSessionCookie(req, val, created) {
pkg/sessions/session_store_test.go+1−2
@@ -18,7 +18,6 @@ import (
1818 "github.com/oauth2-proxy/oauth2-proxy/pkg/sessions"
1919 sessionscookie "github.com/oauth2-proxy/oauth2-proxy/pkg/sessions/cookie"
2020 "github.com/oauth2-proxy/oauth2-proxy/pkg/sessions/redis"
21− "github.com/oauth2-proxy/oauth2-proxy/pkg/sessions/utils"
2221 . "github.com/onsi/ginkgo"
2322 . "github.com/onsi/gomega"
2423)
@@ -365,7 +364,7 @@ var _ = Describe("NewSessionStore", func() {
365364 _, err := rand.Read(secret)
366365 Expect(err).ToNot(HaveOccurred())
367366 cookieOpts.Secret = base64.URLEncoding.EncodeToString(secret)
368− cipher, err := encryption.NewCipher(utils.SecretBytes(cookieOpts.Secret))
367+ cipher, err := encryption.NewCipher(encryption.SecretBytes(cookieOpts.Secret))
369368 Expect(err).ToNot(HaveOccurred())
370369 Expect(cipher).ToNot(BeNil())
371370 opts.Cipher = cipher
pkg/sessions/utils/utils.godeleted−41
@@ -1,41 +0,0 @@
1−package utils
2−
3−import (
4− "encoding/base64"
5−
6− "github.com/oauth2-proxy/oauth2-proxy/pkg/apis/sessions"
7− "github.com/oauth2-proxy/oauth2-proxy/pkg/encryption"
8−)
9−
10−// CookieForSession serializes a session state for storage in a cookie
11−func CookieForSession(s *sessions.SessionState, c *encryption.Cipher) (string, error) {
12− return s.EncodeSessionState(c)
13−}
14−
15−// SessionFromCookie deserializes a session from a cookie value
16−func SessionFromCookie(v string, c *encryption.Cipher) (s *sessions.SessionState, err error) {
17− return sessions.DecodeSessionState(v, c)
18−}
19−
20−// SecretBytes attempts to base64 decode the secret, if that fails it treats the secret as binary
21−func SecretBytes(secret string) []byte {
22− b, err := base64.URLEncoding.DecodeString(addPadding(secret))
23− if err == nil {
24− return []byte(addPadding(string(b)))
25− }
26− return []byte(secret)
27−}
28−
29−func addPadding(secret string) string {
30− padding := len(secret) % 4
31− switch padding {
32− case 1:
33− return secret + "==="
34− case 2:
35− return secret + "=="
36− case 3:
37− return secret + "="
38− default:
39− return secret
40− }
41−}
providers/provider_default.go−11
@@ -14,7 +14,6 @@ import (
1414 "github.com/coreos/go-oidc"
1515
1616 "github.com/oauth2-proxy/oauth2-proxy/pkg/apis/sessions"
17− "github.com/oauth2-proxy/oauth2-proxy/pkg/encryption"
1817)
1918
2019var _ Provider = (*ProviderData)(nil)
@@ -108,16 +107,6 @@ func (p *ProviderData) GetLoginURL(redirectURI, state string) string {
108107 return a.String()
109108}
110109
111−// CookieForSession serializes a session state for storage in a cookie
112−func (p *ProviderData) CookieForSession(s *sessions.SessionState, c *encryption.Cipher) (string, error) {
113− return s.EncodeSessionState(c)
114−}
115−
116−// SessionFromCookie deserializes a session from a cookie value
117−func (p *ProviderData) SessionFromCookie(v string, c *encryption.Cipher) (s *sessions.SessionState, err error) {
118− return sessions.DecodeSessionState(v, c)
119−}
120−
121110// GetEmailAddress returns the Account email address
122111func (p *ProviderData) GetEmailAddress(ctx context.Context, s *sessions.SessionState) (string, error) {
123112 return "", errors.New("not implemented")
providers/providers.go−3
@@ -5,7 +5,6 @@ import (
55
66 "github.com/coreos/go-oidc"
77 "github.com/oauth2-proxy/oauth2-proxy/pkg/apis/sessions"
8− "github.com/oauth2-proxy/oauth2-proxy/pkg/encryption"
98)
109
1110// Provider represents an upstream identity provider implementation
@@ -19,8 +18,6 @@ type Provider interface {
1918 ValidateSessionState(ctx context.Context, s *sessions.SessionState) bool
2019 GetLoginURL(redirectURI, finalRedirect string) string
2120 RefreshSessionIfNeeded(ctx context.Context, s *sessions.SessionState) (bool, error)
22− SessionFromCookie(string, *encryption.Cipher) (*sessions.SessionState, error)
23− CookieForSession(*sessions.SessionState, *encryption.Cipher) (string, error)
2421 CreateSessionStateFromBearerToken(ctx context.Context, rawIDToken string, idToken *oidc.IDToken) (*sessions.SessionState, error)
2522}
2623