коммит произвёл
GitHub
родитель
540f4c1145
Коммит
e14175eb65
@@ -11,6 +11,7 @@ import (
|
||||
"net/url"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"slices"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
@@ -22,6 +23,10 @@ import (
|
||||
"github.com/mattermost/mattermost/server/v8/channels/utils/fileutils"
|
||||
)
|
||||
|
||||
const (
|
||||
callbackHost = "callback"
|
||||
)
|
||||
|
||||
func (w *Web) InitOAuth() {
|
||||
// API version independent OAuth 2.0 as a service provider endpoints
|
||||
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 != ""
|
||||
}
|
||||
}
|
||||
redirectURL = fullyQualifiedRedirectURL(c.GetSiteURLHeader(), redirectURL)
|
||||
redirectURL = fullyQualifiedRedirectURL(c.GetSiteURLHeader(), redirectURL, c.App.Config().NativeAppSettings.AppCustomURLSchemes)
|
||||
|
||||
renderError := func(err *model.AppError) {
|
||||
if isMobile && hasRedirectURL {
|
||||
@@ -535,7 +540,7 @@ func signupWithOAuth(c *Context, w http.ResponseWriter, r *http.Request) {
|
||||
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)
|
||||
if err != nil {
|
||||
return siteURLPrefix
|
||||
@@ -544,8 +549,15 @@ func fullyQualifiedRedirectURL(siteURLPrefix, targetURL string) string {
|
||||
if err != nil {
|
||||
return siteURLPrefix
|
||||
}
|
||||
|
||||
// Check if the targetURL is a valid URL and is within the siteURLPrefix
|
||||
// mobile access
|
||||
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
|
||||
sameHost := parsed.Host == prefixParsed.Host
|
||||
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) {
|
||||
const siteURL = "https://xxx.yyy/mm"
|
||||
|
||||
for target, expected := range map[string]string{
|
||||
"": 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/../malicious-path": siteURL,
|
||||
":foo": siteURL,
|
||||
"mmauth://callback": "mmauth://callback",
|
||||
"mmauth://xxx.yyy/mm": siteURL, // invalid mobile URL (wrong host)
|
||||
} {
|
||||
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
|
||||
hasRedirectURL = val != ""
|
||||
}
|
||||
redirectURL = fullyQualifiedRedirectURL(c.GetSiteURLHeader(), redirectURL)
|
||||
redirectURL = fullyQualifiedRedirectURL(c.GetSiteURLHeader(), redirectURL, c.App.Config().NativeAppSettings.AppCustomURLSchemes)
|
||||
|
||||
handleError := func(err *model.AppError) {
|
||||
if isMobile && hasRedirectURL {
|
||||
|
||||
Ссылка в новой задаче
Block a user