summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChris Duarte <csduarte@users.noreply.github.com>2018-07-18 14:56:38 -0700
committerChristopher Speller <crspeller@gmail.com>2018-07-18 14:56:38 -0700
commit3fcecd521a5c6ccfdb52fb4c3fb1f8c6ea528a4e (patch)
treecfb316b15d34d9242b5db41e76f1161e08813444
parent6b27b74f0cbd39e5d1400cddbed6437a4df64856 (diff)
downloadchat-3fcecd521a5c6ccfdb52fb4c3fb1f8c6ea528a4e.tar.gz
chat-3fcecd521a5c6ccfdb52fb4c3fb1f8c6ea528a4e.tar.bz2
chat-3fcecd521a5c6ccfdb52fb4c3fb1f8c6ea528a4e.zip
Support for Embeded chat (#9129)
* Add ucLive support crazy testing lovely logs more cookie work arounds Added Access-Control-Expose-Headers to user login Add complete_saml_body template and revert loginWithSaml endpoint Set Access-Control-Allow-Credentials to true in user login Login via email instead of username Clean up code Add comment to give some context Move faml logic into saml function Communicate via chrome sendMessage api Remove unused code Add config to support multiple extensions Clean up embedded complete_saml template Fix indentation for templates Added license header to extension.go Add EnableExperimentalExtensions flag Extension validated for email auth Clean up api auth code Remove complete_saml_body.html * Add extension support in saml * Clean up code * Clean up extension validation
-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)
}