@@ -11,19 +11,20 @@ import (
1111 middlewareapi "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/apis/middleware"
1212 sessionsapi "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/apis/sessions"
1313 "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/logger"
14+ "github.com/oauth2-proxy/oauth2-proxy/v7/providers"
1415)
1516
16−// StoredSessionLoaderOptions cotnains all of the requirements to construct
17+// StoredSessionLoaderOptions contains all of the requirements to construct
1718// a stored session loader.
1819// All options must be provided.
1920type StoredSessionLoaderOptions struct {
20− // Session storage basckend
21+ // Session storage backend
2122 SessionStore sessionsapi.SessionStore
2223
2324 // How often should sessions be refreshed
2425 RefreshPeriod time.Duration
2526
26− // Provider based sesssion refreshing
27+ // Provider based session refreshing
2728 RefreshSession func(context.Context, *sessionsapi.SessionState) (bool, error)
2829
2930 // Provider based session validation.
@@ -115,7 +116,7 @@ func (s *storedSessionLoader) refreshSessionIfNeeded(rw http.ResponseWriter, req
115116 return nil
116117 }
117118
118− logger.Printf("Refreshing %s old session cookie for %s (refresh after %s)", session.Age(), session, s.refreshPeriod)
119+ logger.Printf("Refreshing session - User: %s; SessionAge: %s", session.User, session.Age())
119120 err := s.refreshSession(rw, req, session)
120121 if err != nil {
121122 // If a preemptive refresh fails, we still keep the session
@@ -131,21 +132,27 @@ func (s *storedSessionLoader) refreshSessionIfNeeded(rw http.ResponseWriter, req
131132// and will save the session if it was updated.
132133func (s *storedSessionLoader) refreshSession(rw http.ResponseWriter, req *http.Request, session *sessionsapi.SessionState) error {
133134 refreshed, err := s.sessionRefresher(req.Context(), session)
134− if err != nil {
135+ if err != nil && !errors.Is(err, providers.ErrNotImplemented) {
135136 return fmt.Errorf("error refreshing tokens: %v", err)
136137 }
137138
139+ // HACK:
140+ // Providers that don't implement `RefreshSession` use the default
141+ // implementation which returns `ErrNotImplemented`.
142+ // Pretend it refreshed to reset the refresh timer so that `ValidateSession`
143+ // isn't triggered every subsequent request and is only called once during
144+ // this request.
145+ if errors.Is(err, providers.ErrNotImplemented) {
146+ refreshed = true
147+ }
148+
149+ // Session not refreshed, nothing to persist.
138150 if !refreshed {
139151 return nil
140152 }
141153
142154 // If we refreshed, update the `CreatedAt` time to reset the refresh timer
143− //
144− // HACK:
145− // Providers that don't implement `RefreshSession` use the default
146− // implementation. It always returns `refreshed == true`, so the
147− // `session.CreatedAt` is updated and doesn't trigger `ValidateSession`
148− // every subsequent request.
155+ // (In case underlying provider implementations forget)
149156 session.CreatedAtNow()
150157
151158 // Because the session was refreshed, make sure to save it