@@ -35,6 +35,7 @@ var _ = Describe("NewSessionStore", func() {
3535 var response *httptest.ResponseRecorder
3636 var session *sessionsapi.SessionState
3737 var ss sessionsapi.SessionStore
38+ var mr *miniredis.Miniredis
3839
3940 CheckCookieOptions := func() {
4041 Context("the cookies returned", func() {
@@ -203,7 +204,38 @@ var _ = Describe("NewSessionStore", func() {
203204 })
204205
205206 Context("when Load is called", func() {
206− var loadedSession *sessionsapi.SessionState
207+ LoadSessionTests := func() {
208+ var loadedSession *sessionsapi.SessionState
209+ BeforeEach(func() {
210+ var err error
211+ loadedSession, err = ss.Load(request)
212+ Expect(err).ToNot(HaveOccurred())
213+ })
214+
215+ It("loads a session equal to the original session", func() {
216+ if cookieOpts.CookieSecret == "" {
217+ // Only Email and User stored in session when encrypted
218+ Expect(loadedSession.Email).To(Equal(session.Email))
219+ Expect(loadedSession.User).To(Equal(session.User))
220+ } else {
221+ // All fields stored in session if encrypted
222+
223+ // Can't compare time.Time using Equal() so remove ExpiresOn from sessions
224+ l := *loadedSession
225+ l.CreatedAt = time.Time{}
226+ l.ExpiresOn = time.Time{}
227+ s := *session
228+ s.CreatedAt = time.Time{}
229+ s.ExpiresOn = time.Time{}
230+ Expect(l).To(Equal(s))
231+
232+ // Compare time.Time separately
233+ Expect(loadedSession.CreatedAt.Equal(session.CreatedAt)).To(BeTrue())
234+ Expect(loadedSession.ExpiresOn.Equal(session.ExpiresOn)).To(BeTrue())
235+ }
236+ })
237+ }
238+
207239 BeforeEach(func() {
208240 req := httptest.NewRequest("GET", "http://example.com/", nil)
209241 resp := httptest.NewRecorder()
@@ -213,32 +245,49 @@ var _ = Describe("NewSessionStore", func() {
213245 for _, cookie := range resp.Result().Cookies() {
214246 request.AddCookie(cookie)
215247 }
216− loadedSession, err = ss.Load(request)
217− Expect(err).ToNot(HaveOccurred())
218248 })
219249
220− It("loads a session equal to the original session", func() {
221− if cookieOpts.CookieSecret == "" {
222− // Only Email and User stored in session when encrypted
223− Expect(loadedSession.Email).To(Equal(session.Email))
224− Expect(loadedSession.User).To(Equal(session.User))
225− } else {
226− // All fields stored in session if encrypted
227−
228− // Can't compare time.Time using Equal() so remove ExpiresOn from sessions
229− l := *loadedSession
230− l.CreatedAt = time.Time{}
231− l.ExpiresOn = time.Time{}
232− s := *session
233− s.CreatedAt = time.Time{}
234− s.ExpiresOn = time.Time{}
235− Expect(l).To(Equal(s))
236−
237− // Compare time.Time separately
238− Expect(loadedSession.CreatedAt.Equal(session.CreatedAt)).To(BeTrue())
239− Expect(loadedSession.ExpiresOn.Equal(session.ExpiresOn)).To(BeTrue())
240− }
250+ Context("before the refresh period", func() {
251+ LoadSessionTests()
241252 })
253+
254+ // Test TTLs and cleanup of persistent session storage
255+ // For non-persistent we rely on the browser cookie lifecycle
256+ if persistent {
257+ Context("after the refresh period, but before the cookie expire period", func() {
258+ BeforeEach(func() {
259+ switch ss.(type) {
260+ case *redis.SessionStore:
261+ mr.FastForward(cookieOpts.CookieRefresh + time.Minute)
262+ }
263+ })
264+
265+ LoadSessionTests()
266+ })
267+
268+ Context("after the cookie expire period", func() {
269+ var loadedSession *sessionsapi.SessionState
270+ var err error
271+
272+ BeforeEach(func() {
273+ switch ss.(type) {
274+ case *redis.SessionStore:
275+ mr.FastForward(cookieOpts.CookieExpire + time.Minute)
276+ }
277+
278+ loadedSession, err = ss.Load(request)
279+ Expect(err).To(HaveOccurred())
280+ })
281+
282+ It("returns an error loading the session", func() {
283+ Expect(err).To(HaveOccurred())
284+ })
285+
286+ It("returns an empty session", func() {
287+ Expect(loadedSession).To(BeNil())
288+ })
289+ })
290+ }
242291 })
243292
244293 if persistent {
@@ -263,7 +312,7 @@ var _ = Describe("NewSessionStore", func() {
263312 CookieName: "_cookie_name",
264313 CookiePath: "/path",
265314 CookieExpire: time.Duration(72) * time.Hour,
266− CookieRefresh: time.Duration(3600),
315+ CookieRefresh: time.Duration(2) * time.Hour,
267316 CookieSecure: false,
268317 CookieHTTPOnly: false,
269318 CookieDomain: "example.com",
@@ -305,7 +354,7 @@ var _ = Describe("NewSessionStore", func() {
305354 CookieName: "_oauth2_proxy",
306355 CookiePath: "/",
307356 CookieExpire: time.Duration(168) * time.Hour,
308− CookieRefresh: time.Duration(0),
357+ CookieRefresh: time.Duration(1) * time.Hour,
309358 CookieSecure: true,
310359 CookieHTTPOnly: true,
311360 }
@@ -340,7 +389,6 @@ var _ = Describe("NewSessionStore", func() {
340389 })
341390
342391 Context("with type 'redis'", func() {
343− var mr *miniredis.Miniredis
344392 BeforeEach(func() {
345393 var err error
346394 mr, err = miniredis.Run()