1
0
mirror of https://github.com/oauth2-proxy/oauth2-proxy.git synced 2025-05-31 23:19:50 +02:00

Integrate cookie builder in cookie session store

This commit is contained in:
Joel Speed 2021-03-23 14:40:45 +00:00 committed by Joel Speed
parent 2dcda8539c
commit 7f1ae0ee4d
No known key found for this signature in database
GPG Key ID: 6E80578D6751DEFB

View File

@ -1,7 +1,6 @@
package cookie package cookie
import ( import (
"errors"
"fmt" "fmt"
"net/http" "net/http"
"regexp" "regexp"
@ -9,7 +8,7 @@ import (
"github.com/oauth2-proxy/oauth2-proxy/v7/pkg/apis/options" "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/apis/options"
"github.com/oauth2-proxy/oauth2-proxy/v7/pkg/apis/sessions" "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/apis/sessions"
pkgcookies "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/cookies" "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/cookies"
"github.com/oauth2-proxy/oauth2-proxy/v7/pkg/encryption" "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/encryption"
"github.com/oauth2-proxy/oauth2-proxy/v7/pkg/logger" "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/logger"
) )
@ -27,9 +26,9 @@ var _ sessions.SessionStore = &SessionStore{}
// SessionStore is an implementation of the sessions.SessionStore // SessionStore is an implementation of the sessions.SessionStore
// interface that stores sessions in client side cookies // interface that stores sessions in client side cookies
type SessionStore struct { type SessionStore struct {
Cookie *options.Cookie cookieBuilder cookies.Builder
CookieCipher encryption.Cipher CookieCipher encryption.Cipher
Minimal bool Minimal bool
} }
// Save takes a sessions.SessionState and stores the information from it // Save takes a sessions.SessionState and stores the information from it
@ -48,17 +47,18 @@ func (s *SessionStore) Save(rw http.ResponseWriter, req *http.Request, ss *sessi
// Load reads sessions.SessionState information from Cookies within the // Load reads sessions.SessionState information from Cookies within the
// HTTP request object // HTTP request object
func (s *SessionStore) Load(req *http.Request) (*sessions.SessionState, error) { func (s *SessionStore) Load(req *http.Request) (*sessions.SessionState, error) {
c, err := loadCookie(req, s.Cookie.Name) c, err := loadCookie(req, s.cookieBuilder.GetName())
if err != nil { if err != nil {
// always http.ErrNoCookie // always http.ErrNoCookie
return nil, fmt.Errorf("cookie %q not present", s.Cookie.Name) return nil, fmt.Errorf("cookie %q not present", s.cookieBuilder.GetName())
}
val, _, ok := encryption.Validate(c, s.Cookie.Secret, s.Cookie.Expire)
if !ok {
return nil, errors.New("cookie signature not valid")
} }
session, err := sessions.DecodeSessionState(val, s.CookieCipher, true) val, err := s.cookieBuilder.ValidateCookie(c)
if err != nil {
return nil, fmt.Errorf("cookie signature not valid: %v", err)
}
session, err := sessions.DecodeSessionState([]byte(val), s.CookieCipher, true)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -69,11 +69,17 @@ func (s *SessionStore) Load(req *http.Request) (*sessions.SessionState, error) {
// clear the session // clear the session
func (s *SessionStore) Clear(rw http.ResponseWriter, req *http.Request) error { func (s *SessionStore) Clear(rw http.ResponseWriter, req *http.Request) error {
// matches CookieName, CookieName_<number> // matches CookieName, CookieName_<number>
var cookieNameRegex = regexp.MustCompile(fmt.Sprintf("^%s(_\\d+)?$", s.Cookie.Name)) var cookieNameRegex = regexp.MustCompile(fmt.Sprintf("^%s(_\\d+)?$", s.cookieBuilder.GetName()))
for _, c := range req.Cookies() { for _, c := range req.Cookies() {
if cookieNameRegex.MatchString(c.Name) { if cookieNameRegex.MatchString(c.Name) {
clearCookie := s.makeCookie(req, c.Name, "", time.Hour*-1, time.Now()) clearCookie, err := s.cookieBuilder.
WithName(c.Name).
WithExpiration(time.Hour*-1).
MakeCookie(req, "")
if err != nil {
return err
}
http.SetCookie(rw, clearCookie) http.SetCookie(rw, clearCookie)
} }
@ -111,30 +117,14 @@ func (s *SessionStore) setSessionCookie(rw http.ResponseWriter, req *http.Reques
// makeSessionCookie creates an http.Cookie containing the authenticated user's // makeSessionCookie creates an http.Cookie containing the authenticated user's
// authentication details // authentication details
func (s *SessionStore) makeSessionCookie(req *http.Request, value []byte, now time.Time) ([]*http.Cookie, error) { func (s *SessionStore) makeSessionCookie(req *http.Request, value []byte, now time.Time) ([]*http.Cookie, error) {
strValue := string(value) cookie, err := s.cookieBuilder.WithSignedValue(true).WithStart(now).MakeCookie(req, string(value))
if strValue != "" { if err != nil {
var err error return nil, fmt.Errorf("could not create cookie: %v", err)
strValue, err = encryption.SignedValue(s.Cookie.Secret, s.Cookie.Name, value, now)
if err != nil {
return nil, err
}
} }
c := s.makeCookie(req, s.Cookie.Name, strValue, s.Cookie.Expire, now) if len(cookie.String()) > maxCookieLength {
if len(c.String()) > maxCookieLength { return splitCookie(cookie), nil
return splitCookie(c), nil
} }
return []*http.Cookie{c}, nil return []*http.Cookie{cookie}, nil
}
func (s *SessionStore) makeCookie(req *http.Request, name string, value string, expiration time.Duration, now time.Time) *http.Cookie {
return pkgcookies.MakeCookieFromOptions(
req,
name,
value,
s.Cookie,
expiration,
now,
)
} }
// NewCookieSessionStore initialises a new instance of the SessionStore from // NewCookieSessionStore initialises a new instance of the SessionStore from
@ -146,9 +136,9 @@ func NewCookieSessionStore(opts *options.SessionOptions, cookieOpts *options.Coo
} }
return &SessionStore{ return &SessionStore{
CookieCipher: cipher, CookieCipher: cipher,
Cookie: cookieOpts, cookieBuilder: cookies.NewBuilder(*cookieOpts),
Minimal: opts.Cookie.Minimal, Minimal: opts.Cookie.Minimal,
}, nil }, nil
} }