fix: broken STS Sessions with large policies (#1096)

Signed-off-by: Daniel Valdivia <18384552+dvaldivia@users.noreply.github.com>
This commit is contained in:
Daniel Valdivia
2021-10-04 14:25:00 -07:00
committed by GitHub
parent 7a864d2631
commit 1b225e0901
7 changed files with 109 additions and 30 deletions

View File

@@ -55,8 +55,10 @@ func registerLoginHandlers(api *operations.OperatorAPI) {
}
// Custom response writer to set the session cookies
return middleware.ResponderFunc(func(w http.ResponseWriter, p runtime.Producer) {
cookie := restapi.NewSessionCookieForConsole(loginResponse.SessionID)
http.SetCookie(w, &cookie)
cookies := restapi.NewSessionCookieForConsole(loginResponse.SessionID)
for _, cookie := range cookies {
http.SetCookie(w, &cookie)
}
user_api.NewLoginCreated().WithPayload(loginResponse).WriteResponse(w, p)
})
})
@@ -67,8 +69,10 @@ func registerLoginHandlers(api *operations.OperatorAPI) {
}
// Custom response writer to set the session cookies
return middleware.ResponderFunc(func(w http.ResponseWriter, p runtime.Producer) {
cookie := restapi.NewSessionCookieForConsole(loginResponse.SessionID)
http.SetCookie(w, &cookie)
cookies := restapi.NewSessionCookieForConsole(loginResponse.SessionID)
for _, cookie := range cookies {
http.SetCookie(w, &cookie)
}
user_api.NewLoginOauth2AuthCreated().WithPayload(loginResponse).WriteResponse(w, p)
})
})
@@ -79,8 +83,10 @@ func registerLoginHandlers(api *operations.OperatorAPI) {
}
// Custom response writer to set the session cookies
return middleware.ResponderFunc(func(w http.ResponseWriter, p runtime.Producer) {
cookie := restapi.NewSessionCookieForConsole(loginResponse.SessionID)
http.SetCookie(w, &cookie)
cookies := restapi.NewSessionCookieForConsole(loginResponse.SessionID)
for _, cookie := range cookies {
http.SetCookie(w, &cookie)
}
user_api.NewLoginOperatorCreated().WithPayload(loginResponse).WriteResponse(w, p)
})
})

View File

@@ -287,6 +287,7 @@ func decrypt(ciphertext []byte, associatedData []byte) ([]byte, error) {
func GetTokenFromRequest(r *http.Request) (string, error) {
// Token might come either as a Cookie or as a Header
// if not set in cookie, check if it is set on Header.
tokenCookie, err := r.Cookie("token")
if err != nil {
return "", ErrNoAuthToken
@@ -295,7 +296,16 @@ func GetTokenFromRequest(r *http.Request) (string, error) {
if tokenCookie.Expires.After(currentTime) {
return "", errTokenExpired
}
return strings.TrimSpace(tokenCookie.Value), nil
mergeToken := strings.TrimSpace(tokenCookie.Value)
for _, cookie := range r.Cookies() {
if cookie.Name != "token" && strings.HasPrefix(cookie.Name, "token") {
mergeToken = fmt.Sprintf("%s%s", mergeToken, strings.TrimSpace(cookie.Value))
}
}
return mergeToken, nil
}
func GetClaimsFromTokenInRequest(req *http.Request) (*models.Principal, error) {

View File

@@ -76,6 +76,9 @@ export const deleteCookie = (name: string) => {
export const clearSession = () => {
storage.removeItem("token");
deleteCookie("token");
for (let i = 1; i < 10; i++) {
deleteCookie(`token${i}`);
}
};
// timeFromDate gets time string from date input

View File

@@ -136,7 +136,7 @@ const ModalWrapper = ({
return;
}
// Open SnackBar
if(modalSnackMessage.type !== "error") {
if (modalSnackMessage.type !== "error") {
setOpenSnackbar(true);
}
}

View File

@@ -39,8 +39,10 @@ func registerAccountHandlers(api *operations.ConsoleAPI) {
}
// Custom response writer to update the session cookies
return middleware.ResponderFunc(func(w http.ResponseWriter, p runtime.Producer) {
cookie := NewSessionCookieForConsole(changePasswordResponse.SessionID)
http.SetCookie(w, &cookie)
cookies := NewSessionCookieForConsole(changePasswordResponse.SessionID)
for _, cookie := range cookies {
http.SetCookie(w, &cookie)
}
user_api.NewLoginCreated().WithPayload(changePasswordResponse).WriteResponse(w, p)
})
})

View File

@@ -53,8 +53,10 @@ func registerLoginHandlers(api *operations.ConsoleAPI) {
}
// Custom response writer to set the session cookies
return middleware.ResponderFunc(func(w http.ResponseWriter, p runtime.Producer) {
cookie := NewSessionCookieForConsole(loginResponse.SessionID)
http.SetCookie(w, &cookie)
cookies := NewSessionCookieForConsole(loginResponse.SessionID)
for _, cookie := range cookies {
http.SetCookie(w, &cookie)
}
user_api.NewLoginCreated().WithPayload(loginResponse).WriteResponse(w, p)
})
})
@@ -65,8 +67,10 @@ func registerLoginHandlers(api *operations.ConsoleAPI) {
}
// Custom response writer to set the session cookies
return middleware.ResponderFunc(func(w http.ResponseWriter, p runtime.Producer) {
cookie := NewSessionCookieForConsole(loginResponse.SessionID)
http.SetCookie(w, &cookie)
cookies := NewSessionCookieForConsole(loginResponse.SessionID)
for _, cookie := range cookies {
http.SetCookie(w, &cookie)
}
user_api.NewLoginOauth2AuthCreated().WithPayload(loginResponse).WriteResponse(w, p)
})
})
@@ -77,8 +81,10 @@ func registerLoginHandlers(api *operations.ConsoleAPI) {
}
// Custom response writer to set the session cookies
return middleware.ResponderFunc(func(w http.ResponseWriter, p runtime.Producer) {
cookie := NewSessionCookieForConsole(loginResponse.SessionID)
http.SetCookie(w, &cookie)
cookies := NewSessionCookieForConsole(loginResponse.SessionID)
for _, cookie := range cookies {
http.SetCookie(w, &cookie)
}
user_api.NewLoginOperatorCreated().WithPayload(loginResponse).WriteResponse(w, p)
})
})

