git.iko.soy/typeable/oauth2-proxy
on master help sign in
Implement ClearSession for cookie SessionStore
commit15a2cf8b9e174bf4607f089f2a4bced6bad1a3e0 authorJoel Speed <Joel.speed@hotmail.co.uk> dateTue 7 May 2019, 00:20 (7 years ago) parent8b3a385
3 files changed+99−13
pkg/cookies/cookies.go+34 pkg/sessions/cookie/session_store.go+47−9 pkg/sessions/session_store_test.go+18−4
pkg/cookies/cookies.gonew file+34
@@ -0,0 +1,34 @@
1+package cookies
2+
3+import (
4+ "net"
5+ "net/http"
6+ "strings"
7+ "time"
8+
9+ "github.com/pusher/oauth2_proxy/logger"
10+)
11+
12+// MakeCookie constructs a cookie from the given parameters,
13+// discovering the domain from the request if not specified.
14+func MakeCookie(req *http.Request, name string, value string, path string, domain string, httpOnly bool, secure bool, expiration time.Duration, now time.Time) *http.Cookie {
15+ if domain != "" {
16+ host := req.Host
17+ if h, _, err := net.SplitHostPort(host); err == nil {
18+ host = h
19+ }
20+ if !strings.HasSuffix(host, domain) {
21+ logger.Printf("Warning: request host is %q but using configured cookie domain of %q", host, domain)
22+ }
23+ }
24+
25+ return &http.Cookie{
26+ Name: name,
27+ Value: value,
28+ Path: path,
29+ Domain: domain,
30+ HttpOnly: httpOnly,
31+ Secure: secure,
32+ Expires: now.Add(expiration),
33+ }
34+}
pkg/sessions/cookie/session_store.go+47−9
@@ -4,12 +4,14 @@ import (
44 "errors"
55 "fmt"
66 "net/http"
7+ "regexp"
78 "strings"
89 "time"
910
1011 "github.com/pusher/oauth2_proxy/cookie"
1112 "github.com/pusher/oauth2_proxy/pkg/apis/options"
1213 "github.com/pusher/oauth2_proxy/pkg/apis/sessions"
14+ "github.com/pusher/oauth2_proxy/pkg/cookies"
1315 "github.com/pusher/oauth2_proxy/pkg/sessions/utils"
1416)
1517
@@ -19,10 +21,14 @@ var _ sessions.SessionStore = &SessionStore{}
1921// SessionStore is an implementation of the sessions.SessionStore
2022// interface that stores sessions in client side cookies
2123type SessionStore struct {
22− CookieCipher *cookie.Cipher
23− CookieExpire time.Duration
24− CookieName string
25− CookieSecret string
24+ CookieCipher *cookie.Cipher
25+ CookieDomain string
26+ CookieExpire time.Duration
27+ CookieHTTPOnly bool
28+ CookieName string
29+ CookiePath string
30+ CookieSecret string
31+ CookieSecure bool
2632}
2733
2834// SaveSession takes a sessions.SessionState and stores the information from it
@@ -54,7 +60,35 @@ func (s *SessionStore) LoadSession(req *http.Request) (*sessions.SessionState, e
5460// ClearSession clears any saved session information by writing a cookie to
5561// clear the session
5662func (s *SessionStore) ClearSession(rw http.ResponseWriter, req *http.Request) error {
57− return fmt.Errorf("method not implemented")
63+ var cookies []*http.Cookie
64+
65+ // matches CookieName, CookieName_<number>
66+ var cookieNameRegex = regexp.MustCompile(fmt.Sprintf("^%s(_\\d+)?$", s.CookieName))
67+
68+ for _, c := range req.Cookies() {
69+ if cookieNameRegex.MatchString(c.Name) {
70+ clearCookie := s.makeCookie(req, c.Name, "", time.Hour*-1)
71+
72+ http.SetCookie(rw, clearCookie)
73+ cookies = append(cookies, clearCookie)
74+ }
75+ }
76+
77+ return nil
78+}
79+
80+func (s *SessionStore) makeCookie(req *http.Request, name string, value string, expiration time.Duration) *http.Cookie {
81+ return cookies.MakeCookie(
82+ req,
83+ name,
84+ value,
85+ s.CookiePath,
86+ s.CookieDomain,
87+ s.CookieHTTPOnly,
88+ s.CookieSecure,
89+ expiration,
90+ time.Now(),
91+ )
5892}
5993
6094// NewCookieSessionStore initialises a new instance of the SessionStore from
@@ -70,10 +104,14 @@ func NewCookieSessionStore(opts options.CookieStoreOptions, cookieOpts *options.
70104 }
71105
72106 return &SessionStore{
73− CookieCipher: cipher,
74− CookieExpire: cookieOpts.CookieExpire,
75− CookieName: cookieOpts.CookieName,
76− CookieSecret: cookieOpts.CookieSecret,
107+ CookieCipher: cipher,
108+ CookieDomain: cookieOpts.CookieDomain,
109+ CookieExpire: cookieOpts.CookieExpire,
110+ CookieHTTPOnly: cookieOpts.CookieHTTPOnly,
111+ CookieName: cookieOpts.CookieName,
112+ CookiePath: cookieOpts.CookiePath,
113+ CookieSecret: cookieOpts.CookieSecret,
114+ CookieSecure: cookieOpts.CookieSecure,
77115 }, nil
78116}
79117
pkg/sessions/session_store_test.go+18−4
@@ -2,6 +2,7 @@ package sessions_test
22
33import (
44 "net/http"
5+ "net/http/httptest"
56 "testing"
67 "time"
78
@@ -9,6 +10,7 @@ import (
910 . "github.com/onsi/gomega"
1011 "github.com/pusher/oauth2_proxy/pkg/apis/options"
1112 sessionsapi "github.com/pusher/oauth2_proxy/pkg/apis/sessions"
13+ "github.com/pusher/oauth2_proxy/pkg/cookies"
1214 "github.com/pusher/oauth2_proxy/pkg/sessions"
1315 "github.com/pusher/oauth2_proxy/pkg/sessions/cookie"
1416)
@@ -23,16 +25,14 @@ var _ = Describe("NewSessionStore", func() {
2325 var cookieOpts *options.CookieOptions
2426
2527 var request *http.Request
26− var response http.ResponseWriter
28+ var response *httptest.ResponseRecorder
2729 var session *sessionsapi.SessionState
2830
2931 CheckCookieOptions := func() {
3032 Context("the cookies returned", func() {
3133 var cookies []*http.Cookie
3234 BeforeEach(func() {
33− req := http.Request{}
34− req.Header.Add("Cookie", response.Header().Get("Set-Cookie"))
35− cookies = req.Cookies()
35+ cookies = response.Result().Cookies()
3636 })
3737
3838 It("have the correct name set", func() {
@@ -97,6 +97,17 @@ var _ = Describe("NewSessionStore", func() {
9797
9898 Context("when ClearSession is called", func() {
9999 BeforeEach(func() {
100+ cookie := cookies.MakeCookie(request,
101+ cookieOpts.CookieName,
102+ "foo",
103+ cookieOpts.CookiePath,
104+ cookieOpts.CookieDomain,
105+ cookieOpts.CookieHTTPOnly,
106+ cookieOpts.CookieSecure,
107+ cookieOpts.CookieExpire,
108+ time.Now(),
109+ )
110+ request.AddCookie(cookie)
100111 err := ss.ClearSession(response, request)
101112 Expect(err).ToNot(HaveOccurred())
102113 })
@@ -166,6 +177,9 @@ var _ = Describe("NewSessionStore", func() {
166177 CookieSecure: true,
167178 CookieHTTPOnly: true,
168179 }
180+
181+ request = httptest.NewRequest("GET", "http://example.com/", nil)
182+ response = httptest.NewRecorder()
169183 })
170184
171185 Context("with type 'cookie'", func() {