fix (cookie): sso cookie issue on safari

whenever using an iframe, cookies are a problem in cross domain setup as
browser like safari got that disabled entirely. We had to find a
solution to work with Safari properly, hence passing the data through
URL
This commit is contained in:
MickaelK 2024-09-07 01:57:28 +10:00
parent 59d0ba0fd4
commit fe736b755d
2 changed files with 43 additions and 33 deletions

View file

@ -241,15 +241,13 @@ func SessionAuthMiddleware(ctx *App, res http.ResponseWriter, req *http.Request)
return
}
formData := map[string]string{}
switch req.Method {
case "GET":
for key, element := range _get {
if len(element) == 0 {
continue
}
formData[key] = element[0]
for key, element := range _get {
if len(element) == 0 {
continue
}
case "POST":
formData[key] = element[0]
}
if req.Method == http.MethodPost {
if err := req.ParseForm(); err != nil {
http.Redirect(
res, req,
@ -265,6 +263,7 @@ func SessionAuthMiddleware(ctx *App, res http.ResponseWriter, req *http.Request)
formData[key] = values[0]
}
}
idpParams := map[string]string{}
if err := json.Unmarshal(
[]byte(Config.Get("middleware.identity_provider.params").String()),
@ -280,7 +279,7 @@ func SessionAuthMiddleware(ctx *App, res http.ResponseWriter, req *http.Request)
// Step1: Entrypoint of the authentication process is handled by the plugin
if req.Method == "GET" && _get.Get("action") == "redirect" {
if label := _get.Get("label"); label != "" {
if label := _get.Get("label"); label != "" { // TODO: remove when we finish migration of auth plugins without cookie
http.SetCookie(res, applyCookieRules(http.Cookie{
Name: SSOCookieName,
Value: label + "::" + _get.Get("state"),
@ -317,32 +316,39 @@ func SessionAuthMiddleware(ctx *App, res http.ResponseWriter, req *http.Request)
)
return
}
templateBind["machine_id"] = GenerateMachineID()
for _, value := range os.Environ() {
pair := strings.SplitN(value, "=", 2)
if len(pair) == 2 {
templateBind[fmt.Sprintf("ENV_%s", pair[0])] = pair[1]
}
}
templateBind["machine_id"] = GenerateMachineID()
cookieLabel := ""
if refCookie, err := req.Cookie(SSOCookieName); err == nil {
var (
label = ""
state = ""
)
if refCookie, err := req.Cookie(SSOCookieName); err == nil { // TODO: deprecate SSOCookieName
s := strings.SplitN(refCookie.Value, "::", 2)
switch len(s) {
case 1:
cookieLabel = s[0]
label = s[0]
case 2:
cookieLabel = s[0]
if decodedState, err := base64.StdEncoding.DecodeString(s[1]); err == nil {
cookieState := map[string]string{}
json.Unmarshal(decodedState, &cookieState)
for key, value := range cookieState {
if templateBind[key] != "" {
continue
}
templateBind[key] = value
}
label = s[0]
state = s[1]
}
} else if l := req.URL.Query().Get("label"); l != "" {
label = l
state = req.URL.Query().Get("state")
}
if decodedState, err := base64.StdEncoding.DecodeString(state); err == nil {
stateStruct := map[string]string{}
json.Unmarshal(decodedState, &stateStruct)
for key, value := range stateStruct {
if templateBind[key] != "" {
continue
}
templateBind[key] = value
}
}
@ -357,7 +363,7 @@ func SessionAuthMiddleware(ctx *App, res http.ResponseWriter, req *http.Request)
return map[string]string{}, err
}
mappingToUse := map[string]string{}
for k, v := range globalMapping[cookieLabel] {
for k, v := range globalMapping[label] {
str := NewStringFromInterface(v)
if str == "" {
continue
@ -428,18 +434,21 @@ func SessionAuthMiddleware(ctx *App, res http.ResponseWriter, req *http.Request)
SendErrorResult(res, ErrNotValid)
return
}
http.SetCookie(res, applyCookieRules(http.Cookie{ // TODO: deprecate SSOCookieName
Name: SSOCookieName,
Value: "",
MaxAge: -1,
Path: COOKIE_PATH,
}, req))
http.SetCookie(res, applyCookieRules(http.Cookie{
Name: COOKIE_NAME_AUTH,
Value: obfuscate,
MaxAge: 60 * Config.Get("general.cookie_timeout").Int(),
Path: COOKIE_PATH,
}, req))
http.SetCookie(res, applyCookieRules(http.Cookie{
Name: SSOCookieName,
Value: "",
MaxAge: -1,
Path: COOKIE_PATH,
}, req))
if Config.Get("features.protection.iframe").String() != "" {
res.Header().Set("bearer", obfuscate)
}
redirectURI := templateBind["next"]
if redirectURI == "" {
redirectURI = WithBase("/")

View file

@ -36,14 +36,15 @@ func (this Admin) Setup() Form {
func (this Admin) EntryPoint(idpParams map[string]string, req *http.Request, res http.ResponseWriter) error {
res.Header().Set("Content-Type", "text/html; charset=utf-8")
getParams := "?label=" + req.URL.Query().Get("label") + "&state=" + req.URL.Query().Get("state")
switch idpParams["strategy"] {
case "direct":
res.WriteHeader(http.StatusOK)
res.Write([]byte(Page(`<h2 style="display:none;">PASSTHROUGH</h2><script>location.href = "/api/session/auth/"</script>`)))
res.Write([]byte(Page(`<h2 style="display:none;">PASSTHROUGH</h2><script>location.href = "` + WithBase("/api/session/auth/") + getParams + `"</script>`)))
case "password_only":
res.WriteHeader(http.StatusOK)
res.Write([]byte(Page(`
<form action="` + WithBase("/api/session/auth/") + `" method="post">
<form action="` + WithBase("/api/session/auth/"+getParams) + `" method="post">
<label>
<input type="password" name="password" value="" placeholder="Password" />
</label>
@ -52,7 +53,7 @@ func (this Admin) EntryPoint(idpParams map[string]string, req *http.Request, res
case "username_and_password":
res.WriteHeader(http.StatusOK)
res.Write([]byte(Page(`
<form action="` + WithBase("/api/session/auth/") + `" method="post">
<form action="` + WithBase("/api/session/auth/"+getParams) + `" method="post">
<label>
<input type="text" name="user" value="" placeholder="User" />
</label>