diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index fcb9164401cc2..057396197c606 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -5,9 +5,11 @@ on: branches: - main pull_request: + branches: + - main workflow_dispatch: -permissions: read-all +permissions: {} jobs: package: @@ -41,6 +43,9 @@ jobs: - name: Apply patches run: for i in ./patch/*.patch; do patch -p1 < "$i"; done + - name: Add overlay + run: cp -R ./patch/overlay/* ./ + - name: Build server uses: ./patch/build-server diff --git a/0002-enable-openid-provider.patch b/0002-enable-openid-provider.patch new file mode 100644 index 0000000000000..40d900c059a46 --- /dev/null +++ b/0002-enable-openid-provider.patch @@ -0,0 +1,27 @@ +Import openid oauthprovider and enable in non-enterprise version. + +--- a/server/cmd/mattermost/main.go ++++ b/server/cmd/mattermost/main.go +@@ -11,6 +11,7 @@ import ( + _ "github.com/mattermost/mattermost/server/v8/channels/app/slashcommands" + // Plugins + _ "github.com/mattermost/mattermost/server/v8/channels/app/oauthproviders/gitlab" ++ _ "github.com/mattermost/mattermost/server/v8/channels/app/oauthproviders/openid" + + // Enterprise Imports + _ "github.com/mattermost/mattermost/server/v8/enterprise" +--- a/server/config/client.go ++++ b/server/config/client.go +@@ -326,9 +326,9 @@ func GenerateLimitedClientConfig(c *model.Config, telemetryID string, license *m + props["SamlLoginButtonTextColor"] = "" + props["EnableSignUpWithGoogle"] = "false" + props["EnableSignUpWithOffice365"] = "false" +- props["EnableSignUpWithOpenId"] = "false" +- props["OpenIdButtonText"] = "" +- props["OpenIdButtonColor"] = "" ++ props["EnableSignUpWithOpenId"] = strconv.FormatBool(*c.OpenIdSettings.Enable) ++ props["OpenIdButtonColor"] = *c.OpenIdSettings.ButtonColor ++ props["OpenIdButtonText"] = *c.OpenIdSettings.ButtonText + props["CWSURL"] = "" + props["EnableCustomBrand"] = strconv.FormatBool(*c.TeamSettings.EnableCustomBrand) + props["CustomBrandText"] = *c.TeamSettings.CustomBrandText diff --git a/0002-replace-gitlab-icon-with-opencampus-icon.patch b/0002-replace-gitlab-icon-with-opencampus-icon.patch deleted file mode 100644 index 91630f683b6e0..0000000000000 --- a/0002-replace-gitlab-icon-with-opencampus-icon.patch +++ /dev/null @@ -1,13 +0,0 @@ -replace gitlab icon with opencampus icon. - ---- a/webapp/channels/src/components/common/svg_images_components/gitlab_svg.tsx -+++ b/webapp/channels/src/components/common/svg_images_components/gitlab_svg.tsx -@@ -34,7 +34,7 @@ export default () => ( - id='image0_615_81787' - width='338' - height='311' -- xlinkHref='data:image/png;base64,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' -+ xlinkHref='data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4KPCEtLSBHZW5lcmF0b3I6IEFkb2JlIElsbHVzdHJhdG9yIDIzLjAuNiwgU1ZHIEV4cG9ydCBQbHVnLUluIC4gU1ZHIFZlcnNpb246IDYuMDAgQnVpbGQgMCkgIC0tPgo8c3ZnIHZlcnNpb249IjEuMSIgaWQ9IkViZW5lXzEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIHg9IjBweCIgeT0iMHB4IgoJIHZpZXdCb3g9IjAgMCAyNTYgMjU2IiBzdHlsZT0iZW5hYmxlLWJhY2tncm91bmQ6bmV3IDAgMCAyNTYgMjU2OyIgeG1sOnNwYWNlPSJwcmVzZXJ2ZSI+CjxnIGlkPSJCaWxkbWFya2UiPgoJPHBhdGggZD0iTTg4LjA1LDEyOC42OGMwLTE3LjE2LDAtMzQuMzIsMC01MS40OGMwLTAuNzMsMC0xLjQ2LDAuMDItMi4yYzAuMDQtMS4xOSwwLjU0LTEuNjYsMS43MS0xLjA5CgkJYzAuNTEsMC4yNSwxLjAyLDAuNSwxLjUzLDAuNzZjMzUuMTMsMTcuNTUsNzAuMjYsMzUuMSwxMDUuMzksNTIuNjVjMC41MSwwLjI1LDEuMDMsMC40OSwxLjUyLDAuNzhjMC44NiwwLjUsMS4wNCwxLjAzLDAsMS41NQoJCWMtMC4zNiwwLjE4LTAuNzMsMC4zNi0xLjA5LDAuNTRjLTM1LjIsMTcuNTgtNzAuNDEsMzUuMTctMTA1LjYxLDUyLjc1Yy0wLjUxLDAuMjUtMS4wMiwwLjUtMS41MywwLjc2CgkJYy0xLjIxLDAuNjItMS44NiwwLjI1LTEuOTEtMS4xMWMtMC4wMy0wLjgxLTAuMDMtMS42My0wLjAzLTIuNDRDODguMDUsMTYyLjk5LDg4LjA1LDE0NS44NCw4OC4wNSwxMjguNjh6IE0xNjYuNDIsMTI4LjkxCgkJYy0wLjgzLTAuNDgtMS4xNi0wLjctMS41Mi0wLjg4Yy0xOS43OC05Ljg2LTM5LjU2LTE5LjcyLTU5LjM1LTI5LjU2Yy0yLjItMS4wOS0yLjM3LTAuOTgtMi4zNywxLjZjLTAuMDEsMTkuMDItMC4wMSwzOC4wNCwwLDU3LjA2CgkJYzAsMy4xNSwwLjE0LDMuMjQsMi45LDEuODZjMTQuNjItNy4yOCwyOS4yNC0xNC41Nyw0My44NS0yMS44NUMxNTUuMywxMzQuNDYsMTYwLjY2LDEzMS43OSwxNjYuNDIsMTI4LjkxeiIvPgoJPHBhdGggZD0iTTEyNi45NCwyNDNjLTI0LjEyLTAuNTQtNDYuNDctNi42Mi02Ni4xNS0yMS4xNmMtMi4yMy0xLjY1LTIuMjQtMS43LDAuMTQtMi45NWMzLjUzLTEuODUsNy4wOC0zLjY1LDEwLjU3LTUuNTYKCQljMS4zNS0wLjc0LDIuNDUtMC43NywzLjgyLDAuMDdjMTcuOCwxMC45LDM3LjIsMTUuNjksNTcuOTcsMTQuNDNjMjEuNS0xLjMsNDAuNy04Ljg0LDU3LjI2LTIyLjY3CgkJYzE4LjQ4LTE1LjQzLDI5Ljg5LTM1LjA4LDM0LjIzLTU4Ljc5YzAuNTMtMi44NywwLjg4LTUuNzgsMS4yLTguNjljMC4xNS0xLjMzLDAuNzktMS44NywyLjA0LTEuODdjMy43NCwwLDcuNDgsMC4wMiwxMS4yMi0wLjAyCgkJYzEuNzUtMC4wMiwyLjI5LDAuODUsMi4wNywyLjQ3Yy0yLjQsMTcuNTMtNi43MSwzNC40MS0xNi4xMyw0OS42OWMtMTEuMDUsMTcuOTItMjUuODEsMzEuODctNDQuMjUsNDEuOTQKCQljLTEyLjM2LDYuNzYtMjUuODEsMTAuMS0zOS41OCwxMi40QzEzNi41NywyNDMuMTEsMTMxLjc3LDI0Mi43MywxMjYuOTQsMjQzeiIvPgoJPHBhdGggZD0iTTEyNy41LDE1LjA2YzMzLjY1LDAuNzksNjIuMzEsMTIuOTQsODUuMDMsMzguMDljMTQuODgsMTYuNDgsMjMuODEsMzUuOTEsMjcuNCw1Ny44YzAuMzcsMi4yNCwwLjYzLDQuNSwxLjAyLDYuNzQKCQljMC4zMSwxLjc5LTAuNDYsMi4yOC0yLjEzLDIuMjRjLTMuNDktMC4wOC02Ljk5LTAuMS0xMC40OSwwLjAxYy0xLjgzLDAuMDUtMi41OC0wLjYtMi43OC0yLjQ2Yy0xLjc5LTE2LjI0LTcuMjktMzEuMTUtMTYuNy00NC40OQoJCWMtMTYuOTMtMjMuOTgtMzkuOTctMzguMTktNjkuMTItNDIuMDFjLTIzLjMzLTMuMDYtNDUuMDgsMS44Mi02NS4xLDE0LjE5Yy0xLjM1LDAuODMtMi40MywwLjktMy44MSwwLjE1CgkJYy0zLjU2LTEuOTYtNy4xNi0zLjg0LTEwLjgtNS42NWMtMi0wLjk5LTEuNTgtMS42OC0wLjA3LTIuODFjMTMuMDMtOS44MSwyNy42Ni0xNS45MSw0My41Ny0xOS4yNQoJCUMxMTEuNDMsMTUuOTUsMTE5LjM0LDE0LjcyLDEyNy41LDE1LjA2eiIvPgoJPHBhdGggZD0iTTEyLjY2LDEyOC44OGMxLjA5LTI4LjcyLDEwLjExLTU0LjM4LDI5LjM4LTc2LjEyYzEuMy0xLjQ3LDIuMzQtMS44MSw0LjEyLTAuNzljMy4xMSwxLjc2LDYuMzQsMy4zMSw5LjU4LDQuODMKCQljMS43OCwwLjgzLDIuMTIsMS40NSwwLjU2LDMuMDVDNDUuNTQsNzAuOTEsMzcuMzUsODMuNjcsMzIuOTMsOTguNWMtMTAuNSwzNS4yOC00LjEsNjcuMjcsMTkuNTYsOTUuNjMKCQljMS4yNSwxLjUsMi41OCwyLjkyLDMuOTUsNC4zMWMxLjAxLDEuMDMsMC45OSwxLjc1LTAuMzUsMi40Yy0zLjczLDEuODEtNy40NiwzLjYtMTEuMTcsNS40NmMtMS42OSwwLjg1LTIuNDEtMC40Ni0zLjItMS4zOQoJCWMtNS42NS02LjYzLTEwLjc0LTEzLjY3LTE1LjAxLTIxLjI4Yy03LjU5LTEzLjU1LTExLjA5LTI4LjM1LTEzLjQzLTQzLjUzQzEyLjcyLDEzNi4zNywxMi44NSwxMzIuNjQsMTIuNjYsMTI4Ljg4eiIvPgo8L2c+Cjwvc3ZnPgo=' - /> - - diff --git a/0003-replace-openid-icon-with-opencampus-icon.patch b/0003-replace-openid-icon-with-opencampus-icon.patch new file mode 100644 index 0000000000000..5b5520f10a2d7 --- /dev/null +++ b/0003-replace-openid-icon-with-opencampus-icon.patch @@ -0,0 +1,50 @@ +Replace openid logo with the opencampus icon. + +--- a/webapp/channels/src/components/widgets/icons/login_openid_icon.tsx ++++ b/webapp/channels/src/components/widgets/icons/login_openid_icon.tsx +@@ -12,23 +12,31 @@ export default function LoginOpenIdIcon(props: React.HTMLAttributes +- +- +- ++ ++ ++ ++ + + + diff --git a/README.md b/README.md index db06fad748b1c..fd4922ed9591a 100644 --- a/README.md +++ b/README.md @@ -5,11 +5,12 @@ applied. The upstream mettermost version is specified in the `VERSION` file. All patch files (files ending with .patch) in the root directory of the -repository are applied onto the specified mattermost version. When -adding new patches or changing them please make sure a description -exists and is up to date. +repository are applied onto the specified mattermost version. Files +inside of the `overlay/` directory are copied directly. When adding new +patches or changing them please make sure a description exists and is +up to date. ## License -The code is published under the AGPL version 3.0 only. See the -`LICENSE` file for details. +The code is published under the AGPL version 3.0 only unless otherwise +specified in the file. See the `LICENSE` file for details. diff --git a/overlay/server/channels/app/oauthproviders/openid/openid.go b/overlay/server/channels/app/oauthproviders/openid/openid.go new file mode 100644 index 0000000000000..4c58a5a28e995 --- /dev/null +++ b/overlay/server/channels/app/oauthproviders/openid/openid.go @@ -0,0 +1,246 @@ +// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. +// See [LICENSE.txt] for license information. +// [LICENSE.txt]: https://github.com/mattermost/mattermost/blob/03a5b4a288ba60c52e604e5ef017cf5fc179db51/LICENSE.txt + +package oauthopenid + +import ( + "encoding/base64" + "encoding/json" + "errors" + "io" + "net/http" + "strconv" + "strings" + "time" + + "github.com/mattermost/mattermost/server/public/model" + "github.com/mattermost/mattermost/server/public/shared/mlog" + "github.com/mattermost/mattermost/server/public/shared/request" + "github.com/mattermost/mattermost/server/v8/einterfaces" +) + +type CacheData struct { + Service string + Expires int64 + Settings model.SSOSettings +} + +type OpenIdMetadata struct { + Issuer string `json:"issuer"` + AuthorizationEndpoint string `json:"authorization_endpoint"` + TokenEndpoint string `json:"token_endpoint"` + UserEndpoint string `json:"userinfo_endpoint"` + JwksURI string `json:"jwks_uri"` + Algorithms []string `json:"id_token_signing_alg_values_supported"` +} + +type OpenIdProvider struct { + CacheData *CacheData +} + +type OpenIdUser struct { + Id string `json:"sub"` + Oid string `json:"oid"` //Office 365 only + FirstName string `json:"given_name"` + LastName string `json:"family_name"` + Name string `json:"name"` + Nickname string `json:"nickname"` + Email string `json:"email"` +} + +func init() { + provider := &OpenIdProvider{} + einterfaces.RegisterOAuthProvider(model.ServiceOpenid, provider) +} + +func (o *OpenIdProvider) userFromOpenIdUser(logger mlog.LoggerIFace, u *OpenIdUser) *model.User { + user := &model.User{} + + user.Email = u.Email + user.Username = model.CleanUsername(logger, strings.Split(user.Email, "@")[0]) + if o.CacheData.Service == model.ServiceGitlab && u.Nickname != "" { + user.Username = u.Nickname + } + + user.FirstName = u.FirstName + user.LastName = u.LastName + user.Nickname = u.Nickname + + user.AuthData = new(string) + *user.AuthData = o.getAuthData(u) + + return user +} + +func (o *OpenIdProvider) getAuthData(u *OpenIdUser) string { + if o.CacheData.Service == model.ServiceOffice365 { + if u.Oid != "" { + return u.Oid + } + } + return u.Id +} + +func openIDUserFromJSON(data io.Reader) (*OpenIdUser, error) { + decoder := json.NewDecoder(data) + var u OpenIdUser + err := decoder.Decode(&u) + if err != nil { + return nil, err + } + return &u, nil +} + +func (u *OpenIdUser) IsValid() error { + if u.Id == "" { + return errors.New("invalid id") + } + + if u.Email == "" { + return errors.New("invalid emails") + } + return nil +} + +func (u *OpenIdUser) GetIdentifier() string { + return model.ServiceOpenid +} + +func (o *OpenIdProvider) GetUserFromJSON(c request.CTX, data io.Reader, tokenUser *model.User) (*model.User, error) { + oid, err := openIDUserFromJSON(data) + if err != nil { + return nil, err + } + jsonUser := o.userFromOpenIdUser(c.Logger(), oid) + + if tokenUser != nil { + jsonUser = o.combineUsers(jsonUser, tokenUser) + } + return jsonUser, nil +} + +func (o *OpenIdProvider) combineUsers(jsonUser *model.User, tokenUser *model.User) *model.User { + if o.CacheData.Service == model.ServiceOffice365 { + jsonUser.AuthData = tokenUser.AuthData + } + return jsonUser +} + +func (o *OpenIdProvider) GetAuthDataFromJSON(data io.Reader) (string, error) { + u, err := openIDUserFromJSON(data) + if err != nil { + return "", err + } + + err = u.IsValid() + if err != nil { + return "", err + } + return o.getAuthData(u), nil +} + +// GetSSOSettings returns SSO Settings from Cache or Discovery Document +func (o *OpenIdProvider) GetSSOSettings(_ request.CTX, config *model.Config, service string) (*model.SSOSettings, error) { + settings := config.OpenIdSettings + if service == model.ServiceOffice365 { + settings = *config.Office365Settings.SSOSettings() + } else if service == model.ServiceGoogle { + settings = config.GoogleSettings + } else if service == model.ServiceGitlab { + settings = config.GitLabSettings + } + + if o.CacheData != nil && !settingsChanged(*o.CacheData, service, settings) && o.CacheData.Expires > time.Now().Unix() { + return &o.CacheData.Settings, nil + } + + var age int64 = 0 + if *settings.DiscoveryEndpoint != "" { + response, err := http.Get(*settings.DiscoveryEndpoint) + if err != nil { + return nil, err + } + defer response.Body.Close() + + for _, v := range strings.Split(response.Header.Get("Cache-Control"), ",") { + if strings.Contains(v, "max-age") { + ageValue := strings.Split(v, "=")[1] + age, _ = strconv.ParseInt(ageValue, 10, 64) + } + } + responseData, err := io.ReadAll(response.Body) + if err != nil { + return nil, err + } + + var openIDResponse OpenIdMetadata + err = json.Unmarshal(responseData, &openIDResponse) + if err != nil { + return nil, err + } + + settings.AuthEndpoint = &openIDResponse.AuthorizationEndpoint + settings.TokenEndpoint = &openIDResponse.TokenEndpoint + settings.UserAPIEndpoint = &openIDResponse.UserEndpoint + } + expires := time.Now().Unix() + age + + o.CacheData = &CacheData{ + Service: service, + Expires: expires, + Settings: settings, + } + return &settings, nil +} + +func settingsChanged(cacheData CacheData, service string, configSettings model.SSOSettings) bool { + if cacheData.Service == service && + cacheData.Settings.DiscoveryEndpoint == configSettings.DiscoveryEndpoint && + cacheData.Settings.Secret == configSettings.Secret && + cacheData.Settings.Id == configSettings.Id { + return false + } + return true +} + +func (o *OpenIdProvider) GetUserFromIdToken(c request.CTX, idToken string) (*model.User, error) { + parts := strings.Split(idToken, ".") + if len(parts) != 3 { + return nil, errors.New("invalid Id Token") + } + + b, err := base64.RawURLEncoding.DecodeString(parts[1]) + if err != nil { + return nil, err + } + + claims := &OpenIdUser{} + json.Unmarshal(b, &claims) + + return o.userFromOpenIdUser(c.Logger(), claims), nil +} + +func (o *OpenIdProvider) IsSameUser(_ request.CTX, dbUser, oauthUser *model.User) bool { + // Office365 OAuth would store Ids without dashes. (ie. 0e8fddd450d344999a93a390ee8cb83d) + // Office365 OpenId will return as a formatted GUID (ie. '0e8fddd4-50d3-4499-9a93-a390ee8cb83d') + // If this is a UUID that starts with all zero. (ie. 00000000-0000-0000-be95-fe607df5dbeb) + // For backwards compatibility we store the auth data from OAuth as be95fe607df5dbeb + if dbUser.AuthData == nil || oauthUser.AuthData == nil { + return false + } + dbID := *dbUser.AuthData + oauthID := *oauthUser.AuthData + if dbID == "" || oauthID == "" { + return false + } + parts := strings.Split(oauthID, "-") + for _, part := range parts { + if strings.Count(part, "0") != len(part) { + if !strings.Contains(dbID, part) { + return false + } + } + } + return true +}