Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion internal/outpost/proxyv2/application/oauth_state.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,15 @@ func (a *Application) checkRedirectParam(r *http.Request) (string, bool) {
func (a *Application) createState(r *http.Request, w http.ResponseWriter, fwd string) (string, error) {
s, err := a.sessions.Get(r, a.SessionName())
if err != nil {
return "", fmt.Errorf("failed to get session: %w", err)
// Session file may not exist (e.g., after outpost restart or logout)
// Delete the stale session cookie and continue with the new empty session
a.log.WithError(err).Debug("failed to get session, clearing stale cookie")
s.Options.MaxAge = -1
if saveErr := s.Save(r, w); saveErr != nil {
a.log.WithError(saveErr).Warning("failed to delete stale session cookie")
}
// Get a fresh session after clearing the stale cookie
s, _ = a.sessions.Get(r, a.SessionName())
}
if s.ID == "" {
// Ensure session has an ID
Expand Down
36 changes: 36 additions & 0 deletions internal/outpost/proxyv2/application/session_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -154,3 +154,39 @@ func TestStateFromRequestDeletesStaleCookie(t *testing.T) {
}
assert.True(t, foundDeleteCookie, "Expected stale session cookie to be deleted")
}

func TestCreateStateWithStaleCookie(t *testing.T) {
a := newTestApplication()
_ = a.configureProxy()

// Create a request with a stale session cookie (simulates outpost restart or user change)
req, _ := http.NewRequest("GET", "https://ext.t.goauthentik.io/outpost.goauthentik.io/start", nil)

// Add a cookie for a non-existent session
nonExistentSessionID := uuid.New().String()
req.AddCookie(&http.Cookie{
Name: a.SessionName(),
Value: "encoded_session_data_" + nonExistentSessionID,
Path: "/",
})

rr := httptest.NewRecorder()

// Call createState which should succeed despite the stale cookie
state, err := a.createState(req, rr, "/redirect")

// Verify createState succeeded
assert.NoError(t, err)
assert.NotEmpty(t, state)

// Verify the response includes a Set-Cookie header to delete the stale cookie
cookies := rr.Result().Cookies()
var foundDeleteCookie bool
for _, cookie := range cookies {
if cookie.Name == a.SessionName() && cookie.MaxAge < 0 {
foundDeleteCookie = true
break
}
}
assert.True(t, foundDeleteCookie, "Expected stale session cookie to be deleted")
}
Loading