Skip to content

Commit 47085c9

Browse files
authored
Merge pull request #4015 from appare45/set-cookie-with-baseurl
backend: auth: Include baseURL in Cookie Path
2 parents 8fb1424 + 7647546 commit 47085c9

File tree

3 files changed

+66
-13
lines changed

3 files changed

+66
-13
lines changed

backend/cmd/headlamp.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -755,7 +755,7 @@ func createHeadlampHandler(config *HeadlampConfig) http.Handler {
755755
}
756756

757757
// Set auth cookie
758-
auth.SetTokenCookie(w, r, string(decodedState), rawUserToken)
758+
auth.SetTokenCookie(w, r, string(decodedState), rawUserToken, config.BaseURL)
759759

760760
redirectURL += fmt.Sprintf("auth?cluster=%1s", decodedState)
761761
http.Redirect(w, r, redirectURL, http.StatusSeeOther)
@@ -841,7 +841,7 @@ func (c *HeadlampConfig) refreshAndSetToken(oidcAuthConfig *kubeconfig.OidcConfi
841841
}
842842

843843
// Set refreshed token in cookie
844-
auth.SetTokenCookie(w, r, cluster, newTokenString)
844+
auth.SetTokenCookie(w, r, cluster, newTokenString, c.BaseURL)
845845

846846
c.telemetryHandler.RecordEvent(span, "Token refreshed successfully")
847847
}
@@ -2333,9 +2333,9 @@ func (c *HeadlampConfig) handleSetToken(w http.ResponseWriter, r *http.Request)
23332333
}
23342334

23352335
if req.Token == "" {
2336-
auth.ClearTokenCookie(w, r, cluster)
2336+
auth.ClearTokenCookie(w, r, cluster, c.BaseURL)
23372337
} else {
2338-
auth.SetTokenCookie(w, r, cluster, req.Token)
2338+
auth.SetTokenCookie(w, r, cluster, req.Token, c.BaseURL)
23392339
}
23402340

23412341
w.WriteHeader(http.StatusOK)

backend/pkg/auth/cookies.go

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,16 @@ const (
2929
chunkSize = 3800
3030
)
3131

