* implement openid connect

* update error strings

* handle OpenIdSetting.Secret as FAKE SETTING

* add openid to telemetry

* update config defaults, add telemetry

* fix bug with Office365

* Retrieve Office365 AuthData from IdToken

* fix linter

* add feature flag, reset defaults for config

* fix build error

* fix unit tests

* add authentication permission to Feature
Flags

* turn off feature flag

* set default button color

* set default button color only on openid

* fix for merging FeatureFlags in config

* remove feature flag

* revert config changes

* remove debug statements

Co-authored-by: Mattermod <mattermod@users.noreply.github.com>
Этот коммит содержится в:
Scott Bishel
2020-12-08 19:58:37 -07:00
коммит произвёл GitHub
родитель 2a71fc5ee2
Коммит f548ecbee1
22 изменённых файлов: 258 добавлений и 138 удалений

Просмотреть файл

@@ -31,6 +31,7 @@ type AccessResponse struct {
ExpiresIn int32 `json:"expires_in"`
Scope string `json:"scope"`
RefreshToken string `json:"refresh_token"`
IdToken string `json:"id_token"`
}
// IsValid validates the AccessData and returns an error if it isn't configured

Просмотреть файл

@@ -45,6 +45,7 @@ const (
SERVICE_GITLAB = "gitlab"
SERVICE_GOOGLE = "google"
SERVICE_OFFICE365 = "office365"
SERVICE_OPENID = "openid"
GENERIC_NO_CHANNEL_NOTIFICATION = "generic_no_channel"
GENERIC_NOTIFICATION = "generic"
@@ -230,6 +231,7 @@ const (
OFFICE365_SETTINGS_DEFAULT_USER_API_ENDPOINT = "https://graph.microsoft.com/v1.0/me"
CLOUD_SETTINGS_DEFAULT_CWS_URL = "https://customers.mattermost.com"
OPENID_SETTINGS_DEFAULT_SCOPE = "profile openid email"
LOCAL_MODE_SOCKET_PATH = "/var/tmp/mattermost_local.socket"
)
@@ -960,16 +962,19 @@ func (s *AnalyticsSettings) SetDefaults() {
}
type SSOSettings struct {
Enable *bool `access:"authentication"`
Secret *string `access:"authentication"`
Id *string `access:"authentication"`
Scope *string `access:"authentication"`
AuthEndpoint *string `access:"authentication"`
TokenEndpoint *string `access:"authentication"`
UserApiEndpoint *string `access:"authentication"`
Enable *bool `access:"authentication"`
Secret *string `access:"authentication"`
Id *string `access:"authentication"`
Scope *string `access:"authentication"`
AuthEndpoint *string `access:"authentication"`
TokenEndpoint *string `access:"authentication"`
UserApiEndpoint *string `access:"authentication"`
DiscoveryEndpoint *string `access:"authentication"`
ButtonText *string `access:"authentication"`
ButtonColor *string `access:"authentication"`
}
func (s *SSOSettings) setDefaults(scope, authEndpoint, tokenEndpoint, userApiEndpoint string) {
func (s *SSOSettings) setDefaults(scope, authEndpoint, tokenEndpoint, userApiEndpoint, buttonColor string) {
if s.Enable == nil {
s.Enable = NewBool(false)
}
@@ -986,6 +991,10 @@ func (s *SSOSettings) setDefaults(scope, authEndpoint, tokenEndpoint, userApiEnd
s.Scope = NewString(scope)
}
if s.DiscoveryEndpoint == nil {
s.DiscoveryEndpoint = NewString("")
}
if s.AuthEndpoint == nil {
s.AuthEndpoint = NewString(authEndpoint)
}
@@ -997,17 +1006,26 @@ func (s *SSOSettings) setDefaults(scope, authEndpoint, tokenEndpoint, userApiEnd
if s.UserApiEndpoint == nil {
s.UserApiEndpoint = NewString(userApiEndpoint)
}
if s.ButtonText == nil {
s.ButtonText = NewString("")
}
if s.ButtonColor == nil {
s.ButtonColor = NewString(buttonColor)
}
}
type Office365Settings struct {
Enable *bool `access:"authentication"`
Secret *string `access:"authentication"`
Id *string `access:"authentication"`
Scope *string `access:"authentication"`
AuthEndpoint *string `access:"authentication"`
TokenEndpoint *string `access:"authentication"`
UserApiEndpoint *string `access:"authentication"`
DirectoryId *string `access:"authentication"`
Enable *bool `access:"authentication"`
Secret *string `access:"authentication"`
Id *string `access:"authentication"`
Scope *string `access:"authentication"`
AuthEndpoint *string `access:"authentication"`
TokenEndpoint *string `access:"authentication"`
UserApiEndpoint *string `access:"authentication"`
DiscoveryEndpoint *string `access:"authentication"`
DirectoryId *string `access:"authentication"`
}
func (s *Office365Settings) setDefaults() {
@@ -1027,6 +1045,10 @@ func (s *Office365Settings) setDefaults() {
s.Scope = NewString(OFFICE365_SETTINGS_DEFAULT_SCOPE)
}
if s.DiscoveryEndpoint == nil {
s.DiscoveryEndpoint = NewString("")
}
if s.AuthEndpoint == nil {
s.AuthEndpoint = NewString(OFFICE365_SETTINGS_DEFAULT_AUTH_ENDPOINT)
}
@@ -1050,6 +1072,7 @@ func (s *Office365Settings) SSOSettings() *SSOSettings {
ssoSettings.Secret = s.Secret
ssoSettings.Id = s.Id
ssoSettings.Scope = s.Scope
ssoSettings.DiscoveryEndpoint = s.DiscoveryEndpoint
ssoSettings.AuthEndpoint = s.AuthEndpoint
ssoSettings.TokenEndpoint = s.TokenEndpoint
ssoSettings.UserApiEndpoint = s.UserApiEndpoint
@@ -2948,6 +2971,7 @@ type Config struct {
GitLabSettings SSOSettings
GoogleSettings SSOSettings
Office365Settings Office365Settings
OpenIdSettings SSOSettings
LdapSettings LdapSettings
ComplianceSettings ComplianceSettings
LocalizationSettings LocalizationSettings
@@ -3004,6 +3028,8 @@ func (o *Config) GetSSOService(service string) *SSOSettings {
return &o.GoogleSettings
case SERVICE_OFFICE365:
return o.Office365Settings.SSOSettings()
case SERVICE_OPENID:
return &o.OpenIdSettings
}
return nil
@@ -3039,8 +3065,10 @@ func (o *Config) SetDefaults() {
o.EmailSettings.SetDefaults(isUpdate)
o.PrivacySettings.setDefaults()
o.Office365Settings.setDefaults()
o.GitLabSettings.setDefaults("", "", "", "")
o.GoogleSettings.setDefaults(GOOGLE_SETTINGS_DEFAULT_SCOPE, GOOGLE_SETTINGS_DEFAULT_AUTH_ENDPOINT, GOOGLE_SETTINGS_DEFAULT_TOKEN_ENDPOINT, GOOGLE_SETTINGS_DEFAULT_USER_API_ENDPOINT)
o.Office365Settings.setDefaults()
o.GitLabSettings.setDefaults("", "", "", "", "")
o.GoogleSettings.setDefaults(GOOGLE_SETTINGS_DEFAULT_SCOPE, GOOGLE_SETTINGS_DEFAULT_AUTH_ENDPOINT, GOOGLE_SETTINGS_DEFAULT_TOKEN_ENDPOINT, GOOGLE_SETTINGS_DEFAULT_USER_API_ENDPOINT, "")
o.OpenIdSettings.setDefaults(OPENID_SETTINGS_DEFAULT_SCOPE, "", "", "", "#145DBF")
o.ServiceSettings.SetDefaults(isUpdate)
o.PasswordSettings.SetDefaults()
o.TeamSettings.SetDefaults()
@@ -3691,6 +3719,10 @@ func (o *Config) Sanitize() {
*o.Office365Settings.Secret = FAKE_SETTING
}
if o.OpenIdSettings.Secret != nil && len(*o.OpenIdSettings.Secret) > 0 {
*o.OpenIdSettings.Secret = FAKE_SETTING
}
*o.SqlSettings.DataSource = FAKE_SETTING
*o.SqlSettings.AtRestEncryptKey = FAKE_SETTING

Просмотреть файл

@@ -1322,6 +1322,7 @@ func TestConfigSanitize(t *testing.T) {
*c.FileSettings.AmazonS3SecretAccessKey = "bar"
*c.EmailSettings.SMTPPassword = "baz"
*c.GitLabSettings.Secret = "bingo"
*c.OpenIdSettings.Secret = "secret"
c.SqlSettings.DataSourceReplicas = []string{"stuff"}
c.SqlSettings.DataSourceSearchReplicas = []string{"stuff"}
@@ -1332,6 +1333,7 @@ func TestConfigSanitize(t *testing.T) {
assert.Equal(t, FAKE_SETTING, *c.FileSettings.AmazonS3SecretAccessKey)
assert.Equal(t, FAKE_SETTING, *c.EmailSettings.SMTPPassword)
assert.Equal(t, FAKE_SETTING, *c.GitLabSettings.Secret)
assert.Equal(t, FAKE_SETTING, *c.OpenIdSettings.Secret)
assert.Equal(t, FAKE_SETTING, *c.SqlSettings.DataSource)
assert.Equal(t, FAKE_SETTING, *c.SqlSettings.AtRestEncryptKey)
assert.Equal(t, FAKE_SETTING, *c.ElasticsearchSettings.Password)

Просмотреть файл

@@ -91,7 +91,7 @@ func (glu *GitLabUser) getAuthData() string {
return strconv.FormatInt(glu.Id, 10)
}
func (m *GitLabProvider) GetUserFromJson(data io.Reader) (*model.User, error) {
func (m *GitLabProvider) GetUserFromJson(data io.Reader, tokenUser *model.User) (*model.User, error) {
glu, err := gitLabUserFromJson(data)
if err != nil {
return nil, err
@@ -102,3 +102,11 @@ func (m *GitLabProvider) GetUserFromJson(data io.Reader) (*model.User, error) {
return userFromGitLabUser(glu), nil
}
func (m *GitLabProvider) GetSSOSettings(config *model.Config, service string) (*model.SSOSettings, error) {
return &config.GitLabSettings, nil
}
func (m *GitLabProvider) GetUserFromIdToken(idToken string) (*model.User, error) {
return nil, nil
}

Просмотреть файл

@@ -63,6 +63,7 @@ type Features struct {
MFA *bool `json:"mfa"`
GoogleOAuth *bool `json:"google_oauth"`
Office365OAuth *bool `json:"office365_oauth"`
OpenId *bool `json:"openid"`
Compliance *bool `json:"compliance"`
Cluster *bool `json:"cluster"`
Metrics *bool `json:"metrics"`
@@ -95,6 +96,7 @@ func (f *Features) ToMap() map[string]interface{} {
"mfa": *f.MFA,
"google": *f.GoogleOAuth,
"office365": *f.Office365OAuth,
"openid": *f.OpenId,
"compliance": *f.Compliance,
"cluster": *f.Cluster,
"metrics": *f.Metrics,
@@ -145,6 +147,10 @@ func (f *Features) SetDefaults() {
f.Office365OAuth = NewBool(*f.FutureFeatures)
}
if f.OpenId == nil {
f.OpenId = NewBool(*f.FutureFeatures)
}
if f.Compliance == nil {
f.Compliance = NewBool(*f.FutureFeatures)
}

Просмотреть файл

@@ -34,14 +34,16 @@ func (o *SwitchRequest) EmailToOAuth() bool {
(o.NewService == USER_AUTH_SERVICE_SAML ||
o.NewService == USER_AUTH_SERVICE_GITLAB ||
o.NewService == SERVICE_GOOGLE ||
o.NewService == SERVICE_OFFICE365)
o.NewService == SERVICE_OFFICE365 ||
o.NewService == SERVICE_OPENID)
}
func (o *SwitchRequest) OAuthToEmail() bool {
return (o.CurrentService == USER_AUTH_SERVICE_SAML ||
o.CurrentService == USER_AUTH_SERVICE_GITLAB ||
o.CurrentService == SERVICE_GOOGLE ||
o.CurrentService == SERVICE_OFFICE365) && o.NewService == USER_AUTH_SERVICE_EMAIL
o.CurrentService == SERVICE_OFFICE365 ||
o.CurrentService == SERVICE_OPENID) && o.NewService == USER_AUTH_SERVICE_EMAIL
}
func (o *SwitchRequest) EmailToLdap() bool {