Skip to content

Commit 1b225e0

Browse files
authored
fix: broken STS Sessions with large policies (#1096)
Signed-off-by: Daniel Valdivia <18384552+dvaldivia@users.noreply.github.com>
1 parent 7a864d2 commit 1b225e0

File tree

7 files changed

+108
-29
lines changed

7 files changed

+108
-29
lines changed

operatorapi/operator_login.go

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -55,8 +55,10 @@ func registerLoginHandlers(api *operations.OperatorAPI) {
5555
}
5656
// Custom response writer to set the session cookies
5757
return middleware.ResponderFunc(func(w http.ResponseWriter, p runtime.Producer) {
58-
cookie := restapi.NewSessionCookieForConsole(loginResponse.SessionID)
59-
http.SetCookie(w, &cookie)
58+
cookies := restapi.NewSessionCookieForConsole(loginResponse.SessionID)
59+
for _, cookie := range cookies {
60+
http.SetCookie(w, &cookie)
61+
}
6062
user_api.NewLoginCreated().WithPayload(loginResponse).WriteResponse(w, p)
6163
})
6264
})
@@ -67,8 +69,10 @@ func registerLoginHandlers(api *operations.OperatorAPI) {
6769
}
6870
// Custom response writer to set the session cookies
6971
return middleware.ResponderFunc(func(w http.ResponseWriter, p runtime.Producer) {
70-
cookie := restapi.NewSessionCookieForConsole(loginResponse.SessionID)
71-
http.SetCookie(w, &cookie)
72+
cookies := restapi.NewSessionCookieForConsole(loginResponse.SessionID)
73+
for _, cookie := range cookies {
74+
http.SetCookie(w, &cookie)
75+
}
7276
user_api.NewLoginOauth2AuthCreated().WithPayload(loginResponse).WriteResponse(w, p)
7377
})
7478
})
@@ -79,8 +83,10 @@ func registerLoginHandlers(api *operations.OperatorAPI) {
7983
}
8084
// Custom response writer to set the session cookies
8185
return middleware.ResponderFunc(func(w http.ResponseWriter, p runtime.Producer) {
82-
cookie := restapi.NewSessionCookieForConsole(loginResponse.SessionID)
83-
http.SetCookie(w, &cookie)
86+
cookies := restapi.NewSessionCookieForConsole(loginResponse.SessionID)
87+
for _, cookie := range cookies {
88+
http.SetCookie(w, &cookie)
89+
}
8490
user_api.NewLoginOperatorCreated().WithPayload(loginResponse).WriteResponse(w, p)
8591
})
8692
})

pkg/auth/token.go

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -287,6 +287,7 @@ func decrypt(ciphertext []byte, associatedData []byte) ([]byte, error) {
287287
func GetTokenFromRequest(r *http.Request) (string, error) {
288288
// Token might come either as a Cookie or as a Header
289289
// if not set in cookie, check if it is set on Header.
290+
290291
tokenCookie, err := r.Cookie("token")
291292
if err != nil {
292293
return "", ErrNoAuthToken
@@ -295,7 +296,16 @@ func GetTokenFromRequest(r *http.Request) (string, error) {
295296
if tokenCookie.Expires.After(currentTime) {
296297
return "", errTokenExpired
297298
}
298-
return strings.TrimSpace(tokenCookie.Value), nil
299+
300+
mergeToken := strings.TrimSpace(tokenCookie.Value)
301+
for _, cookie := range r.Cookies() {
302+
if cookie.Name != "token" && strings.HasPrefix(cookie.Name, "token") {
303+
mergeToken = fmt.Sprintf("%s%s", mergeToken, strings.TrimSpace(cookie.Value))
304+
}
305+
}
306+
307+
return mergeToken, nil
308+
299309
}
300310

301311
func GetClaimsFromTokenInRequest(req *http.Request) (*models.Principal, error) {

portal-ui/src/common/utils.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,9 @@ export const deleteCookie = (name: string) => {
7676
export const clearSession = () => {
7777
storage.removeItem("token");
7878
deleteCookie("token");
79+
for (let i = 1; i < 10; i++) {
80+
deleteCookie(`token${i}`);
81+
}
7982
};
8083

8184
// timeFromDate gets time string from date input

portal-ui/src/screens/Console/Common/ModalWrapper/ModalWrapper.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@ const ModalWrapper = ({
136136
return;
137137
}
138138
// Open SnackBar
139-
if(modalSnackMessage.type !== "error") {
139+
if (modalSnackMessage.type !== "error") {
140140
setOpenSnackbar(true);
141141
}
142142
}

restapi/user_account.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,10 @@ func registerAccountHandlers(api *operations.ConsoleAPI) {
3939
}
4040
// Custom response writer to update the session cookies
4141
return middleware.ResponderFunc(func(w http.ResponseWriter, p runtime.Producer) {
42-
cookie := NewSessionCookieForConsole(changePasswordResponse.SessionID)
43-
http.SetCookie(w, &cookie)
42+
cookies := NewSessionCookieForConsole(changePasswordResponse.SessionID)
43+
for _, cookie := range cookies {
44+
http.SetCookie(w, &cookie)
45+
}
4446
user_api.NewLoginCreated().WithPayload(changePasswordResponse).WriteResponse(w, p)
4547
})
4648
})

restapi/user_login.go

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -53,8 +53,10 @@ func registerLoginHandlers(api *operations.ConsoleAPI) {
5353
}
5454
// Custom response writer to set the session cookies
5555
return middleware.ResponderFunc(func(w http.ResponseWriter, p runtime.Producer) {
56-
cookie := NewSessionCookieForConsole(loginResponse.SessionID)
57-
http.SetCookie(w, &cookie)
56+
cookies := NewSessionCookieForConsole(loginResponse.SessionID)
57+
for _, cookie := range cookies {
58+
http.SetCookie(w, &cookie)
59+
}
5860
user_api.NewLoginCreated().WithPayload(loginResponse).WriteResponse(w, p)
5961
})
6062
})
@@ -65,8 +67,10 @@ func registerLoginHandlers(api *operations.ConsoleAPI) {
6567
}
6668
// Custom response writer to set the session cookies
6769
return middleware.ResponderFunc(func(w http.ResponseWriter, p runtime.Producer) {
68-
cookie := NewSessionCookieForConsole(loginResponse.SessionID)
69-
http.SetCookie(w, &cookie)
70+
cookies := NewSessionCookieForConsole(loginResponse.SessionID)
71+
for _, cookie := range cookies {
72+
http.SetCookie(w, &cookie)
73+
}
7074
user_api.NewLoginOauth2AuthCreated().WithPayload(loginResponse).WriteResponse(w, p)
7175
})
7276
})
@@ -77,8 +81,10 @@ func registerLoginHandlers(api *operations.ConsoleAPI) {
7781
}
7882
// Custom response writer to set the session cookies
7983
return middleware.ResponderFunc(func(w http.ResponseWriter, p runtime.Producer) {
80-
cookie := NewSessionCookieForConsole(loginResponse.SessionID)
81-
http.SetCookie(w, &cookie)
84+
cookies := NewSessionCookieForConsole(loginResponse.SessionID)
85+
for _, cookie := range cookies {
86+
http.SetCookie(w, &cookie)
87+
}
8288
user_api.NewLoginOperatorCreated().WithPayload(loginResponse).WriteResponse(w, p)
8389
})
8490
})