View File

@@ -18,6 +18,7 @@ package restapi
import (
"crypto/rand"
"fmt"
"io"
"net/http"
"os"
@@ -105,22 +106,73 @@ func FileExists(filename string) bool {
return !info.IsDir()
}
func NewSessionCookieForConsole(token string) http.Cookie {
expiration := time.Now().Add(SessionDuration)
func NewSessionCookieForConsole(token string) []http.Cookie {
const CookieChunk = 3800
return http.Cookie{
Path: "/",
Name: "token",
Value: token,
MaxAge: int(SessionDuration.Seconds()), // 45 minutes
Expires: expiration,
HttpOnly: true,
// if len(GlobalPublicCerts) > 0 is true, that means Console is running with TLS enable and the browser
// should not leak any cookie if we access the site using HTTP
Secure: len(GlobalPublicCerts) > 0,
// read more: https://web.dev/samesite-cookies-explained/
SameSite: http.SameSiteLaxMode,
expiration := time.Now().Add(SessionDuration)
var cookies []http.Cookie
i := 0
cookieIndex := 0
for i < len(token) {
var until int
if i+CookieChunk < len(token) {
until = i + CookieChunk
} else {
until = len(token)
}
cookieName := "token"
if len(cookies) > 0 {
cookieName = fmt.Sprintf("token%d", len(cookies))
}
cookie := http.Cookie{
Path: "/",
Name: cookieName,
Value: token[i:until],
MaxAge: int(SessionDuration.Seconds()), // 45 minutes
Expires: expiration,
HttpOnly: true,
// if len(GlobalPublicCerts) > 0 is true, that means Console is running with TLS enable and the browser
// should not leak any cookie if we access the site using HTTP
Secure: len(GlobalPublicCerts) > 0,
// read more: https://web.dev/samesite-cookies-explained/
SameSite: http.SameSiteLaxMode,
}
cookies = append(cookies, cookie)
i += until
cookieIndex++
}
// clear old cookies
expiredDuration := time.Now().Add(-1 * time.Second)
for i := cookieIndex; i < 10; i++ {
cookieName := "token"
if len(cookies) > 0 {
cookieName = fmt.Sprintf("token%d", i)
}
cookie := http.Cookie{
Path: "/",
Name: cookieName,
Value: "",
MaxAge: 0, // 45 minutes
Expires: expiredDuration,
HttpOnly: true,
// if len(GlobalPublicCerts) > 0 is true, that means Console is running with TLS enable and the browser
// should not leak any cookie if we access the site using HTTP
Secure: len(GlobalPublicCerts) > 0,
// read more: https://web.dev/samesite-cookies-explained/
SameSite: http.SameSiteLaxMode,
}
cookies = append(cookies, cookie)
}
return cookies
}
func ExpireSessionCookie() http.Cookie {