Auth: Add support for forcing authentication in anonymous mode and modify SignIn to use it instead of redirect (#25567)

* Forbid additional redirect urls

* Optionally force login in anonymous mode

* Update LoginCtrl page to ignore redirect parameter

* Modify SignIn to set forceLogin query instead of redirect

* Pass appUrl to frontend and use URL API for updating url query

* Apply suggestions from code review

Co-authored-by: Arve Knudsen <arve.knudsen@gmail.com>

* Fix SignIn test

Co-authored-by: Arve Knudsen <arve.knudsen@gmail.com>
This commit is contained in:
Sofia Papagiannaki
2020-06-16 16:33:44 +03:00
committed by GitHub
co-authored by Arve Knudsen
parent b4136c1eca
commit fefbbc65a8
10 changed files with 133 additions and 16 deletions
+1
View File
@@ -172,6 +172,7 @@ func (hs *HTTPServer) getFrontendSettingsMap(c *models.ReqContext) (map[string]i
"datasources": datasources,
"minRefreshInterval": setting.MinRefreshInterval,
"panels": panels,
"appUrl": setting.AppUrl,
"appSubUrl": setting.AppSubUrl,
"allowOrgCreate": (setting.AllowUserOrgCreate && c.IsSignedIn) || c.IsGrafanaAdmin,
"authProxyEnabled": setting.AuthProxyEnabled,
+14
View File
@@ -37,11 +37,25 @@ func (hs *HTTPServer) ValidateRedirectTo(redirectTo string) error {
if to.IsAbs() {
return login.ErrAbsoluteRedirectTo
}
if to.Host != "" {
return login.ErrForbiddenRedirectTo
}
// path should have exactly one leading slash
if !strings.HasPrefix(to.Path, "/") {
return login.ErrForbiddenRedirectTo
}
if strings.HasPrefix(to.Path, "//") {
return login.ErrForbiddenRedirectTo
}
// when using a subUrl, the redirect_to should start with the subUrl (which contains the leading slash), otherwise the redirect
// will send the user to the wrong location
if hs.Cfg.AppSubUrl != "" && !strings.HasPrefix(to.Path, hs.Cfg.AppSubUrl+"/") {
return login.ErrInvalidRedirectTo
}
return nil
}
+85 -1
View File
@@ -207,6 +207,48 @@ func TestLoginViewRedirect(t *testing.T) {
appURL: "http://localhost:3000/",
status: 302,
},
{
desc: "non-Grafana URL without scheme",
url: "example.com",
redirectURL: "/",
appURL: "http://localhost:3000/",
status: 302,
},
{
desc: "non-Grafana URL without scheme",
url: "www.example.com",
redirectURL: "/",
appURL: "http://localhost:3000/",
status: 302,
},
{
desc: "URL path is a host with two leading slashes",
url: "//example.com",
redirectURL: "/",
appURL: "http://localhost:3000/",
status: 302,
},
{
desc: "URL path is a host with three leading slashes",
url: "///example.com",
redirectURL: "/",
appURL: "http://localhost:3000/",
status: 302,
},
{
desc: "URL path is an IP address with two leading slashes",
url: "//0.0.0.0",
redirectURL: "/",
appURL: "http://localhost:3000/",
status: 302,
},
{
desc: "URL path is an IP address with three leading slashes",
url: "///0.0.0.0",
redirectURL: "/",
appURL: "http://localhost:3000/",
status: 302,
},
}
for _, c := range redirectCases {
@@ -232,7 +274,7 @@ func TestLoginViewRedirect(t *testing.T) {
if c.status == 302 {
location, ok := sc.resp.Header()["Location"]
assert.True(t, ok)
assert.Equal(t, location[0], c.redirectURL)
assert.Equal(t, c.redirectURL, location[0])
setCookie, ok := sc.resp.Header()["Set-Cookie"]
assert.True(t, ok, "Set-Cookie exists")
@@ -333,6 +375,48 @@ func TestLoginPostRedirect(t *testing.T) {
appURL: "https://localhost:3000/",
err: login.ErrAbsoluteRedirectTo,
},
{
desc: "invalid URL",
url: ":foo",
appURL: "http://localhost:3000/",
err: login.ErrInvalidRedirectTo,
},
{
desc: "non-Grafana URL without scheme",
url: "example.com",
appURL: "http://localhost:3000/",
err: login.ErrForbiddenRedirectTo,
},
{
desc: "non-Grafana URL without scheme",
url: "www.example.com",
appURL: "http://localhost:3000/",
err: login.ErrForbiddenRedirectTo,
},
{
desc: "URL path is a host with two leading slashes",
url: "//example.com",
appURL: "http://localhost:3000/",
err: login.ErrForbiddenRedirectTo,
},
{
desc: "URL path is a host with three leading slashes",
url: "///example.com",
appURL: "http://localhost:3000/",
err: login.ErrForbiddenRedirectTo,
},
{
desc: "URL path is an IP address with two leading slashes",
url: "//0.0.0.0",
appURL: "http://localhost:3000/",
err: login.ErrForbiddenRedirectTo,
},
{
desc: "URL path is an IP address with three leading slashes",
url: "///0.0.0.0",
appURL: "http://localhost:3000/",
err: login.ErrForbiddenRedirectTo,
},
}
for _, c := range redirectCases {