Files
mostlymatter/utils/api.go
Anurag Shivarathri 3da6f270ec 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>
2021-01-19 21:16:22 +05:30

142 строки
4.5 KiB
Go

// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
package utils
import (
"crypto"
"crypto/rand"
"encoding/base64"
"fmt"
"html/template"
"net/http"
"net/url"
"path"
"strings"
"github.com/mattermost/mattermost-server/v5/model"
)
func CheckOrigin(r *http.Request, allowedOrigins string) bool {
origin := r.Header.Get("Origin")
if origin == "" {
return true
}
if allowedOrigins == "*" {
return true
}
for _, allowed := range strings.Split(allowedOrigins, " ") {
if allowed == origin {
return true
}
}
return false
}
func OriginChecker(allowedOrigins string) func(*http.Request) bool {
return func(r *http.Request) bool {
return CheckOrigin(r, allowedOrigins)
}
}
func RenderWebAppError(config *model.Config, w http.ResponseWriter, r *http.Request, err *model.AppError, s crypto.Signer) {
RenderWebError(config, w, r, err.StatusCode, url.Values{
"message": []string{err.Message},
}, s)
}
func RenderWebError(config *model.Config, w http.ResponseWriter, r *http.Request, status int, params url.Values, s crypto.Signer) {
queryString := params.Encode()
subpath, _ := GetSubpathFromConfig(config)
h := crypto.SHA256
sum := h.New()
sum.Write([]byte(path.Join(subpath, "error") + "?" + queryString))
signature, err := s.Sign(rand.Reader, sum.Sum(nil), h)
if err != nil {
http.Error(w, "", http.StatusInternalServerError)
return
}
destination := path.Join(subpath, "error") + "?" + queryString + "&s=" + base64.URLEncoding.EncodeToString(signature)
if status >= 300 && status < 400 {
http.Redirect(w, r, destination, status)
return
}
w.Header().Set("Content-Type", "text/html")
w.WriteHeader(status)
fmt.Fprintln(w, `<!DOCTYPE html><html><head></head>`)
fmt.Fprintln(w, `<body onload="window.location = '`+template.HTMLEscapeString(template.JSEscapeString(destination))+`'">`)
fmt.Fprintln(w, `<noscript><meta http-equiv="refresh" content="0; url=`+template.HTMLEscapeString(destination)+`"></noscript>`)
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>
`)
}