11package application
22
33import (
4+ "context"
45 "net/http"
56 "net/url"
67 "strings"
@@ -19,8 +20,41 @@ func (a *Application) handleAuthStart(rw http.ResponseWriter, r *http.Request, f
1920 state , err := a .createState (r , rw , fwd )
2021 if err != nil {
2122 a .log .WithError (err ).Warning ("failed to create state" )
22- rw .WriteHeader (400 )
23- return
23+ if ! strings .HasPrefix (err .Error (), "failed to get session" ) {
24+ rw .WriteHeader (400 )
25+ return
26+ }
27+
28+ // Client has a cookie but we're unable to load the session from
29+ // storage (TMPDIR=/dev/shm). This can happen if the session file
30+ // was deleted due to container restart or session invalidation
31+ // (e.g., logout on auth server).
32+ //
33+ // Re-save an empty session and try again.
34+
35+ session , err := a .sessions .Get (r , a .SessionName ())
36+ if err != nil && ! strings .HasSuffix (err .Error (), "no such file or directory" ) {
37+ a .log .WithError (err ).Warning ("failed to get session" )
38+ rw .WriteHeader (400 )
39+ return
40+ }
41+ err = a .sessions .Save (r , rw , session )
42+ if err != nil {
43+ a .log .WithError (err ).Warning ("failed to save session" )
44+ rw .WriteHeader (400 )
45+ return
46+ }
47+
48+ // The registry caches the previous attempt to open the session so it
49+ // needs to be cleared in order to get the session in createState().
50+ * r = * r .WithContext (context .Background ())
51+
52+ state , err = a .createState (r , rw , fwd )
53+ if err != nil {
54+ a .log .WithError (err ).Warning ("failed to create state on retry" )
55+ rw .WriteHeader (400 )
56+ return
57+ }
2458 }
2559 http .Redirect (rw , r , a .oauthConfig .AuthCodeURL (state ), http .StatusFound )
2660}
0 commit comments