diff options
author | Chris Duarte <csduarte@users.noreply.github.com> | 2018-07-18 14:56:38 -0700 |
---|---|---|
committer | Christopher Speller <crspeller@gmail.com> | 2018-07-18 14:56:38 -0700 |
commit | 3fcecd521a5c6ccfdb52fb4c3fb1f8c6ea528a4e (patch) | |
tree | cfb316b15d34d9242b5db41e76f1161e08813444 | |
parent | 6b27b74f0cbd39e5d1400cddbed6437a4df64856 (diff) | |
download | chat-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.go | 82 | ||||
-rw-r--r-- | config/default.json | 4 | ||||
-rw-r--r-- | i18n/en.json | 16 | ||||
-rw-r--r-- | model/config.go | 17 | ||||
-rw-r--r-- | model/oauth.go | 1 | ||||
-rw-r--r-- | templates/complete_saml_extension_body.html | 30 | ||||
-rw-r--r-- | web/saml.go | 17 |
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) } |