32+
// GetCookiePath returns the full cookie path including baseURL.
33+
func GetCookiePath(baseURL, cluster string) string {
34+
if baseURL != "" {
35+
baseURL = "/" + strings.Trim(baseURL, "/")
36+
return baseURL + "/clusters/" + cluster
37+
}
38+
39+
return "/clusters/" + cluster
40+
}
41+
3242
// SanitizeClusterName ensures cluster names are safe for use in cookie names.
3343
func SanitizeClusterName(cluster string) string {
3444
// Only allow alphanumeric characters, hyphens, and underscores
@@ -65,7 +75,7 @@ func IsSecureContext(r *http.Request) bool {
6575
}
6676

6777
// SetTokenCookie sets an authentication cookie for a specific cluster.
68-
func SetTokenCookie(w http.ResponseWriter, r *http.Request, cluster, token string) {
78+
func SetTokenCookie(w http.ResponseWriter, r *http.Request, cluster, token, baseURL string) {
6979
// Validate inputs
7080
if cluster == "" || token == "" {
7181
return
@@ -77,7 +87,7 @@ func SetTokenCookie(w http.ResponseWriter, r *http.Request, cluster, token strin
7787
}
7888

7989
// Clear any existing cookies
80-
ClearTokenCookie(w, r, cluster)
90+
ClearTokenCookie(w, r, cluster, baseURL)
8191

8292
secure := IsSecureContext(r)
8393

@@ -90,7 +100,7 @@ func SetTokenCookie(w http.ResponseWriter, r *http.Request, cluster, token strin
90100
HttpOnly: true,
91101
Secure: secure,
92102
SameSite: http.SameSiteStrictMode,
93-
Path: "/clusters/" + cluster,
103+
Path: GetCookiePath(baseURL, cluster),
94104
MaxAge: 86400, // 24 hours
95105
}
96106

@@ -125,7 +135,7 @@ func GetTokenFromCookie(r *http.Request, cluster string) (string, error) {
125135
}
126136

127137
// ClearTokenCookie clears an authentication cookie for a specific cluster.
128-
func ClearTokenCookie(w http.ResponseWriter, r *http.Request, cluster string) {
138+
func ClearTokenCookie(w http.ResponseWriter, r *http.Request, cluster, baseURL string) {
129139
sanitizedCluster := SanitizeClusterName(cluster)
130140
if sanitizedCluster == "" {
131141
return
@@ -149,7 +159,7 @@ func ClearTokenCookie(w http.ResponseWriter, r *http.Request, cluster string) {
149159
HttpOnly: true,
150160
Secure: secure,
151161
SameSite: http.SameSiteStrictMode,
152-
Path: "/clusters/" + cluster,
162+
Path: GetCookiePath(baseURL, cluster),
153163
MaxAge: -1,
154164
}
155165
http.SetCookie(w, cookie)

backend/pkg/auth/cookies_test.go

Lines changed: 47 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -117,13 +117,56 @@ func TestIsSecureContext(t *testing.T) {
117117
}
118118
}
119119

120+
func TestGetCookiePath(t *testing.T) {
121+
tests := []struct {
122+
name string
123+
baseURL string
124+
cluster string
125+
wantPath string
126+
}{
127+
{
128+
name: "empty base URL",
129+
baseURL: "",
130+
cluster: "test-cluster",
131+
wantPath: "/clusters/test-cluster",
132+
},
133+
{
134+
name: "base URL without leading slash",
135+
baseURL: "headlamp",
136+
cluster: "test-cluster",
137+
wantPath: "/headlamp/clusters/test-cluster",
138+
},
139+
{
140+
name: "base URL with leading slash",
141+
baseURL: "/headlamp",
142+
cluster: "test-cluster",
143+
wantPath: "/headlamp/clusters/test-cluster",
144+
},
145+
{
146+
name: "base URL with trailing slash",
147+
baseURL: "/headlamp/",
148+
cluster: "test-cluster",
149+
wantPath: "/headlamp/clusters/test-cluster",
150+
},
151+
}
152+
153+
for _, tt := range tests {
154+
t.Run(tt.name, func(t *testing.T) {
155+
got := auth.GetCookiePath(tt.baseURL, tt.cluster)
156+
if got != tt.wantPath {
157+
t.Errorf("getCookiePath() = %q, want %q", got, tt.wantPath)
158+
}
159+
})
160+
}
161+
}
162+
120163
func TestSetAndGetAuthCookie(t *testing.T) {
121164
req := httptest.NewRequest("GET", localhost, nil)
122165
req.Host = localhost
123166
w := httptest.NewRecorder()
124167

125168
// Test setting a cookie
126-
auth.SetTokenCookie(w, req, "test-cluster", "test-token")
169+
auth.SetTokenCookie(w, req, "test-cluster", "test-token", "")
127170

128171
// Check if cookie was set
129172
cookies := w.Result().Cookies()
@@ -170,7 +213,7 @@ func TestGetAuthCookieChunked(t *testing.T) {
170213
longToken := strings.Repeat("a", 5000)
171214

172215
// Test setting a cookie
173-
auth.SetTokenCookie(w, req, "test-cluster", longToken)
216+
auth.SetTokenCookie(w, req, "test-cluster", longToken, "")
174217

175218
// Check if cookie was set
176219
cookies := w.Result().Cookies()
@@ -209,7 +252,7 @@ func TestClearAuthCookie(t *testing.T) {
209252
})
210253

211254
// Clear a cookie
212-
auth.ClearTokenCookie(w, req, "test-cluster")
255+
auth.ClearTokenCookie(w, req, "test-cluster", "")
213256

214257
// Check if cookie was set
215258
cookies := w.Result().Cookies()
@@ -218,7 +261,7 @@ func TestClearAuthCookie(t *testing.T) {
218261
}
219262

220263
// Test clearing the cookie
221-
auth.ClearTokenCookie(w, req, "test-cluster")
264+
auth.ClearTokenCookie(w, req, "test-cluster", "")
222265

223266
// Check if cookie was cleared
224267
clearedCookies := w.Result().Cookies()

0 commit comments

Comments
 (0)