git.iko.soy/typeable/oauth2-proxy
on master help sign in
Allow binary values in signed cookies

Make signedValue & Validate operate on []byte by default and not assume/cast string. Any casting will be done from callers.

commitb4530b92927d23c3df986e4b25b6e2046a047f61 authorNick Meves <nick.meves@greenhouse.io> dateMon 4 May 2020, 11:34 (6 years ago) parentf9025a8
4 files changed+11−11
pkg/encryption/cipher.go+4−4 pkg/sessions/cookie/session_store.go+2−2 pkg/sessions/redis/redis_store.go+4−4 pkg/sessions/session_store_test.go+1−1
pkg/encryption/cipher.go+4−4
@@ -39,7 +39,7 @@ func SecretBytes(secret string) []byte {
3939// additionally, the 'value' is encrypted so it's opaque to the browser
4040
4141// Validate ensures a cookie is properly signed
42−func Validate(cookie *http.Cookie, seed string, expiration time.Duration) (value string, t time.Time, ok bool) {
42+func Validate(cookie *http.Cookie, seed string, expiration time.Duration) (value []byte, t time.Time, ok bool) {
4343 // value, timestamp, sig
4444 parts := strings.Split(cookie.Value, "|")
4545 if len(parts) != 3 {
@@ -59,7 +59,7 @@ func Validate(cookie *http.Cookie, seed string, expiration time.Duration) (value
5959 // it's a valid cookie. now get the contents
6060 rawValue, err := base64.URLEncoding.DecodeString(parts[0])
6161 if err == nil {
62− value = string(rawValue)
62+ value = rawValue
6363 ok = true
6464 return
6565 }
@@ -69,8 +69,8 @@ func Validate(cookie *http.Cookie, seed string, expiration time.Duration) (value
6969}
7070
7171// SignedValue returns a cookie that is signed and can later be checked with Validate
72−func SignedValue(seed string, key string, value string, now time.Time) string {
73− encodedValue := base64.URLEncoding.EncodeToString([]byte(value))
72+func SignedValue(seed string, key string, value []byte, now time.Time) string {
73+ encodedValue := base64.URLEncoding.EncodeToString(value)
7474 timeStr := fmt.Sprintf("%d", now.Unix())
7575 sig := cookieSignature(sha256.New, seed, key, encodedValue, timeStr)
7676 cookieVal := fmt.Sprintf("%s|%s|%s", encodedValue, timeStr, sig)
pkg/sessions/cookie/session_store.go+2−2
@@ -59,7 +59,7 @@ func (s *SessionStore) Load(req *http.Request) (*sessions.SessionState, error) {
5959 return nil, errors.New("cookie signature not valid")
6060 }
6161
62− session, err := sessionFromCookie(val, s.CookieCipher)
62+ session, err := sessionFromCookie(string(val), s.CookieCipher)
6363 if err != nil {
6464 return nil, err
6565 }
@@ -104,7 +104,7 @@ func (s *SessionStore) setSessionCookie(rw http.ResponseWriter, req *http.Reques
104104// authentication details
105105func (s *SessionStore) makeSessionCookie(req *http.Request, value string, now time.Time) []*http.Cookie {
106106 if value != "" {
107− value = encryption.SignedValue(s.CookieOptions.Secret, s.CookieOptions.Name, value, now)
107+ value = encryption.SignedValue(s.CookieOptions.Secret, s.CookieOptions.Name, []byte(value), now)
108108 }
109109 c := s.makeCookie(req, s.CookieOptions.Name, value, s.CookieOptions.Expire, now)
110110 if len(c.Value) > 4096-len(s.CookieOptions.Name) {
pkg/sessions/redis/redis_store.go+4−4
@@ -175,7 +175,7 @@ func (store *SessionStore) Load(req *http.Request) (*sessions.SessionState, erro
175175 return nil, fmt.Errorf("cookie signature not valid")
176176 }
177177 ctx := req.Context()
178− session, err := store.loadSessionFromString(ctx, val)
178+ session, err := store.loadSessionFromString(ctx, string(val))
179179 if err != nil {
180180 return nil, fmt.Errorf("error loading session: %s", err)
181181 }
@@ -237,7 +237,7 @@ func (store *SessionStore) Clear(rw http.ResponseWriter, req *http.Request) erro
237237
238238 // We only return an error if we had an issue with redis
239239 // If there's an issue decoding the ticket, ignore it
240− ticket, _ := decodeTicket(store.CookieOptions.Name, val)
240+ ticket, _ := decodeTicket(store.CookieOptions.Name, string(val))
241241 if ticket != nil {
242242 ctx := req.Context()
243243 err := store.Client.Del(ctx, ticket.asHandle(store.CookieOptions.Name))
@@ -251,7 +251,7 @@ func (store *SessionStore) Clear(rw http.ResponseWriter, req *http.Request) erro
251251// makeCookie makes a cookie, signing the value if present
252252func (store *SessionStore) makeCookie(req *http.Request, value string, expires time.Duration, now time.Time) *http.Cookie {
253253 if value != "" {
254− value = encryption.SignedValue(store.CookieOptions.Secret, store.CookieOptions.Name, value, now)
254+ value = encryption.SignedValue(store.CookieOptions.Secret, store.CookieOptions.Name, []byte(value), now)
255255 }
256256 return cookies.MakeCookieFromOptions(
257257 req,
@@ -302,7 +302,7 @@ func (store *SessionStore) getTicket(requestCookie *http.Cookie) (*TicketData, e
302302 }
303303
304304 // Valid cookie, decode the ticket
305− ticket, err := decodeTicket(store.CookieOptions.Name, val)
305+ ticket, err := decodeTicket(store.CookieOptions.Name, string(val))
306306 if err != nil {
307307 // If we can't decode the ticket we have to create a new one
308308 return newTicket()
pkg/sessions/session_store_test.go+1−1
@@ -170,7 +170,7 @@ var _ = Describe("NewSessionStore", func() {
170170 BeforeEach(func() {
171171 By("Using a valid cookie with a different providers session encoding")
172172 broken := "BrokenSessionFromADifferentSessionImplementation"
173− value := encryption.SignedValue(cookieOpts.Secret, cookieOpts.Name, broken, time.Now())
173+ value := encryption.SignedValue(cookieOpts.Secret, cookieOpts.Name, []byte(broken), time.Now())
174174 cookie := cookiesapi.MakeCookieFromOptions(request, cookieOpts.Name, value, cookieOpts, cookieOpts.Expire, time.Now())
175175 request.AddCookie(cookie)
176176