summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--app/extension.go82
-rw-r--r--config/default.json4
-rw-r--r--i18n/en.json16
-rw-r--r--model/config.go17
-rw-r--r--model/oauth.go1
-rw-r--r--templates/complete_saml_extension_body.html30
-rw-r--r--web/saml.go17
7 files changed, 167 insertions, 0 deletions
diff --git a/app/extension.go b/app/extension.go
new file mode 100644
index 000000000..d0226bba5
--- /dev/null
+++ b/app/extension.go
@@ -0,0 +1,82 @@
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
+// See License.txt for license information.
+
+package app
+
+import (
+ "github.com/mattermost/mattermost-server/model"
+ "html/template"
+ "net/http"
+)
+
+func (a *App) isExtensionSupportEnabled() bool {
+ return *a.Config().ExtensionSettings.EnableExperimentalExtensions
+}
+
+func (a *App) isExtensionValid(extensionId string) bool {
+ extensionIsValid := false
+ extensionIDs := a.Config().ExtensionSettings.AllowedExtensionsIDs
+
+ for _, id := range extensionIDs {
+ if extensionId == id {
+ extensionIsValid = true
+ }
+ }
+
+ return extensionIsValid
+}
+
+func (a *App) ValidateExtension(extensionId string) *model.AppError {
+ enabled := a.isExtensionSupportEnabled()
+ if !enabled {
+ return model.NewAppError("completeSaml", "api.user.saml.extension_unsupported", nil, "", http.StatusInternalServerError)
+ }
+
+ valid := a.isExtensionValid(extensionId)
+ if !valid {
+ params := map[string]interface{}{"ExtensionId": extensionId}
+ return model.NewAppError("completeSaml", "api.user.saml.invalid_extension", params, "", http.StatusInternalServerError)
+ }
+
+ return nil
+}
+
+func (a *App) SendMessageToExtension(w http.ResponseWriter, extensionId string, token string) *model.AppError {
+ var err error
+ var t *template.Template
+ if len(extensionId) == 0 {
+ return model.NewAppError("completeSaml", "api.user.saml.extension_id.app_error", nil, "", http.StatusInternalServerError)
+ }
+
+ t = template.New("complete_saml_extension_body")
+ t, err = t.ParseFiles("templates/complete_saml_extension_body.html")
+
+ if err != nil {
+ return model.NewAppError("completeSaml", "api.user.saml.app_error", nil, "err="+err.Error(), http.StatusInternalServerError)
+ }
+
+ w.Header().Set("Content-Type", "text/html")
+ w.WriteHeader(http.StatusOK)
+
+ var errMessage string
+ if len(token) == 0 {
+ loginError := model.NewAppError("completeSaml", "api.user.saml.app_error", nil, "", http.StatusInternalServerError)
+ errMessage = loginError.Message
+ }
+
+ data := struct {
+ ExtensionId string
+ Token string
+ Error string
+ }{
+ extensionId,
+ token,
+ errMessage,
+ }
+
+ if err := t.Execute(w, data); err != nil {
+ return model.NewAppError("completeSaml", "api.user.saml.app_error", nil, "err="+err.Error(), http.StatusInternalServerError)
+ }
+
+ return nil
+}
diff --git a/config/default.json b/config/default.json
index cb60611ba..cd85eda50 100644
--- a/config/default.json
+++ b/config/default.json
@@ -194,6 +194,10 @@
"LoginButtonBorderColor": "",
"LoginButtonTextColor": ""
},
+ "ExtensionSettings": {
+ "EnableExperimentalExtensions": false,
+ "AllowedExtensionsIDs": []
+ },
"RateLimitSettings": {
"Enable": false,
"PerSec": 10,
diff --git a/i18n/en.json b/i18n/en.json
index 9493a36b0..aad77aeb5 100644
--- a/i18n/en.json
+++ b/i18n/en.json
@@ -2167,6 +2167,22 @@
"translation": "Failed to send the deactivate account email successfully"
},
{
+ "id": "api.user.saml.app_error",
+ "translation": "Unable to process SAML login request."
+ },
+ {
+ "id": "api.user.saml.extension_unsupported",
+ "translation": "Extensions are not supported."
+ },
+ {
+ "id": "api.user.saml.extension_id.app_error",
+ "translation": "Invalid extension id"
+ },
+ {
+ "id": "api.user.saml.invalid_extension",
+ "translation": "Extension with extension_id={{.ExtensionId}} is not supported."
+ },
+ {
"id": "api.user.send_email_change_email_and_forget.error",
"translation": "Failed to send email change notification email successfully"
},
diff --git a/model/config.go b/model/config.go
index 7c9643b75..904668606 100644
--- a/model/config.go
+++ b/model/config.go
@@ -907,6 +907,21 @@ func (s *EmailSettings) SetDefaults() {
}
}
+type ExtensionSettings struct {
+ EnableExperimentalExtensions *bool
+ AllowedExtensionsIDs []string
+}
+
+func (s *ExtensionSettings) SetDefaults() {
+ if s.EnableExperimentalExtensions == nil {
+ s.EnableExperimentalExtensions = NewBool(false)
+ }
+
+ if s.AllowedExtensionsIDs == nil {
+ s.AllowedExtensionsIDs = []string{}
+ }
+}
+
type RateLimitSettings struct {
Enable *bool
PerSec *int
@@ -1870,6 +1885,7 @@ type Config struct {
PasswordSettings PasswordSettings
FileSettings FileSettings
EmailSettings EmailSettings
+ ExtensionSettings ExtensionSettings
RateLimitSettings RateLimitSettings
PrivacySettings PrivacySettings
SupportSettings SupportSettings
@@ -1967,6 +1983,7 @@ func (o *Config) SetDefaults() {
o.MessageExportSettings.SetDefaults()
o.TimezoneSettings.SetDefaults()
o.DisplaySettings.SetDefaults()
+ o.ExtensionSettings.SetDefaults()
}
func (o *Config) IsValid() *AppError {
diff --git a/model/oauth.go b/model/oauth.go
index c92b1ec41..0ea1aa4e2 100644
--- a/model/oauth.go
+++ b/model/oauth.go
@@ -17,6 +17,7 @@ const (
OAUTH_ACTION_EMAIL_TO_SSO = "email_to_sso"
OAUTH_ACTION_SSO_TO_EMAIL = "sso_to_email"
OAUTH_ACTION_MOBILE = "mobile"
+ OAUTH_ACTION_CLIENT = "client"
)
type OAuthApp struct {
diff --git a/templates/complete_saml_extension_body.html b/templates/complete_saml_extension_body.html
new file mode 100644
index 000000000..0c99ecbdc
--- /dev/null
+++ b/templates/complete_saml_extension_body.html
@@ -0,0 +1,30 @@
+{{define "complete_saml_extension_body"}}
+
+<html>
+ <head>
+ <script>
+ document.addEventListener("DOMContentLoaded", function(event) {
+ var extensionId = {{.ExtensionId}};
+
+ if (!extensionId) {
+ return;
+ }
+
+ chrome.runtime.sendMessage(
+ extensionId,
+ {
+ value: {{.Token}},
+ error: {{.Error}}
+ },
+ function(response) {
+ }
+ );
+ });
+ </script>
+ </head>
+ <body>
+ Login Successful
+ </body>
+</html>
+
+{{end}}
diff --git a/web/saml.go b/web/saml.go
index 9cf93bdab..f5400a378 100644
--- a/web/saml.go
+++ b/web/saml.go
@@ -32,6 +32,7 @@ func loginWithSaml(c *Context, w http.ResponseWriter, r *http.Request) {
}
action := r.URL.Query().Get("action")
redirectTo := r.URL.Query().Get("redirect_to")
+ extensionId := r.URL.Query().Get("extension_id")
relayProps := map[string]string{}
relayState := ""
@@ -47,6 +48,15 @@ func loginWithSaml(c *Context, w http.ResponseWriter, r *http.Request) {
relayProps["redirect_to"] = redirectTo
}
+ if len(extensionId) != 0 {
+ relayProps["extension_id"] = extensionId
+ err := c.App.ValidateExtension(extensionId)
+ if err != nil {
+ c.Err = err
+ return
+ }
+ }
+
if len(relayProps) > 0 {
relayState = b64.StdEncoding.EncodeToString([]byte(model.MapToJson(relayProps)))
}
@@ -141,6 +151,13 @@ func completeSaml(c *Context, w http.ResponseWriter, r *http.Request) {
if action == model.OAUTH_ACTION_MOBILE {
ReturnStatusOK(w)
+ } else if action == model.OAUTH_ACTION_CLIENT {
+ err = c.App.SendMessageToExtension(w, relayProps["extension_id"], c.Session.Token)
+
+ if err != nil {
+ c.Err = err
+ return
+ }
} else {
http.Redirect(w, r, c.GetSiteURLHeader(), http.StatusFound)
}