коммит произвёл
GitHub
родитель
540f4c1145
Коммит
e14175eb65
@@ -11,6 +11,7 @@ import (
|
|||||||
"net/url"
|
"net/url"
|
||||||
"path"
|
"path"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"slices"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@@ -22,6 +23,10 @@ import (
|
|||||||
"github.com/mattermost/mattermost/server/v8/channels/utils/fileutils"
|
"github.com/mattermost/mattermost/server/v8/channels/utils/fileutils"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
callbackHost = "callback"
|
||||||
|
)
|
||||||
|
|
||||||
func (w *Web) InitOAuth() {
|
func (w *Web) InitOAuth() {
|
||||||
// API version independent OAuth 2.0 as a service provider endpoints
|
// API version independent OAuth 2.0 as a service provider endpoints
|
||||||
w.MainRouter.Handle("/oauth/authorize", w.APIHandlerTrustRequester(authorizeOAuthPage)).Methods(http.MethodGet)
|
w.MainRouter.Handle("/oauth/authorize", w.APIHandlerTrustRequester(authorizeOAuthPage)).Methods(http.MethodGet)
|
||||||
@@ -315,7 +320,7 @@ func completeOAuth(c *Context, w http.ResponseWriter, r *http.Request) {
|
|||||||
hasRedirectURL = redirectURL != ""
|
hasRedirectURL = redirectURL != ""
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
redirectURL = fullyQualifiedRedirectURL(c.GetSiteURLHeader(), redirectURL)
|
redirectURL = fullyQualifiedRedirectURL(c.GetSiteURLHeader(), redirectURL, c.App.Config().NativeAppSettings.AppCustomURLSchemes)
|
||||||
|
|
||||||
renderError := func(err *model.AppError) {
|
renderError := func(err *model.AppError) {
|
||||||
if isMobile && hasRedirectURL {
|
if isMobile && hasRedirectURL {
|
||||||
@@ -535,7 +540,7 @@ func signupWithOAuth(c *Context, w http.ResponseWriter, r *http.Request) {
|
|||||||
http.Redirect(w, r, authURL, http.StatusFound)
|
http.Redirect(w, r, authURL, http.StatusFound)
|
||||||
}
|
}
|
||||||
|
|
||||||
func fullyQualifiedRedirectURL(siteURLPrefix, targetURL string) string {
|
func fullyQualifiedRedirectURL(siteURLPrefix, targetURL string, otherValidSchemes []string) string {
|
||||||
parsed, err := url.Parse(targetURL)
|
parsed, err := url.Parse(targetURL)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return siteURLPrefix
|
return siteURLPrefix
|
||||||
@@ -544,8 +549,15 @@ func fullyQualifiedRedirectURL(siteURLPrefix, targetURL string) string {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return siteURLPrefix
|
return siteURLPrefix
|
||||||
}
|
}
|
||||||
|
// mobile access
|
||||||
// Check if the targetURL is a valid URL and is within the siteURLPrefix
|
if slices.Contains(otherValidSchemes, fmt.Sprintf("%v://", parsed.Scheme)) &&
|
||||||
|
parsed.Host == callbackHost &&
|
||||||
|
parsed.Path == "" &&
|
||||||
|
parsed.RawQuery == "" &&
|
||||||
|
parsed.Fragment == "" {
|
||||||
|
return targetURL
|
||||||
|
}
|
||||||
|
// Check if the targetURL is valid and within the siteURLPrefix, excluding native app schemes like mmauth://
|
||||||
sameScheme := parsed.Scheme == prefixParsed.Scheme
|
sameScheme := parsed.Scheme == prefixParsed.Scheme
|
||||||
sameHost := parsed.Host == prefixParsed.Host
|
sameHost := parsed.Host == prefixParsed.Host
|
||||||
safePath := strings.HasPrefix(path.Clean(parsed.Path), path.Clean(prefixParsed.Path))
|
safePath := strings.HasPrefix(path.Clean(parsed.Path), path.Clean(prefixParsed.Path))
|
||||||
|
|||||||
@@ -861,6 +861,7 @@ func (th *TestHelper) AddPermissionToRole(permission string, roleName string) {
|
|||||||
|
|
||||||
func TestFullyQualifiedRedirectURL(t *testing.T) {
|
func TestFullyQualifiedRedirectURL(t *testing.T) {
|
||||||
const siteURL = "https://xxx.yyy/mm"
|
const siteURL = "https://xxx.yyy/mm"
|
||||||
|
|
||||||
for target, expected := range map[string]string{
|
for target, expected := range map[string]string{
|
||||||
"": siteURL,
|
"": siteURL,
|
||||||
"/": siteURL + "/",
|
"/": siteURL + "/",
|
||||||
@@ -881,9 +882,11 @@ func TestFullyQualifiedRedirectURL(t *testing.T) {
|
|||||||
"https://xxx.yyy/mm/some-path#section": siteURL + "/some-path#section",
|
"https://xxx.yyy/mm/some-path#section": siteURL + "/some-path#section",
|
||||||
"https://xxx.yyy/mm/../malicious-path": siteURL,
|
"https://xxx.yyy/mm/../malicious-path": siteURL,
|
||||||
":foo": siteURL,
|
":foo": siteURL,
|
||||||
|
"mmauth://callback": "mmauth://callback",
|
||||||
|
"mmauth://xxx.yyy/mm": siteURL, // invalid mobile URL (wrong host)
|
||||||
} {
|
} {
|
||||||
t.Run(target, func(t *testing.T) {
|
t.Run(target, func(t *testing.T) {
|
||||||
require.Equal(t, expected, fullyQualifiedRedirectURL(siteURL, target))
|
require.Equal(t, expected, fullyQualifiedRedirectURL(siteURL, target, []string{"mmauth://"}))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -117,7 +117,7 @@ func completeSaml(c *Context, w http.ResponseWriter, r *http.Request) {
|
|||||||
redirectURL = val
|
redirectURL = val
|
||||||
hasRedirectURL = val != ""
|
hasRedirectURL = val != ""
|
||||||
}
|
}
|
||||||
redirectURL = fullyQualifiedRedirectURL(c.GetSiteURLHeader(), redirectURL)
|
redirectURL = fullyQualifiedRedirectURL(c.GetSiteURLHeader(), redirectURL, c.App.Config().NativeAppSettings.AppCustomURLSchemes)
|
||||||
|
|
||||||
handleError := func(err *model.AppError) {
|
handleError := func(err *model.AppError) {
|
||||||
if isMobile && hasRedirectURL {
|
if isMobile && hasRedirectURL {
|
||||||
|
|||||||
Ссылка в новой задаче
Block a user