After OAUTH, SAML auth completion, Redirect to App custom url scheme with token data as query params. (#16447)
* Added redirection after Auth complete * Fixed gofmt * Handling error while parsing the url, added util function to check for a valid mobile redirect url * Added check for custom scheme url validation * Added test to verify custom schele url * Added mobile message screens * Translation strings for mobile screens * Added mobile specific screens for success and error * Added error logs and changed variable name for consistency with oauth.go * i18n fix * Reusing assigned variable instead of map * Added AppCustomUrlScheme property * Code refactor and removed dependency from cookies to build the final url * Changed util function * Updated util test * Fixed go lint * Code refactor and unsused code removed * Code refactor * simplified boolean checks * Added support of whitelist of appCustomURLSchemes * Changed i18 en * Fixed validating redirecturl for web Co-authored-by: Mattermod <mattermod@users.noreply.github.com>
Этот коммит содержится в:
коммит произвёл
GitHub
родитель
911d1f070e
Коммит
3da6f270ec
65
utils/api.go
65
utils/api.go
@@ -74,3 +74,68 @@ func RenderWebError(config *model.Config, w http.ResponseWriter, r *http.Request
|
||||
fmt.Fprintln(w, `<a href="`+template.HTMLEscapeString(destination)+`" style="color: #c0c0c0;">...</a>`)
|
||||
fmt.Fprintln(w, `</body></html>`)
|
||||
}
|
||||
|
||||
func RenderMobileAuthComplete(w http.ResponseWriter, redirectUrl string) {
|
||||
RenderMobileMessage(w, `
|
||||
<div class="icon text-success" style="font-size: 4em">
|
||||
<i class="fa fa-check-circle" title="Success Icon"></i>
|
||||
</div>
|
||||
<h2> `+T("api.oauth.auth_complete")+` </h2>
|
||||
<p id="redirecting-message"> `+T("api.oauth.redirecting_back")+` </p>
|
||||
<p id="close-tab-message" style="display: none"> `+T("api.oauth.close_browser")+` </p>
|
||||
<noscript><meta http-equiv="refresh" content="2; url=`+template.HTMLEscapeString(redirectUrl)+`"></noscript>
|
||||
<script>
|
||||
window.onload = function() {
|
||||
setTimeout(function() {
|
||||
document.getElementById('redirecting-message').style.display = 'none';
|
||||
document.getElementById('close-tab-message').style.display = 'block';
|
||||
window.location='`+template.HTMLEscapeString(template.JSEscapeString(redirectUrl))+`';
|
||||
}, 2000);
|
||||
}
|
||||
</script>
|
||||
`)
|
||||
}
|
||||
|
||||
func RenderMobileError(config *model.Config, w http.ResponseWriter, err *model.AppError, redirectURL string) {
|
||||
RenderMobileMessage(w, `
|
||||
<div class="icon" style="color: #ccc; font-size: 4em">
|
||||
<span class="fa fa-warning"></span>
|
||||
</div>
|
||||
<h2> `+T("error")+` </h2>
|
||||
<p> `+err.Message+` </p>
|
||||
<a href="`+redirectURL+`">
|
||||
`+T("api.back_to_app", map[string]interface{}{"SiteName": config.TeamSettings.SiteName})+`
|
||||
</a>
|
||||
`)
|
||||
}
|
||||
|
||||
func RenderMobileMessage(w http.ResponseWriter, message string) {
|
||||
w.Header().Set("Content-Type", "text/html")
|
||||
fmt.Fprintln(w, `
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, user-scalable=yes, viewport-fit=cover">
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.css" integrity="sha512-5A8nwdMOWrSz20fDsjczgUidUBR8liPYU+WymTZP1lmY9G6Oc7HlZv156XqnsgNUzTyMefFTcsFH/tnJE/+xBg==" crossorigin="anonymous" />
|
||||
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous" />
|
||||
<style>
|
||||
.message-container {
|
||||
color: #555;
|
||||
display: table-cell;
|
||||
padding: 5em 0;
|
||||
text-align: left;
|
||||
vertical-align: top;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container-fluid">
|
||||
<div class="message-container">
|
||||
`+message+`
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
`)
|
||||
}
|
||||
|
||||
@@ -11,6 +11,8 @@ import (
|
||||
"strings"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"github.com/mattermost/mattermost-server/v5/model"
|
||||
)
|
||||
|
||||
func StringInSlice(a string, slice []string) bool {
|
||||
@@ -173,3 +175,43 @@ func GetUrlWithCache(url string, cache *RequestCache, skip bool) ([]byte, error)
|
||||
cache.Date = resp.Header.Get("Date")
|
||||
return cache.Data, err
|
||||
}
|
||||
|
||||
// Append tokens to passed baseUrl as query params
|
||||
func AppendQueryParamsToURL(baseUrl string, params map[string]string) string {
|
||||
u, err := url.Parse(baseUrl)
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
q, err := url.ParseQuery(u.RawQuery)
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
for key, value := range params {
|
||||
q.Add(key, value)
|
||||
}
|
||||
u.RawQuery = q.Encode()
|
||||
return u.String()
|
||||
}
|
||||
|
||||
// Validates RedirectURL passed during OAuth or SAML
|
||||
func IsValidWebAuthRedirectURL(config *model.Config, redirectURL string) bool {
|
||||
u, err := url.Parse(redirectURL)
|
||||
if err == nil && (u.Scheme == "http" || u.Scheme == "https") {
|
||||
if config.ServiceSettings.SiteURL != nil {
|
||||
siteUrl := *config.ServiceSettings.SiteURL
|
||||
return strings.Index(strings.ToLower(redirectURL), strings.ToLower(siteUrl)) == 0
|
||||
}
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// Validates Mobile Custom URL Scheme passed during OAuth or SAML
|
||||
func IsValidMobileAuthRedirectURL(config *model.Config, redirectURL string) bool {
|
||||
for _, URLScheme := range config.NativeAppSettings.AppCustomURLSchemes {
|
||||
if strings.Index(strings.ToLower(redirectURL), strings.ToLower(URLScheme)) == 0 {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -160,3 +160,13 @@ func TestRemoveStringFromSlice(t *testing.T) {
|
||||
|
||||
assert.Equal(t, RemoveStringFromSlice("four", a), expected)
|
||||
}
|
||||
|
||||
func TestAppendQueryParamsToURL(t *testing.T) {
|
||||
url := "mattermost://callback"
|
||||
redirectUrl := AppendQueryParamsToURL(url, map[string]string{
|
||||
"key1": "value1",
|
||||
"key2": "value2",
|
||||
})
|
||||
expected := url + "?key1=value1&key2=value2"
|
||||
assert.Equal(t, redirectUrl, expected)
|
||||
}
|
||||
|
||||
Ссылка в новой задаче
Block a user