restapi/utils.go

Lines changed: 65 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ package restapi
1818

1919
import (
2020
"crypto/rand"
21+
"fmt"
2122
"io"
2223
"net/http"
2324
"os"
@@ -105,22 +106,73 @@ func FileExists(filename string) bool {
105106
return !info.IsDir()
106107
}
107108

108-
func NewSessionCookieForConsole(token string) http.Cookie {
109+
func NewSessionCookieForConsole(token string) []http.Cookie {
110+
const CookieChunk = 3800
111+
109112
expiration := time.Now().Add(SessionDuration)
113+
var cookies []http.Cookie
110114

111-
return http.Cookie{
112-
Path: "/",
113-
Name: "token",
114-
Value: token,
115-
MaxAge: int(SessionDuration.Seconds()), // 45 minutes
116-
Expires: expiration,
117-
HttpOnly: true,
118-
// if len(GlobalPublicCerts) > 0 is true, that means Console is running with TLS enable and the browser
119-
// should not leak any cookie if we access the site using HTTP
120-
Secure: len(GlobalPublicCerts) > 0,
121-
// read more: https://web.dev/samesite-cookies-explained/
122-
SameSite: http.SameSiteLaxMode,
115+
i := 0
116+
cookieIndex := 0
117+
118+
for i < len(token) {
119+
var until int
120+
if i+CookieChunk < len(token) {
121+
until = i + CookieChunk
122+
} else {
123+
until = len(token)
124+
}
125+
126+
cookieName := "token"
127+
if len(cookies) > 0 {
128+
cookieName = fmt.Sprintf("token%d", len(cookies))
129+
}
130+
131+
cookie := http.Cookie{
132+
Path: "/",
133+
Name: cookieName,
134+
Value: token[i:until],
135+
MaxAge: int(SessionDuration.Seconds()), // 45 minutes
136+
Expires: expiration,
137+
HttpOnly: true,
138+
// if len(GlobalPublicCerts) > 0 is true, that means Console is running with TLS enable and the browser
139+
// should not leak any cookie if we access the site using HTTP
140+
Secure: len(GlobalPublicCerts) > 0,
141+
// read more: https://web.dev/samesite-cookies-explained/
142+
SameSite: http.SameSiteLaxMode,
143+
}
144+
145+
cookies = append(cookies, cookie)
146+
i += until
147+
cookieIndex++
148+
}
149+
150+
// clear old cookies
151+
expiredDuration := time.Now().Add(-1 * time.Second)
152+
for i := cookieIndex; i < 10; i++ {
153+
cookieName := "token"
154+
if len(cookies) > 0 {
155+
cookieName = fmt.Sprintf("token%d", i)
156+
}
157+
158+
cookie := http.Cookie{
159+
Path: "/",
160+
Name: cookieName,
161+
Value: "",
162+
MaxAge: 0, // 45 minutes
163+
Expires: expiredDuration,
164+
HttpOnly: true,
165+
// if len(GlobalPublicCerts) > 0 is true, that means Console is running with TLS enable and the browser
166+
// should not leak any cookie if we access the site using HTTP
167+
Secure: len(GlobalPublicCerts) > 0,
168+
// read more: https://web.dev/samesite-cookies-explained/
169+
SameSite: http.SameSiteLaxMode,
170+
}
171+
172+
cookies = append(cookies, cookie)
123173
}
174+
175+
return cookies
124176
}
125177

126178
func ExpireSessionCookie() http.Cookie {

0 commit comments

Comments
 (0)