From a94ea1874fcbed65ea5c505cf6bdd94cd915a3b6 Mon Sep 17 00:00:00 2001 From: Jusshersmith Date: Mon, 6 Jul 2020 14:42:03 +0100 Subject: [PATCH] sso: prevent upstream switching --- internal/pkg/logging/logging.go | 5 + internal/pkg/sessions/session_state.go | 7 +- internal/proxy/oauthproxy.go | 29 ++- internal/proxy/oauthproxy_test.go | 264 +++++++++++++++---------- 4 files changed, 194 insertions(+), 111 deletions(-) diff --git a/internal/pkg/logging/logging.go b/internal/pkg/logging/logging.go index 003d5820..cafc4cdd 100644 --- a/internal/pkg/logging/logging.go +++ b/internal/pkg/logging/logging.go @@ -144,6 +144,11 @@ func (l *LogEntry) WithEndpoint(endpoint string) *LogEntry { return l.withField("endpoint", endpoint) } +// WithAuthorizedUpstream appends an `authorized_upstream` tag to a LogEntry. +func (l *LogEntry) WithAuthorizedUpstream(upstream string) *LogEntry { + return l.withField("authorized_upstream", upstream) +} + // WithError appends an `error` tag to a LogEntry. Useful for annotating non-Error log // entries (e.g. Fatal messages) with an `error` object. func (l *LogEntry) WithError(err error) *LogEntry { diff --git a/internal/pkg/sessions/session_state.go b/internal/pkg/sessions/session_state.go index f6044d7e..56a805ca 100644 --- a/internal/pkg/sessions/session_state.go +++ b/internal/pkg/sessions/session_state.go @@ -25,9 +25,10 @@ type SessionState struct { ValidDeadline time.Time `json:"valid_deadline"` GracePeriodStart time.Time `json:"grace_period_start"` - Email string `json:"email"` - User string `json:"user"` - Groups []string `json:"groups"` + Email string `json:"email"` + User string `json:"user"` + Groups []string `json:"groups"` + AuthorizedUpstream string `json:"authorized_upstream"` } // LifetimePeriodExpired returns true if the lifetime has expired diff --git a/internal/proxy/oauthproxy.go b/internal/proxy/oauthproxy.go index 72142c42..2092098e 100644 --- a/internal/proxy/oauthproxy.go +++ b/internal/proxy/oauthproxy.go @@ -40,9 +40,10 @@ var SignatureHeaders = []string{ // Errors var ( - ErrLifetimeExpired = errors.New("user lifetime expired") - ErrUserNotAuthorized = errors.New("user not authorized") - ErrWrongIdentityProvider = errors.New("user authenticated with wrong identity provider") + ErrLifetimeExpired = errors.New("user lifetime expired") + ErrUserNotAuthorized = errors.New("user not authorized") + ErrWrongIdentityProvider = errors.New("user authenticated with wrong identity provider") + ErrUnauthorizedUpstreamRequested = errors.New("user session authorized with different upstream") ) type ErrOAuthProxyMisconfigured struct { @@ -591,6 +592,13 @@ func (p *OAuthProxy) OAuthCallback(rw http.ResponseWriter, req *http.Request) { logger.WithRemoteAddress(remoteAddr).WithUser(session.Email).WithInGroups(session.Groups).Info( fmt.Sprintf("oauth callback: user validated ")) + // We add the request host into the session to allow us to validate that each request has + // been authorized for the upstream it's requesting. + // e.g. if a request is authenticated while trying to reach 'foo' upstream, it should not + // automatically be seen as authorized with 'bar' upstream. Each upstream may set different + // validators, so the request should be reauthenticated. + session.AuthorizedUpstream = req.Host + // We store the session in a cookie and redirect the user back to the application err = p.sessionStore.SaveSession(rw, req, session) if err != nil { @@ -655,6 +663,12 @@ func (p *OAuthProxy) Proxy(rw http.ResponseWriter, req *http.Request) { // the user has a stale sesssion. p.OAuthStart(rw, req, tags) return + case ErrUnauthorizedUpstreamRequested: + // The users session has been authorised for use with a different upstream than the one + // that is being requested, so we trigger the start of the oauth flow. + // This exists primarily to implement some form of grace period while this additional session + // check is being introduced. + p.OAuthStart(rw, req, tags) case sessions.ErrInvalidSession: // The user session is invalid and we can't decode it. // This can happen for a variety of reasons but the most common non-malicious @@ -720,6 +734,15 @@ func (p *OAuthProxy) Authenticate(rw http.ResponseWriter, req *http.Request) (er return ErrWrongIdentityProvider } + // check that the user has been authorized against the requested upstream + // this is primarily to combat against a user authorizing with one upstream and attempting to use + // the session cookie for a different upstream. + if req.Host != session.AuthorizedUpstream { + logger.WithProxyHost(req.Host).WithAuthorizedUpstream(session.AuthorizedUpstream).WithUser(session.Email).Warn( + "session authorized against different upstream; restarting authentication") + return ErrUnauthorizedUpstreamRequested + } + // Lifetime period is the entire duration in which the session is valid. // This should be set to something like 14 to 30 days. if session.LifetimePeriodExpired() { diff --git a/internal/proxy/oauthproxy_test.go b/internal/proxy/oauthproxy_test.go index d916ebe5..38432a5d 100644 --- a/internal/proxy/oauthproxy_test.go +++ b/internal/proxy/oauthproxy_test.go @@ -73,9 +73,10 @@ func testSession() *sessions.SessionState { theFuture := time.Now().AddDate(100, 100, 100) return &sessions.SessionState{ - Email: "michael.bland@gsa.gov", - AccessToken: "my_access_token", - Groups: []string{"foo", "bar"}, + Email: "michael.bland@gsa.gov", + AccessToken: "my_access_token", + Groups: []string{"foo", "bar"}, + AuthorizedUpstream: "localhost", RefreshDeadline: theFuture, LifetimeDeadline: theFuture, @@ -456,8 +457,9 @@ func TestAuthenticate(t *testing.T) { SessionStore: &sessions.MockSessionStore{ Session: &sessions.SessionState{ - Email: "email1@example.com", - AccessToken: "my_access_token", + Email: "email1@example.com", + AuthorizedUpstream: "localhost", + AccessToken: "my_access_token", }, }, ExpectedErr: ErrLifetimeExpired, @@ -476,11 +478,12 @@ func TestAuthenticate(t *testing.T) { Name: "authenticate successfully", SessionStore: &sessions.MockSessionStore{ Session: &sessions.SessionState{ - Email: "email1@example.com", - AccessToken: "my_access_token", - LifetimeDeadline: time.Now().Add(time.Duration(24) * time.Hour), - RefreshDeadline: time.Now().Add(time.Duration(1) * time.Hour), - ValidDeadline: time.Now().Add(time.Duration(1) * time.Minute), + Email: "email1@example.com", + AuthorizedUpstream: "localhost", + AccessToken: "my_access_token", + LifetimeDeadline: time.Now().Add(time.Duration(24) * time.Hour), + RefreshDeadline: time.Now().Add(time.Duration(1) * time.Hour), + ValidDeadline: time.Now().Add(time.Duration(1) * time.Minute), }, }, ExpectedErr: nil, @@ -490,11 +493,12 @@ func TestAuthenticate(t *testing.T) { Name: "lifetime expired, do not authenticate", SessionStore: &sessions.MockSessionStore{ Session: &sessions.SessionState{ - Email: "email1@example.com", - AccessToken: "my_access_token", - LifetimeDeadline: time.Now().Add(time.Duration(-24) * time.Hour), - RefreshDeadline: time.Now().Add(time.Duration(1) * time.Hour), - ValidDeadline: time.Now().Add(time.Duration(1) * time.Minute), + Email: "email1@example.com", + AuthorizedUpstream: "localhost", + AccessToken: "my_access_token", + LifetimeDeadline: time.Now().Add(time.Duration(-24) * time.Hour), + RefreshDeadline: time.Now().Add(time.Duration(1) * time.Hour), + ValidDeadline: time.Now().Add(time.Duration(1) * time.Minute), }, }, ExpectedErr: ErrLifetimeExpired, @@ -504,11 +508,12 @@ func TestAuthenticate(t *testing.T) { Name: "refresh expired, refresh fails, do not authenticate", SessionStore: &sessions.MockSessionStore{ Session: &sessions.SessionState{ - Email: "email1@example.com", - AccessToken: "my_access_token", - LifetimeDeadline: time.Now().Add(time.Duration(24) * time.Hour), - RefreshDeadline: time.Now().Add(time.Duration(-1) * time.Hour), - ValidDeadline: time.Now().Add(time.Duration(1) * time.Minute), + Email: "email1@example.com", + AuthorizedUpstream: "localhost", + AccessToken: "my_access_token", + LifetimeDeadline: time.Now().Add(time.Duration(24) * time.Hour), + RefreshDeadline: time.Now().Add(time.Duration(-1) * time.Hour), + ValidDeadline: time.Now().Add(time.Duration(1) * time.Minute), }, }, ExpectedErr: ErrRefreshFailed, @@ -519,11 +524,12 @@ func TestAuthenticate(t *testing.T) { Name: "refresh expired, user not OK, do not authenticate", SessionStore: &sessions.MockSessionStore{ Session: &sessions.SessionState{ - Email: "email1@example.com", - AccessToken: "my_access_token", - LifetimeDeadline: time.Now().Add(time.Duration(24) * time.Hour), - RefreshDeadline: time.Now().Add(time.Duration(-1) * time.Hour), - ValidDeadline: time.Now().Add(time.Duration(1) * time.Minute), + Email: "email1@example.com", + AuthorizedUpstream: "localhost", + AccessToken: "my_access_token", + LifetimeDeadline: time.Now().Add(time.Duration(24) * time.Hour), + RefreshDeadline: time.Now().Add(time.Duration(-1) * time.Hour), + ValidDeadline: time.Now().Add(time.Duration(1) * time.Minute), }, }, ExpectedErr: ErrUserNotAuthorized, @@ -534,11 +540,12 @@ func TestAuthenticate(t *testing.T) { Name: "refresh expired, user OK, authenticate", SessionStore: &sessions.MockSessionStore{ Session: &sessions.SessionState{ - Email: "email1@example.com", - AccessToken: "my_access_token", - LifetimeDeadline: time.Now().Add(time.Duration(24) * time.Hour), - RefreshDeadline: time.Now().Add(time.Duration(-1) * time.Hour), - ValidDeadline: time.Now().Add(time.Duration(1) * time.Minute), + Email: "email1@example.com", + AuthorizedUpstream: "localhost", + AccessToken: "my_access_token", + LifetimeDeadline: time.Now().Add(time.Duration(24) * time.Hour), + RefreshDeadline: time.Now().Add(time.Duration(-1) * time.Hour), + ValidDeadline: time.Now().Add(time.Duration(1) * time.Minute), }, }, ExpectedErr: nil, @@ -549,11 +556,12 @@ func TestAuthenticate(t *testing.T) { Name: "refresh expired, refresh and user OK, error saving session", SessionStore: &sessions.MockSessionStore{ Session: &sessions.SessionState{ - Email: "email1@example.com", - AccessToken: "my_access_token", - LifetimeDeadline: time.Now().Add(time.Duration(24) * time.Hour), - RefreshDeadline: time.Now().Add(time.Duration(-1) * time.Hour), - ValidDeadline: time.Now().Add(time.Duration(1) * time.Minute), + Email: "email1@example.com", + AuthorizedUpstream: "localhost", + AccessToken: "my_access_token", + LifetimeDeadline: time.Now().Add(time.Duration(24) * time.Hour), + RefreshDeadline: time.Now().Add(time.Duration(-1) * time.Hour), + ValidDeadline: time.Now().Add(time.Duration(1) * time.Minute), }, SaveError: SaveCookieFailed, }, @@ -565,11 +573,12 @@ func TestAuthenticate(t *testing.T) { Name: "validation expired, user not OK, do not authenticate", SessionStore: &sessions.MockSessionStore{ Session: &sessions.SessionState{ - Email: "email1@example.com", - AccessToken: "my_access_token", - LifetimeDeadline: time.Now().Add(time.Duration(24) * time.Hour), - RefreshDeadline: time.Now().Add(time.Duration(1) * time.Hour), - ValidDeadline: time.Now().Add(time.Duration(-1) * time.Minute), + Email: "email1@example.com", + AuthorizedUpstream: "localhost", + AccessToken: "my_access_token", + LifetimeDeadline: time.Now().Add(time.Duration(24) * time.Hour), + RefreshDeadline: time.Now().Add(time.Duration(1) * time.Hour), + ValidDeadline: time.Now().Add(time.Duration(-1) * time.Minute), }, }, ExpectedErr: ErrUserNotAuthorized, @@ -580,11 +589,12 @@ func TestAuthenticate(t *testing.T) { Name: "validation expired, user OK, authenticate", SessionStore: &sessions.MockSessionStore{ Session: &sessions.SessionState{ - Email: "email1@example.com", - AccessToken: "my_access_token", - LifetimeDeadline: time.Now().Add(time.Duration(24) * time.Hour), - RefreshDeadline: time.Now().Add(time.Duration(1) * time.Hour), - ValidDeadline: time.Now().Add(time.Duration(-1) * time.Minute), + Email: "email1@example.com", + AuthorizedUpstream: "localhost", + AccessToken: "my_access_token", + LifetimeDeadline: time.Now().Add(time.Duration(24) * time.Hour), + RefreshDeadline: time.Now().Add(time.Duration(1) * time.Hour), + ValidDeadline: time.Now().Add(time.Duration(-1) * time.Minute), }, }, ExpectedErr: nil, @@ -595,17 +605,33 @@ func TestAuthenticate(t *testing.T) { Name: "wrong identity provider, user OK, do not authenticate", SessionStore: &sessions.MockSessionStore{ Session: &sessions.SessionState{ - ProviderSlug: "example", - Email: "email1@example.com", - AccessToken: "my_access_token", - LifetimeDeadline: time.Now().Add(time.Duration(24) * time.Hour), - RefreshDeadline: time.Now().Add(time.Duration(1) * time.Hour), - ValidDeadline: time.Now().Add(time.Duration(1) * time.Minute), + ProviderSlug: "example", + Email: "email1@example.com", + AuthorizedUpstream: "localhost", + AccessToken: "my_access_token", + LifetimeDeadline: time.Now().Add(time.Duration(24) * time.Hour), + RefreshDeadline: time.Now().Add(time.Duration(1) * time.Hour), + ValidDeadline: time.Now().Add(time.Duration(1) * time.Minute), }, }, ExpectedErr: ErrWrongIdentityProvider, CookieExpectation: ClearCookie, }, + { + Name: "authorized against different upstream, user OK, do not authenticate", + SessionStore: &sessions.MockSessionStore{ + Session: &sessions.SessionState{ + Email: "email1@example.com", + AuthorizedUpstream: "foo", + AccessToken: "my_access_token", + LifetimeDeadline: time.Now().Add(time.Duration(24) * time.Hour), + RefreshDeadline: time.Now().Add(time.Duration(1) * time.Hour), + ValidDeadline: time.Now().Add(time.Duration(1) * time.Minute), + }, + }, + ExpectedErr: ErrUnauthorizedUpstreamRequested, + CookieExpectation: ClearCookie, + }, } for _, tc := range testCases { t.Run(tc.Name, func(t *testing.T) { @@ -662,8 +688,9 @@ func TestAuthenticationUXFlows(t *testing.T) { Name: "missing deadlines, redirect to sign-in", SessionStore: &sessions.MockSessionStore{ Session: &sessions.SessionState{ - Email: "email1@example.com", - AccessToken: "my_access_token", + Email: "email1@example.com", + AuthorizedUpstream: "localhost", + AccessToken: "my_access_token", }, }, ExpectStatusCode: http.StatusFound, @@ -680,11 +707,12 @@ func TestAuthenticationUXFlows(t *testing.T) { Name: "authenticate successfully, expect ok", SessionStore: &sessions.MockSessionStore{ Session: &sessions.SessionState{ - Email: "email1@example.com", - AccessToken: "my_access_token", - LifetimeDeadline: time.Now().Add(time.Duration(24) * time.Hour), - RefreshDeadline: time.Now().Add(time.Duration(1) * time.Hour), - ValidDeadline: time.Now().Add(time.Duration(1) * time.Minute), + Email: "email1@example.com", + AuthorizedUpstream: "localhost", + AccessToken: "my_access_token", + LifetimeDeadline: time.Now().Add(time.Duration(24) * time.Hour), + RefreshDeadline: time.Now().Add(time.Duration(1) * time.Hour), + ValidDeadline: time.Now().Add(time.Duration(1) * time.Minute), }, }, ExpectStatusCode: http.StatusOK, @@ -693,11 +721,12 @@ func TestAuthenticationUXFlows(t *testing.T) { Name: "lifetime expired, redirect to sign-in", SessionStore: &sessions.MockSessionStore{ Session: &sessions.SessionState{ - Email: "email1@example.com", - AccessToken: "my_access_token", - LifetimeDeadline: time.Now().Add(time.Duration(-24) * time.Hour), - RefreshDeadline: time.Now().Add(time.Duration(1) * time.Hour), - ValidDeadline: time.Now().Add(time.Duration(1) * time.Minute), + Email: "email1@example.com", + AuthorizedUpstream: "localhost", + AccessToken: "my_access_token", + LifetimeDeadline: time.Now().Add(time.Duration(-24) * time.Hour), + RefreshDeadline: time.Now().Add(time.Duration(1) * time.Hour), + ValidDeadline: time.Now().Add(time.Duration(1) * time.Minute), }, }, ExpectStatusCode: http.StatusFound, @@ -706,11 +735,12 @@ func TestAuthenticationUXFlows(t *testing.T) { Name: "refresh expired, refresh fails, show error", SessionStore: &sessions.MockSessionStore{ Session: &sessions.SessionState{ - Email: "email1@example.com", - AccessToken: "my_access_token", - LifetimeDeadline: time.Now().Add(time.Duration(24) * time.Hour), - RefreshDeadline: time.Now().Add(time.Duration(-1) * time.Hour), - ValidDeadline: time.Now().Add(time.Duration(1) * time.Minute), + Email: "email1@example.com", + AuthorizedUpstream: "localhost", + AccessToken: "my_access_token", + LifetimeDeadline: time.Now().Add(time.Duration(24) * time.Hour), + RefreshDeadline: time.Now().Add(time.Duration(-1) * time.Hour), + ValidDeadline: time.Now().Add(time.Duration(1) * time.Minute), }, }, RefreshSessionFunc: func(s *sessions.SessionState, g []string) (bool, error) { return false, ErrRefreshFailed }, @@ -720,11 +750,12 @@ func TestAuthenticationUXFlows(t *testing.T) { Name: "refresh expired, user not OK, deny", SessionStore: &sessions.MockSessionStore{ Session: &sessions.SessionState{ - Email: "email1@example.com", - AccessToken: "my_access_token", - LifetimeDeadline: time.Now().Add(time.Duration(24) * time.Hour), - RefreshDeadline: time.Now().Add(time.Duration(-1) * time.Hour), - ValidDeadline: time.Now().Add(time.Duration(1) * time.Minute), + Email: "email1@example.com", + AuthorizedUpstream: "localhost", + AccessToken: "my_access_token", + LifetimeDeadline: time.Now().Add(time.Duration(24) * time.Hour), + RefreshDeadline: time.Now().Add(time.Duration(-1) * time.Hour), + ValidDeadline: time.Now().Add(time.Duration(1) * time.Minute), }, }, RefreshSessionFunc: func(s *sessions.SessionState, g []string) (bool, error) { return false, nil }, @@ -734,11 +765,12 @@ func TestAuthenticationUXFlows(t *testing.T) { Name: "refresh expired, user OK, expect ok", SessionStore: &sessions.MockSessionStore{ Session: &sessions.SessionState{ - Email: "email1@example.com", - AccessToken: "my_access_token", - LifetimeDeadline: time.Now().Add(time.Duration(24) * time.Hour), - RefreshDeadline: time.Now().Add(time.Duration(-1) * time.Hour), - ValidDeadline: time.Now().Add(time.Duration(1) * time.Minute), + Email: "email1@example.com", + AuthorizedUpstream: "localhost", + AccessToken: "my_access_token", + LifetimeDeadline: time.Now().Add(time.Duration(24) * time.Hour), + RefreshDeadline: time.Now().Add(time.Duration(-1) * time.Hour), + ValidDeadline: time.Now().Add(time.Duration(1) * time.Minute), }, }, RefreshSessionFunc: func(s *sessions.SessionState, g []string) (bool, error) { return true, nil }, @@ -748,11 +780,12 @@ func TestAuthenticationUXFlows(t *testing.T) { Name: "refresh expired, refresh and user OK, error saving session, show error", SessionStore: &sessions.MockSessionStore{ Session: &sessions.SessionState{ - Email: "email1@example.com", - AccessToken: "my_access_token", - LifetimeDeadline: time.Now().Add(time.Duration(24) * time.Hour), - RefreshDeadline: time.Now().Add(time.Duration(-1) * time.Hour), - ValidDeadline: time.Now().Add(time.Duration(1) * time.Minute), + Email: "email1@example.com", + AuthorizedUpstream: "localhost", + AccessToken: "my_access_token", + LifetimeDeadline: time.Now().Add(time.Duration(24) * time.Hour), + RefreshDeadline: time.Now().Add(time.Duration(-1) * time.Hour), + ValidDeadline: time.Now().Add(time.Duration(1) * time.Minute), }, SaveError: SaveCookieFailed, }, @@ -763,11 +796,12 @@ func TestAuthenticationUXFlows(t *testing.T) { Name: "validation expired, user not OK, deny", SessionStore: &sessions.MockSessionStore{ Session: &sessions.SessionState{ - Email: "email1@example.com", - AccessToken: "my_access_token", - LifetimeDeadline: time.Now().Add(time.Duration(24) * time.Hour), - RefreshDeadline: time.Now().Add(time.Duration(1) * time.Hour), - ValidDeadline: time.Now().Add(time.Duration(-1) * time.Minute), + Email: "email1@example.com", + AuthorizedUpstream: "localhost", + AccessToken: "my_access_token", + LifetimeDeadline: time.Now().Add(time.Duration(24) * time.Hour), + RefreshDeadline: time.Now().Add(time.Duration(1) * time.Hour), + ValidDeadline: time.Now().Add(time.Duration(-1) * time.Minute), }, }, ValidateSessionFunc: func(s *sessions.SessionState, g []string) bool { return false }, @@ -777,11 +811,12 @@ func TestAuthenticationUXFlows(t *testing.T) { Name: "validation expired, user OK, expect ok", SessionStore: &sessions.MockSessionStore{ Session: &sessions.SessionState{ - Email: "email1@example.com", - AccessToken: "my_access_token", - LifetimeDeadline: time.Now().Add(time.Duration(24) * time.Hour), - RefreshDeadline: time.Now().Add(time.Duration(1) * time.Hour), - ValidDeadline: time.Now().Add(time.Duration(-1) * time.Minute), + Email: "email1@example.com", + AuthorizedUpstream: "localhost", + AccessToken: "my_access_token", + LifetimeDeadline: time.Now().Add(time.Duration(24) * time.Hour), + RefreshDeadline: time.Now().Add(time.Duration(1) * time.Hour), + ValidDeadline: time.Now().Add(time.Duration(-1) * time.Minute), }, }, ValidateSessionFunc: func(s *sessions.SessionState, g []string) bool { return true }, @@ -791,12 +826,27 @@ func TestAuthenticationUXFlows(t *testing.T) { Name: "wrong identity provider, redirect to sign-in", SessionStore: &sessions.MockSessionStore{ Session: &sessions.SessionState{ - ProviderSlug: "example", - Email: "email1@example.com", - AccessToken: "my_access_token", - LifetimeDeadline: time.Now().Add(time.Duration(24) * time.Hour), - RefreshDeadline: time.Now().Add(time.Duration(1) * time.Hour), - ValidDeadline: time.Now().Add(time.Duration(1) * time.Minute), + ProviderSlug: "example", + Email: "email1@example.com", + AuthorizedUpstream: "localhost", + AccessToken: "my_access_token", + LifetimeDeadline: time.Now().Add(time.Duration(24) * time.Hour), + RefreshDeadline: time.Now().Add(time.Duration(1) * time.Hour), + ValidDeadline: time.Now().Add(time.Duration(1) * time.Minute), + }, + }, + ExpectStatusCode: http.StatusFound, + }, + { + Name: "authorized against different upstream, redirect to sign-in", + SessionStore: &sessions.MockSessionStore{ + Session: &sessions.SessionState{ + Email: "email1@example.com", + AuthorizedUpstream: "foo", + AccessToken: "my_access_token", + LifetimeDeadline: time.Now().Add(time.Duration(24) * time.Hour), + RefreshDeadline: time.Now().Add(time.Duration(1) * time.Hour), + ValidDeadline: time.Now().Add(time.Duration(1) * time.Minute), }, }, ExpectStatusCode: http.StatusFound, @@ -842,7 +892,8 @@ func TestProxyXHRErrorHandling(t *testing.T) { { Name: "expired session should redirect on normal request (GET)", Session: &sessions.SessionState{ - LifetimeDeadline: time.Now().Add(time.Duration(-24) * time.Hour), + LifetimeDeadline: time.Now().Add(time.Duration(-24) * time.Hour), + AuthorizedUpstream: "localhost", }, Method: "GET", ExpectedCode: http.StatusFound, @@ -850,7 +901,8 @@ func TestProxyXHRErrorHandling(t *testing.T) { { Name: "expired session should proxy preflight request (OPTIONS)", Session: &sessions.SessionState{ - LifetimeDeadline: time.Now().Add(time.Duration(-24) * time.Hour), + LifetimeDeadline: time.Now().Add(time.Duration(-24) * time.Hour), + AuthorizedUpstream: "localhost", }, Method: "OPTIONS", ExpectedCode: http.StatusFound, @@ -858,7 +910,8 @@ func TestProxyXHRErrorHandling(t *testing.T) { { Name: "expired session should return error code when XMLHttpRequest", Session: &sessions.SessionState{ - LifetimeDeadline: time.Now().Add(time.Duration(-24) * time.Hour), + LifetimeDeadline: time.Now().Add(time.Duration(-24) * time.Hour), + AuthorizedUpstream: "localhost", }, Method: "GET", Header: map[string]string{ @@ -878,9 +931,10 @@ func TestProxyXHRErrorHandling(t *testing.T) { { Name: "valid session should proxy as normal when XMLHttpRequest", Session: &sessions.SessionState{ - LifetimeDeadline: time.Now().Add(time.Duration(1) * time.Hour), - RefreshDeadline: time.Now().Add(time.Duration(1) * time.Hour), - ValidDeadline: time.Now().Add(time.Duration(1) * time.Hour), + LifetimeDeadline: time.Now().Add(time.Duration(1) * time.Hour), + RefreshDeadline: time.Now().Add(time.Duration(1) * time.Hour), + ValidDeadline: time.Now().Add(time.Duration(1) * time.Hour), + AuthorizedUpstream: "localhost", }, Method: "GET", Header: map[string]string{