MM-27688-OpenId Connect (#16222)
* 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>
Этот коммит содержится в:
коммит произвёл
GitHub
родитель
2a71fc5ee2
Коммит
f548ecbee1
@@ -1691,11 +1691,12 @@ func login(c *Context, w http.ResponseWriter, r *http.Request) {
|
|||||||
enableUsername := *config.EmailSettings.EnableSignInWithUsername
|
enableUsername := *config.EmailSettings.EnableSignInWithUsername
|
||||||
enableEmail := *config.EmailSettings.EnableSignInWithEmail
|
enableEmail := *config.EmailSettings.EnableSignInWithEmail
|
||||||
samlEnabled := *config.SamlSettings.Enable
|
samlEnabled := *config.SamlSettings.Enable
|
||||||
gitlabEnabled := *config.GetSSOService("gitlab").Enable
|
gitlabEnabled := *config.GitLabSettings.Enable
|
||||||
googleEnabled := *config.GetSSOService("google").Enable
|
openidEnabled := *config.OpenIdSettings.Enable
|
||||||
|
googleEnabled := *config.GoogleSettings.Enable
|
||||||
office365Enabled := *config.Office365Settings.Enable
|
office365Enabled := *config.Office365Settings.Enable
|
||||||
|
|
||||||
if samlEnabled || gitlabEnabled || googleEnabled || office365Enabled {
|
if samlEnabled || gitlabEnabled || googleEnabled || office365Enabled || openidEnabled {
|
||||||
c.Err = model.NewAppError("login", "api.user.login.invalid_credentials_sso", nil, "", http.StatusUnauthorized)
|
c.Err = model.NewAppError("login", "api.user.login.invalid_credentials_sso", nil, "", http.StatusUnauthorized)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -376,7 +376,7 @@ type AppIface interface {
|
|||||||
AttachDeviceId(sessionId string, deviceId string, expiresAt int64) *model.AppError
|
AttachDeviceId(sessionId string, deviceId string, expiresAt int64) *model.AppError
|
||||||
AttachSessionCookies(w http.ResponseWriter, r *http.Request)
|
AttachSessionCookies(w http.ResponseWriter, r *http.Request)
|
||||||
AuthenticateUserForLogin(id, loginId, password, mfaToken, cwsToken string, ldapOnly bool) (user *model.User, err *model.AppError)
|
AuthenticateUserForLogin(id, loginId, password, mfaToken, cwsToken string, ldapOnly bool) (user *model.User, err *model.AppError)
|
||||||
AuthorizeOAuthUser(w http.ResponseWriter, r *http.Request, service, code, state, redirectUri string) (io.ReadCloser, string, map[string]string, *model.AppError)
|
AuthorizeOAuthUser(w http.ResponseWriter, r *http.Request, service, code, state, redirectUri string) (io.ReadCloser, string, map[string]string, *model.User, *model.AppError)
|
||||||
AutocompleteChannels(teamId string, term string) (*model.ChannelList, *model.AppError)
|
AutocompleteChannels(teamId string, term string) (*model.ChannelList, *model.AppError)
|
||||||
AutocompleteChannelsForSearch(teamId string, userId string, term string) (*model.ChannelList, *model.AppError)
|
AutocompleteChannelsForSearch(teamId string, userId string, term string) (*model.ChannelList, *model.AppError)
|
||||||
AutocompleteUsersInChannel(teamId string, channelId string, term string, options *model.UserSearchOptions) (*model.UserAutocompleteInChannel, *model.AppError)
|
AutocompleteUsersInChannel(teamId string, channelId string, term string, options *model.UserSearchOptions) (*model.UserAutocompleteInChannel, *model.AppError)
|
||||||
@@ -412,8 +412,8 @@ type AppIface interface {
|
|||||||
Cluster() einterfaces.ClusterInterface
|
Cluster() einterfaces.ClusterInterface
|
||||||
CompareAndDeletePluginKey(pluginId string, key string, oldValue []byte) (bool, *model.AppError)
|
CompareAndDeletePluginKey(pluginId string, key string, oldValue []byte) (bool, *model.AppError)
|
||||||
CompareAndSetPluginKey(pluginId string, key string, oldValue, newValue []byte) (bool, *model.AppError)
|
CompareAndSetPluginKey(pluginId string, key string, oldValue, newValue []byte) (bool, *model.AppError)
|
||||||
CompleteOAuth(service string, body io.ReadCloser, teamId string, props map[string]string) (*model.User, *model.AppError)
|
CompleteOAuth(service string, body io.ReadCloser, teamId string, props map[string]string, tokenUser *model.User) (*model.User, *model.AppError)
|
||||||
CompleteSwitchWithOAuth(service string, userData io.Reader, email string) (*model.User, *model.AppError)
|
CompleteSwitchWithOAuth(service string, userData io.Reader, email string, tokenUser *model.User) (*model.User, *model.AppError)
|
||||||
Compliance() einterfaces.ComplianceInterface
|
Compliance() einterfaces.ComplianceInterface
|
||||||
Config() *model.Config
|
Config() *model.Config
|
||||||
Context() context.Context
|
Context() context.Context
|
||||||
@@ -429,7 +429,7 @@ type AppIface interface {
|
|||||||
CreateJob(job *model.Job) (*model.Job, *model.AppError)
|
CreateJob(job *model.Job) (*model.Job, *model.AppError)
|
||||||
CreateOAuthApp(app *model.OAuthApp) (*model.OAuthApp, *model.AppError)
|
CreateOAuthApp(app *model.OAuthApp) (*model.OAuthApp, *model.AppError)
|
||||||
CreateOAuthStateToken(extra string) (*model.Token, *model.AppError)
|
CreateOAuthStateToken(extra string) (*model.Token, *model.AppError)
|
||||||
CreateOAuthUser(service string, userData io.Reader, teamId string) (*model.User, *model.AppError)
|
CreateOAuthUser(service string, userData io.Reader, teamId string, tokenUser *model.User) (*model.User, *model.AppError)
|
||||||
CreateOutgoingWebhook(hook *model.OutgoingWebhook) (*model.OutgoingWebhook, *model.AppError)
|
CreateOutgoingWebhook(hook *model.OutgoingWebhook) (*model.OutgoingWebhook, *model.AppError)
|
||||||
CreatePasswordRecoveryToken(userId, email string) (*model.Token, *model.AppError)
|
CreatePasswordRecoveryToken(userId, email string) (*model.Token, *model.AppError)
|
||||||
CreatePost(post *model.Post, channel *model.Channel, triggerWebhooks, setOnline bool) (savedPost *model.Post, err *model.AppError)
|
CreatePost(post *model.Post, channel *model.Channel, triggerWebhooks, setOnline bool) (savedPost *model.Post, err *model.AppError)
|
||||||
@@ -778,7 +778,7 @@ type AppIface interface {
|
|||||||
ListPluginKeys(pluginId string, page, perPage int) ([]string, *model.AppError)
|
ListPluginKeys(pluginId string, page, perPage int) ([]string, *model.AppError)
|
||||||
ListTeamCommands(teamId string) ([]*model.Command, *model.AppError)
|
ListTeamCommands(teamId string) ([]*model.Command, *model.AppError)
|
||||||
Log() *mlog.Logger
|
Log() *mlog.Logger
|
||||||
LoginByOAuth(service string, userData io.Reader, teamId string) (*model.User, *model.AppError)
|
LoginByOAuth(service string, userData io.Reader, teamId string, tokenUser *model.User) (*model.User, *model.AppError)
|
||||||
MakePermissionError(permissions []*model.Permission) *model.AppError
|
MakePermissionError(permissions []*model.Permission) *model.AppError
|
||||||
MarkChannelsAsViewed(channelIds []string, userId string, currentSessionId string) (map[string]int64, *model.AppError)
|
MarkChannelsAsViewed(channelIds []string, userId string, currentSessionId string) (map[string]int64, *model.AppError)
|
||||||
MaxPostSize() int
|
MaxPostSize() int
|
||||||
@@ -982,7 +982,7 @@ type AppIface interface {
|
|||||||
UpdateLastActivityAtIfNeeded(session model.Session)
|
UpdateLastActivityAtIfNeeded(session model.Session)
|
||||||
UpdateMfa(activate bool, userId, token string) *model.AppError
|
UpdateMfa(activate bool, userId, token string) *model.AppError
|
||||||
UpdateMobileAppBadge(userId string)
|
UpdateMobileAppBadge(userId string)
|
||||||
UpdateOAuthUserAttrs(userData io.Reader, user *model.User, provider einterfaces.OauthProvider, service string) *model.AppError
|
UpdateOAuthUserAttrs(userData io.Reader, user *model.User, provider einterfaces.OauthProvider, service string, tokenUser *model.User) *model.AppError
|
||||||
UpdateOauthApp(oldApp, updatedApp *model.OAuthApp) (*model.OAuthApp, *model.AppError)
|
UpdateOauthApp(oldApp, updatedApp *model.OAuthApp) (*model.OAuthApp, *model.AppError)
|
||||||
UpdateOutgoingWebhook(oldHook, updatedHook *model.OutgoingWebhook) (*model.OutgoingWebhook, *model.AppError)
|
UpdateOutgoingWebhook(oldHook, updatedHook *model.OutgoingWebhook) (*model.OutgoingWebhook, *model.AppError)
|
||||||
UpdatePassword(user *model.User, newPassword string) *model.AppError
|
UpdatePassword(user *model.User, newPassword string) *model.AppError
|
||||||
|
|||||||
124
app/oauth.go
124
app/oauth.go
@@ -26,6 +26,7 @@ import (
|
|||||||
const (
|
const (
|
||||||
OAUTH_COOKIE_MAX_AGE_SECONDS = 30 * 60 // 30 minutes
|
OAUTH_COOKIE_MAX_AGE_SECONDS = 30 * 60 // 30 minutes
|
||||||
COOKIE_OAUTH = "MMOAUTH"
|
COOKIE_OAUTH = "MMOAUTH"
|
||||||
|
OPENID_SCOPE = "openid"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (a *App) CreateOAuthApp(app *model.OAuthApp) (*model.OAuthApp, *model.AppError) {
|
func (a *App) CreateOAuthApp(app *model.OAuthApp) (*model.OAuthApp, *model.AppError) {
|
||||||
@@ -544,52 +545,69 @@ func (a *App) RevokeAccessToken(token string) *model.AppError {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *App) CompleteOAuth(service string, body io.ReadCloser, teamId string, props map[string]string) (*model.User, *model.AppError) {
|
func (a *App) CompleteOAuth(service string, body io.ReadCloser, teamId string, props map[string]string, tokenUser *model.User) (*model.User, *model.AppError) {
|
||||||
defer body.Close()
|
defer body.Close()
|
||||||
|
|
||||||
action := props["action"]
|
action := props["action"]
|
||||||
|
|
||||||
switch action {
|
switch action {
|
||||||
case model.OAUTH_ACTION_SIGNUP:
|
case model.OAUTH_ACTION_SIGNUP:
|
||||||
return a.CreateOAuthUser(service, body, teamId)
|
return a.CreateOAuthUser(service, body, teamId, tokenUser)
|
||||||
case model.OAUTH_ACTION_LOGIN:
|
case model.OAUTH_ACTION_LOGIN:
|
||||||
return a.LoginByOAuth(service, body, teamId)
|
return a.LoginByOAuth(service, body, teamId, tokenUser)
|
||||||
case model.OAUTH_ACTION_EMAIL_TO_SSO:
|
case model.OAUTH_ACTION_EMAIL_TO_SSO:
|
||||||
return a.CompleteSwitchWithOAuth(service, body, props["email"])
|
return a.CompleteSwitchWithOAuth(service, body, props["email"], tokenUser)
|
||||||
case model.OAUTH_ACTION_SSO_TO_EMAIL:
|
case model.OAUTH_ACTION_SSO_TO_EMAIL:
|
||||||
return a.LoginByOAuth(service, body, teamId)
|
return a.LoginByOAuth(service, body, teamId, tokenUser)
|
||||||
default:
|
default:
|
||||||
return a.LoginByOAuth(service, body, teamId)
|
return a.LoginByOAuth(service, body, teamId, tokenUser)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *App) LoginByOAuth(service string, userData io.Reader, teamId string) (*model.User, *model.AppError) {
|
func (a *App) getSSOProvider(service string) (einterfaces.OauthProvider, *model.AppError) {
|
||||||
provider := einterfaces.GetOauthProvider(service)
|
sso := a.Config().GetSSOService(service)
|
||||||
|
if sso == nil || !*sso.Enable {
|
||||||
|
return nil, model.NewAppError("getSSOProvider", "api.user.authorize_oauth_user.unsupported.app_error", nil, "service="+service, http.StatusNotImplemented)
|
||||||
|
}
|
||||||
|
providerType := service
|
||||||
|
if strings.Contains(*sso.Scope, OPENID_SCOPE) {
|
||||||
|
providerType = model.SERVICE_OPENID
|
||||||
|
}
|
||||||
|
provider := einterfaces.GetOauthProvider(providerType)
|
||||||
if provider == nil {
|
if provider == nil {
|
||||||
return nil, model.NewAppError("LoginByOAuth", "api.user.login_by_oauth.not_available.app_error",
|
return nil, model.NewAppError("getSSOProvider", "api.user.login_by_oauth.not_available.app_error",
|
||||||
map[string]interface{}{"Service": strings.Title(service)}, "", http.StatusNotImplemented)
|
map[string]interface{}{"Service": strings.Title(service)}, "", http.StatusNotImplemented)
|
||||||
}
|
}
|
||||||
|
return provider, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *App) LoginByOAuth(service string, userData io.Reader, teamId string, tokenUser *model.User) (*model.User, *model.AppError) {
|
||||||
|
provider, e := a.getSSOProvider(service)
|
||||||
|
if e != nil {
|
||||||
|
return nil, e
|
||||||
|
}
|
||||||
|
|
||||||
buf := bytes.Buffer{}
|
buf := bytes.Buffer{}
|
||||||
if _, err := buf.ReadFrom(userData); err != nil {
|
if _, err := buf.ReadFrom(userData); err != nil {
|
||||||
return nil, model.NewAppError("LoginByOAuth", "api.user.login_by_oauth.parse.app_error",
|
return nil, model.NewAppError("LoginByOAuth2", "api.user.login_by_oauth.parse.app_error",
|
||||||
map[string]interface{}{"Service": service}, "", http.StatusBadRequest)
|
map[string]interface{}{"Service": service}, "", http.StatusBadRequest)
|
||||||
}
|
}
|
||||||
|
|
||||||
authUser, err1 := provider.GetUserFromJson(bytes.NewReader(buf.Bytes()))
|
authUser, err1 := provider.GetUserFromJson(bytes.NewReader(buf.Bytes()), tokenUser)
|
||||||
if err1 != nil {
|
if err1 != nil {
|
||||||
return nil, model.NewAppError("LoginByOAuth", "api.user.login_by_oauth.parse.app_error",
|
return nil, model.NewAppError("LoginByOAuth", "api.user.login_by_oauth.parse.app_error",
|
||||||
map[string]interface{}{"Service": service}, err1.Error(), http.StatusBadRequest)
|
map[string]interface{}{"Service": service}, err1.Error(), http.StatusBadRequest)
|
||||||
}
|
}
|
||||||
|
|
||||||
if *authUser.AuthData == "" {
|
if *authUser.AuthData == "" {
|
||||||
return nil, model.NewAppError("LoginByOAuth", "api.user.login_by_oauth.parse.app_error",
|
return nil, model.NewAppError("LoginByOAuth3", "api.user.login_by_oauth.parse.app_error",
|
||||||
map[string]interface{}{"Service": service}, "", http.StatusBadRequest)
|
map[string]interface{}{"Service": service}, "", http.StatusBadRequest)
|
||||||
}
|
}
|
||||||
|
|
||||||
user, err := a.GetUserByAuth(model.NewString(*authUser.AuthData), service)
|
user, err := a.GetUserByAuth(model.NewString(*authUser.AuthData), service)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if err.Id == MISSING_AUTH_ACCOUNT_ERROR {
|
if err.Id == MISSING_AUTH_ACCOUNT_ERROR {
|
||||||
user, err = a.CreateOAuthUser(service, bytes.NewReader(buf.Bytes()), teamId)
|
user, err = a.CreateOAuthUser(service, bytes.NewReader(buf.Bytes()), teamId, tokenUser)
|
||||||
} else {
|
} else {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -601,7 +619,7 @@ func (a *App) LoginByOAuth(service string, userData io.Reader, teamId string) (*
|
|||||||
return nil, model.NewAppError("loginByOAuth", "api.user.login_by_oauth.bot_login_forbidden.app_error", nil, "", http.StatusForbidden)
|
return nil, model.NewAppError("loginByOAuth", "api.user.login_by_oauth.bot_login_forbidden.app_error", nil, "", http.StatusForbidden)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = a.UpdateOAuthUserAttrs(bytes.NewReader(buf.Bytes()), user, provider, service); err != nil {
|
if err = a.UpdateOAuthUserAttrs(bytes.NewReader(buf.Bytes()), user, provider, service, tokenUser); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if len(teamId) > 0 {
|
if len(teamId) > 0 {
|
||||||
@@ -616,18 +634,17 @@ func (a *App) LoginByOAuth(service string, userData io.Reader, teamId string) (*
|
|||||||
return user, nil
|
return user, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *App) CompleteSwitchWithOAuth(service string, userData io.Reader, email string) (*model.User, *model.AppError) {
|
func (a *App) CompleteSwitchWithOAuth(service string, userData io.Reader, email string, tokenUser *model.User) (*model.User, *model.AppError) {
|
||||||
provider := einterfaces.GetOauthProvider(service)
|
provider, e := a.getSSOProvider(service)
|
||||||
if provider == nil {
|
if e != nil {
|
||||||
return nil, model.NewAppError("CompleteSwitchWithOAuth", "api.user.complete_switch_with_oauth.unavailable.app_error",
|
return nil, e
|
||||||
map[string]interface{}{"Service": strings.Title(service)}, "", http.StatusNotImplemented)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if email == "" {
|
if email == "" {
|
||||||
return nil, model.NewAppError("CompleteSwitchWithOAuth", "api.user.complete_switch_with_oauth.blank_email.app_error", nil, "", http.StatusBadRequest)
|
return nil, model.NewAppError("CompleteSwitchWithOAuth", "api.user.complete_switch_with_oauth.blank_email.app_error", nil, "", http.StatusBadRequest)
|
||||||
}
|
}
|
||||||
|
|
||||||
ssoUser, err1 := provider.GetUserFromJson(userData)
|
ssoUser, err1 := provider.GetUserFromJson(userData, tokenUser)
|
||||||
if err1 != nil {
|
if err1 != nil {
|
||||||
return nil, model.NewAppError("CompleteSwitchWithOAuth", "api.user.complete_switch_with_oauth.parse.app_error",
|
return nil, model.NewAppError("CompleteSwitchWithOAuth", "api.user.complete_switch_with_oauth.parse.app_error",
|
||||||
map[string]interface{}{"Service": service}, err1.Error(), http.StatusBadRequest)
|
map[string]interface{}{"Service": service}, err1.Error(), http.StatusBadRequest)
|
||||||
@@ -696,9 +713,14 @@ func (a *App) GetOAuthStateToken(token string) (*model.Token, *model.AppError) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (a *App) GetAuthorizationCode(w http.ResponseWriter, r *http.Request, service string, props map[string]string, loginHint string) (string, *model.AppError) {
|
func (a *App) GetAuthorizationCode(w http.ResponseWriter, r *http.Request, service string, props map[string]string, loginHint string) (string, *model.AppError) {
|
||||||
sso := a.Config().GetSSOService(service)
|
provider, e := a.getSSOProvider(service)
|
||||||
if sso == nil || !*sso.Enable {
|
if e != nil {
|
||||||
return "", model.NewAppError("GetAuthorizationCode", "api.user.get_authorization_code.unsupported.app_error", nil, "service="+service, http.StatusNotImplemented)
|
return "", e
|
||||||
|
}
|
||||||
|
|
||||||
|
sso, e2 := provider.GetSSOSettings(a.Config(), service)
|
||||||
|
if e2 != nil {
|
||||||
|
return "", model.NewAppError("GetAuthorizationCode.GetSSOSettings", "api.user.get_authorization_code.endpoint.app_error", nil, e.Error(), http.StatusNotImplemented)
|
||||||
}
|
}
|
||||||
|
|
||||||
secure := false
|
secure := false
|
||||||
@@ -755,40 +777,44 @@ func (a *App) GetAuthorizationCode(w http.ResponseWriter, r *http.Request, servi
|
|||||||
return authUrl, nil
|
return authUrl, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *App) AuthorizeOAuthUser(w http.ResponseWriter, r *http.Request, service, code, state, redirectUri string) (io.ReadCloser, string, map[string]string, *model.AppError) {
|
func (a *App) AuthorizeOAuthUser(w http.ResponseWriter, r *http.Request, service, code, state, redirectUri string) (io.ReadCloser, string, map[string]string, *model.User, *model.AppError) {
|
||||||
sso := a.Config().GetSSOService(service)
|
provider, e := a.getSSOProvider(service)
|
||||||
if sso == nil || !*sso.Enable {
|
if e != nil {
|
||||||
return nil, "", nil, model.NewAppError("AuthorizeOAuthUser", "api.user.authorize_oauth_user.unsupported.app_error", nil, "service="+service, http.StatusNotImplemented)
|
return nil, "", nil, nil, e
|
||||||
|
}
|
||||||
|
|
||||||
|
sso, e2 := provider.GetSSOSettings(a.Config(), service)
|
||||||
|
if e2 != nil {
|
||||||
|
return nil, "", nil, nil, model.NewAppError("GetAuthorizationCode.GetSSOSettings", "api.user.get_authorization_code.endpoint.app_error", nil, e.Error(), http.StatusNotImplemented)
|
||||||
}
|
}
|
||||||
|
|
||||||
b, strErr := b64.StdEncoding.DecodeString(state)
|
b, strErr := b64.StdEncoding.DecodeString(state)
|
||||||
if strErr != nil {
|
if strErr != nil {
|
||||||
return nil, "", nil, model.NewAppError("AuthorizeOAuthUser", "api.user.authorize_oauth_user.invalid_state.app_error", nil, strErr.Error(), http.StatusBadRequest)
|
return nil, "", nil, nil, model.NewAppError("AuthorizeOAuthUser", "api.user.authorize_oauth_user.invalid_state.app_error", nil, strErr.Error(), http.StatusBadRequest)
|
||||||
}
|
}
|
||||||
|
|
||||||
stateStr := string(b)
|
stateStr := string(b)
|
||||||
|
|
||||||
stateProps := model.MapFromJson(strings.NewReader(stateStr))
|
stateProps := model.MapFromJson(strings.NewReader(stateStr))
|
||||||
|
|
||||||
expectedToken, appErr := a.GetOAuthStateToken(stateProps["token"])
|
expectedToken, appErr := a.GetOAuthStateToken(stateProps["token"])
|
||||||
if appErr != nil {
|
if appErr != nil {
|
||||||
return nil, "", stateProps, appErr
|
return nil, "", stateProps, nil, appErr
|
||||||
}
|
}
|
||||||
|
|
||||||
stateEmail := stateProps["email"]
|
stateEmail := stateProps["email"]
|
||||||
stateAction := stateProps["action"]
|
stateAction := stateProps["action"]
|
||||||
if stateAction == model.OAUTH_ACTION_EMAIL_TO_SSO && stateEmail == "" {
|
if stateAction == model.OAUTH_ACTION_EMAIL_TO_SSO && stateEmail == "" {
|
||||||
return nil, "", stateProps, model.NewAppError("AuthorizeOAuthUser", "api.user.authorize_oauth_user.invalid_state.app_error", nil, "", http.StatusBadRequest)
|
return nil, "", stateProps, nil, model.NewAppError("AuthorizeOAuthUser", "api.user.authorize_oauth_user.invalid_state.app_error", nil, "", http.StatusBadRequest)
|
||||||
}
|
}
|
||||||
|
|
||||||
cookie, cookieErr := r.Cookie(COOKIE_OAUTH)
|
cookie, cookieErr := r.Cookie(COOKIE_OAUTH)
|
||||||
if cookieErr != nil {
|
if cookieErr != nil {
|
||||||
return nil, "", stateProps, model.NewAppError("AuthorizeOAuthUser", "api.user.authorize_oauth_user.invalid_state.app_error", nil, "", http.StatusBadRequest)
|
return nil, "", stateProps, nil, model.NewAppError("AuthorizeOAuthUser", "api.user.authorize_oauth_user.invalid_state.app_error", nil, "", http.StatusBadRequest)
|
||||||
}
|
}
|
||||||
|
|
||||||
expectedTokenExtra := generateOAuthStateTokenExtra(stateEmail, stateAction, cookie.Value)
|
expectedTokenExtra := generateOAuthStateTokenExtra(stateEmail, stateAction, cookie.Value)
|
||||||
if expectedTokenExtra != expectedToken.Extra {
|
if expectedTokenExtra != expectedToken.Extra {
|
||||||
return nil, "", stateProps, model.NewAppError("AuthorizeOAuthUser", "api.user.authorize_oauth_user.invalid_state.app_error", nil, "", http.StatusBadRequest)
|
return nil, "", stateProps, nil, model.NewAppError("AuthorizeOAuthUser", "api.user.authorize_oauth_user.invalid_state.app_error", nil, "", http.StatusBadRequest)
|
||||||
}
|
}
|
||||||
|
|
||||||
appErr = a.DeleteToken(expectedToken)
|
appErr = a.DeleteToken(expectedToken)
|
||||||
@@ -819,7 +845,7 @@ func (a *App) AuthorizeOAuthUser(w http.ResponseWriter, r *http.Request, service
|
|||||||
|
|
||||||
req, requestErr := http.NewRequest("POST", *sso.TokenEndpoint, strings.NewReader(p.Encode()))
|
req, requestErr := http.NewRequest("POST", *sso.TokenEndpoint, strings.NewReader(p.Encode()))
|
||||||
if requestErr != nil {
|
if requestErr != nil {
|
||||||
return nil, "", stateProps, model.NewAppError("AuthorizeOAuthUser", "api.user.authorize_oauth_user.token_failed.app_error", nil, requestErr.Error(), http.StatusInternalServerError)
|
return nil, "", stateProps, nil, model.NewAppError("AuthorizeOAuthUser", "api.user.authorize_oauth_user.token_failed.app_error", nil, requestErr.Error(), http.StatusInternalServerError)
|
||||||
}
|
}
|
||||||
|
|
||||||
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
|
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
|
||||||
@@ -827,31 +853,39 @@ func (a *App) AuthorizeOAuthUser(w http.ResponseWriter, r *http.Request, service
|
|||||||
|
|
||||||
resp, err := a.HTTPService().MakeClient(true).Do(req)
|
resp, err := a.HTTPService().MakeClient(true).Do(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, "", stateProps, model.NewAppError("AuthorizeOAuthUser", "api.user.authorize_oauth_user.token_failed.app_error", nil, err.Error(), http.StatusInternalServerError)
|
return nil, "", stateProps, nil, model.NewAppError("AuthorizeOAuthUser", "api.user.authorize_oauth_user.token_failed.app_error", nil, err.Error(), http.StatusInternalServerError)
|
||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
|
|
||||||
var buf bytes.Buffer
|
var buf bytes.Buffer
|
||||||
tee := io.TeeReader(resp.Body, &buf)
|
tee := io.TeeReader(resp.Body, &buf)
|
||||||
ar := model.AccessResponseFromJson(tee)
|
ar := model.AccessResponseFromJson(tee)
|
||||||
|
|
||||||
if ar == nil || resp.StatusCode != http.StatusOK {
|
if ar == nil || resp.StatusCode != http.StatusOK {
|
||||||
return nil, "", stateProps, model.NewAppError("AuthorizeOAuthUser", "api.user.authorize_oauth_user.bad_response.app_error", nil, fmt.Sprintf("response_body=%s, status_code=%d", buf.String(), resp.StatusCode), http.StatusInternalServerError)
|
return nil, "", stateProps, nil, model.NewAppError("AuthorizeOAuthUser", "api.user.authorize_oauth_user.bad_response.app_error", nil, fmt.Sprintf("response_body=%s, status_code=%d", buf.String(), resp.StatusCode), http.StatusInternalServerError)
|
||||||
}
|
}
|
||||||
|
|
||||||
if strings.ToLower(ar.TokenType) != model.ACCESS_TOKEN_TYPE {
|
if strings.ToLower(ar.TokenType) != model.ACCESS_TOKEN_TYPE {
|
||||||
return nil, "", stateProps, model.NewAppError("AuthorizeOAuthUser", "api.user.authorize_oauth_user.bad_token.app_error", nil, "token_type="+ar.TokenType+", response_body="+buf.String(), http.StatusInternalServerError)
|
return nil, "", stateProps, nil, model.NewAppError("AuthorizeOAuthUser", "api.user.authorize_oauth_user.bad_token.app_error", nil, "token_type="+ar.TokenType+", response_body="+buf.String(), http.StatusInternalServerError)
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(ar.AccessToken) == 0 {
|
if len(ar.AccessToken) == 0 {
|
||||||
return nil, "", stateProps, model.NewAppError("AuthorizeOAuthUser", "api.user.authorize_oauth_user.missing.app_error", nil, "response_body="+buf.String(), http.StatusInternalServerError)
|
return nil, "", stateProps, nil, model.NewAppError("AuthorizeOAuthUser", "api.user.authorize_oauth_user.missing.app_error", nil, "response_body="+buf.String(), http.StatusInternalServerError)
|
||||||
}
|
}
|
||||||
|
|
||||||
p = url.Values{}
|
p = url.Values{}
|
||||||
p.Set("access_token", ar.AccessToken)
|
p.Set("access_token", ar.AccessToken)
|
||||||
|
|
||||||
|
var userFromToken *model.User
|
||||||
|
if ar.IdToken != "" {
|
||||||
|
userFromToken, err = provider.GetUserFromIdToken(ar.IdToken)
|
||||||
|
if err != nil {
|
||||||
|
return nil, "", stateProps, nil, model.NewAppError("AuthorizeOAuthUser", "api.user.authorize_oauth_user.token_failed.app_error", nil, e.Error(), http.StatusInternalServerError)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
req, requestErr = http.NewRequest("GET", *sso.UserApiEndpoint, strings.NewReader(""))
|
req, requestErr = http.NewRequest("GET", *sso.UserApiEndpoint, strings.NewReader(""))
|
||||||
if requestErr != nil {
|
if requestErr != nil {
|
||||||
return nil, "", stateProps, model.NewAppError("AuthorizeOAuthUser", "api.user.authorize_oauth_user.service.app_error", map[string]interface{}{"Service": service}, requestErr.Error(), http.StatusInternalServerError)
|
return nil, "", stateProps, nil, model.NewAppError("AuthorizeOAuthUser", "api.user.authorize_oauth_user.service.app_error", map[string]interface{}{"Service": service}, requestErr.Error(), http.StatusInternalServerError)
|
||||||
}
|
}
|
||||||
|
|
||||||
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
|
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
|
||||||
@@ -860,7 +894,7 @@ func (a *App) AuthorizeOAuthUser(w http.ResponseWriter, r *http.Request, service
|
|||||||
|
|
||||||
resp, err = a.HTTPService().MakeClient(true).Do(req)
|
resp, err = a.HTTPService().MakeClient(true).Do(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, "", stateProps, model.NewAppError("AuthorizeOAuthUser", "api.user.authorize_oauth_user.service.app_error", map[string]interface{}{"Service": service}, err.Error(), http.StatusInternalServerError)
|
return nil, "", stateProps, nil, model.NewAppError("AuthorizeOAuthUser", "api.user.authorize_oauth_user.service.app_error", map[string]interface{}{"Service": service}, err.Error(), http.StatusInternalServerError)
|
||||||
} else if resp.StatusCode != http.StatusOK {
|
} else if resp.StatusCode != http.StatusOK {
|
||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
|
|
||||||
@@ -868,18 +902,18 @@ func (a *App) AuthorizeOAuthUser(w http.ResponseWriter, r *http.Request, service
|
|||||||
bodyBytes, _ := ioutil.ReadAll(resp.Body)
|
bodyBytes, _ := ioutil.ReadAll(resp.Body)
|
||||||
bodyString := string(bodyBytes)
|
bodyString := string(bodyBytes)
|
||||||
|
|
||||||
mlog.Error("Error getting OAuth user", mlog.String("body_string", bodyString))
|
mlog.Error("Error getting OAuth user", mlog.Int("response", resp.StatusCode), mlog.String("body_string", bodyString))
|
||||||
|
|
||||||
if service == model.SERVICE_GITLAB && resp.StatusCode == http.StatusForbidden && strings.Contains(bodyString, "Terms of Service") {
|
if service == model.SERVICE_GITLAB && resp.StatusCode == http.StatusForbidden && strings.Contains(bodyString, "Terms of Service") {
|
||||||
// Return a nicer error when the user hasn't accepted GitLab's terms of service
|
// Return a nicer error when the user hasn't accepted GitLab's terms of service
|
||||||
return nil, "", stateProps, model.NewAppError("AuthorizeOAuthUser", "oauth.gitlab.tos.error", nil, "", http.StatusBadRequest)
|
return nil, "", stateProps, nil, model.NewAppError("AuthorizeOAuthUser", "oauth.gitlab.tos.error", nil, "", http.StatusBadRequest)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil, "", stateProps, model.NewAppError("AuthorizeOAuthUser", "api.user.authorize_oauth_user.response.app_error", nil, "response_body="+bodyString, http.StatusInternalServerError)
|
return nil, "", stateProps, nil, model.NewAppError("AuthorizeOAuthUser", "api.user.authorize_oauth_user.response.app_error", nil, "response_body="+bodyString, http.StatusInternalServerError)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Note that resp.Body is not closed here, so it must be closed by the caller
|
// Note that resp.Body is not closed here, so it must be closed by the caller
|
||||||
return resp.Body, teamId, stateProps, nil
|
return resp.Body, teamId, stateProps, userFromToken, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *App) SwitchEmailToOAuth(w http.ResponseWriter, r *http.Request, email, password, code, service string) (string, *model.AppError) {
|
func (a *App) SwitchEmailToOAuth(w http.ResponseWriter, r *http.Request, email, password, code, service string) (string, *model.AppError) {
|
||||||
|
|||||||
@@ -191,7 +191,7 @@ func TestAuthorizeOAuthUser(t *testing.T) {
|
|||||||
th := setup(t, false, true, true, "")
|
th := setup(t, false, true, true, "")
|
||||||
defer th.TearDown()
|
defer th.TearDown()
|
||||||
|
|
||||||
_, _, _, err := th.App.AuthorizeOAuthUser(nil, nil, model.SERVICE_GITLAB, "", "", "")
|
_, _, _, _, err := th.App.AuthorizeOAuthUser(nil, nil, model.SERVICE_GITLAB, "", "", "")
|
||||||
require.NotNil(t, err)
|
require.NotNil(t, err)
|
||||||
assert.Equal(t, "api.user.authorize_oauth_user.unsupported.app_error", err.Id)
|
assert.Equal(t, "api.user.authorize_oauth_user.unsupported.app_error", err.Id)
|
||||||
})
|
})
|
||||||
@@ -202,7 +202,7 @@ func TestAuthorizeOAuthUser(t *testing.T) {
|
|||||||
|
|
||||||
state := "!"
|
state := "!"
|
||||||
|
|
||||||
_, _, _, err := th.App.AuthorizeOAuthUser(nil, nil, model.SERVICE_GITLAB, "", state, "")
|
_, _, _, _, err := th.App.AuthorizeOAuthUser(nil, nil, model.SERVICE_GITLAB, "", state, "")
|
||||||
require.NotNil(t, err)
|
require.NotNil(t, err)
|
||||||
assert.Equal(t, "api.user.authorize_oauth_user.invalid_state.app_error", err.Id)
|
assert.Equal(t, "api.user.authorize_oauth_user.invalid_state.app_error", err.Id)
|
||||||
})
|
})
|
||||||
@@ -215,7 +215,7 @@ func TestAuthorizeOAuthUser(t *testing.T) {
|
|||||||
"token": model.NewId(),
|
"token": model.NewId(),
|
||||||
})))
|
})))
|
||||||
|
|
||||||
_, _, _, err := th.App.AuthorizeOAuthUser(nil, nil, model.SERVICE_GITLAB, "", state, "")
|
_, _, _, _, err := th.App.AuthorizeOAuthUser(nil, nil, model.SERVICE_GITLAB, "", state, "")
|
||||||
require.NotNil(t, err)
|
require.NotNil(t, err)
|
||||||
assert.Equal(t, "api.oauth.invalid_state_token.app_error", err.Id)
|
assert.Equal(t, "api.oauth.invalid_state_token.app_error", err.Id)
|
||||||
assert.NotEqual(t, "", err.DetailedError)
|
assert.NotEqual(t, "", err.DetailedError)
|
||||||
@@ -230,7 +230,7 @@ func TestAuthorizeOAuthUser(t *testing.T) {
|
|||||||
|
|
||||||
state := makeState(token)
|
state := makeState(token)
|
||||||
|
|
||||||
_, _, _, err := th.App.AuthorizeOAuthUser(nil, nil, model.SERVICE_GITLAB, "", state, "")
|
_, _, _, _, err := th.App.AuthorizeOAuthUser(nil, nil, model.SERVICE_GITLAB, "", state, "")
|
||||||
require.NotNil(t, err)
|
require.NotNil(t, err)
|
||||||
assert.Equal(t, "api.oauth.invalid_state_token.app_error", err.Id)
|
assert.Equal(t, "api.oauth.invalid_state_token.app_error", err.Id)
|
||||||
assert.Equal(t, "", err.DetailedError)
|
assert.Equal(t, "", err.DetailedError)
|
||||||
@@ -253,7 +253,7 @@ func TestAuthorizeOAuthUser(t *testing.T) {
|
|||||||
"token": token.Token,
|
"token": token.Token,
|
||||||
})))
|
})))
|
||||||
|
|
||||||
_, _, _, err = th.App.AuthorizeOAuthUser(nil, nil, model.SERVICE_GITLAB, "", state, "")
|
_, _, _, _, err = th.App.AuthorizeOAuthUser(nil, nil, model.SERVICE_GITLAB, "", state, "")
|
||||||
require.NotNil(t, err)
|
require.NotNil(t, err)
|
||||||
assert.Equal(t, "api.user.authorize_oauth_user.invalid_state.app_error", err.Id)
|
assert.Equal(t, "api.user.authorize_oauth_user.invalid_state.app_error", err.Id)
|
||||||
})
|
})
|
||||||
@@ -266,7 +266,7 @@ func TestAuthorizeOAuthUser(t *testing.T) {
|
|||||||
request := makeRequest(t, "")
|
request := makeRequest(t, "")
|
||||||
state := makeState(makeToken(th, cookie))
|
state := makeState(makeToken(th, cookie))
|
||||||
|
|
||||||
_, _, _, err := th.App.AuthorizeOAuthUser(nil, request, model.SERVICE_GITLAB, "", state, "")
|
_, _, _, _, err := th.App.AuthorizeOAuthUser(nil, request, model.SERVICE_GITLAB, "", state, "")
|
||||||
require.NotNil(t, err)
|
require.NotNil(t, err)
|
||||||
assert.Equal(t, "api.user.authorize_oauth_user.invalid_state.app_error", err.Id)
|
assert.Equal(t, "api.user.authorize_oauth_user.invalid_state.app_error", err.Id)
|
||||||
})
|
})
|
||||||
@@ -283,7 +283,7 @@ func TestAuthorizeOAuthUser(t *testing.T) {
|
|||||||
request := makeRequest(t, cookie)
|
request := makeRequest(t, cookie)
|
||||||
state := makeState(token)
|
state := makeState(token)
|
||||||
|
|
||||||
_, _, _, err = th.App.AuthorizeOAuthUser(nil, request, model.SERVICE_GITLAB, "", state, "")
|
_, _, _, _, err = th.App.AuthorizeOAuthUser(nil, request, model.SERVICE_GITLAB, "", state, "")
|
||||||
require.NotNil(t, err)
|
require.NotNil(t, err)
|
||||||
assert.Equal(t, "api.user.authorize_oauth_user.invalid_state.app_error", err.Id)
|
assert.Equal(t, "api.user.authorize_oauth_user.invalid_state.app_error", err.Id)
|
||||||
})
|
})
|
||||||
@@ -296,7 +296,7 @@ func TestAuthorizeOAuthUser(t *testing.T) {
|
|||||||
request := makeRequest(t, cookie)
|
request := makeRequest(t, cookie)
|
||||||
state := makeState(makeToken(th, cookie))
|
state := makeState(makeToken(th, cookie))
|
||||||
|
|
||||||
_, _, _, err := th.App.AuthorizeOAuthUser(&httptest.ResponseRecorder{}, request, model.SERVICE_GITLAB, "", state, "")
|
_, _, _, _, err := th.App.AuthorizeOAuthUser(&httptest.ResponseRecorder{}, request, model.SERVICE_GITLAB, "", state, "")
|
||||||
require.NotNil(t, err)
|
require.NotNil(t, err)
|
||||||
assert.Equal(t, "api.user.authorize_oauth_user.token_failed.app_error", err.Id)
|
assert.Equal(t, "api.user.authorize_oauth_user.token_failed.app_error", err.Id)
|
||||||
})
|
})
|
||||||
@@ -314,7 +314,7 @@ func TestAuthorizeOAuthUser(t *testing.T) {
|
|||||||
request := makeRequest(t, cookie)
|
request := makeRequest(t, cookie)
|
||||||
state := makeState(makeToken(th, cookie))
|
state := makeState(makeToken(th, cookie))
|
||||||
|
|
||||||
_, _, _, err := th.App.AuthorizeOAuthUser(&httptest.ResponseRecorder{}, request, model.SERVICE_GITLAB, "", state, "")
|
_, _, _, _, err := th.App.AuthorizeOAuthUser(&httptest.ResponseRecorder{}, request, model.SERVICE_GITLAB, "", state, "")
|
||||||
require.NotNil(t, err)
|
require.NotNil(t, err)
|
||||||
assert.Equal(t, "api.user.authorize_oauth_user.bad_response.app_error", err.Id)
|
assert.Equal(t, "api.user.authorize_oauth_user.bad_response.app_error", err.Id)
|
||||||
assert.Contains(t, err.DetailedError, "status_code=418")
|
assert.Contains(t, err.DetailedError, "status_code=418")
|
||||||
@@ -333,7 +333,7 @@ func TestAuthorizeOAuthUser(t *testing.T) {
|
|||||||
request := makeRequest(t, cookie)
|
request := makeRequest(t, cookie)
|
||||||
state := makeState(makeToken(th, cookie))
|
state := makeState(makeToken(th, cookie))
|
||||||
|
|
||||||
_, _, _, err := th.App.AuthorizeOAuthUser(&httptest.ResponseRecorder{}, request, model.SERVICE_GITLAB, "", state, "")
|
_, _, _, _, err := th.App.AuthorizeOAuthUser(&httptest.ResponseRecorder{}, request, model.SERVICE_GITLAB, "", state, "")
|
||||||
require.NotNil(t, err)
|
require.NotNil(t, err)
|
||||||
assert.Equal(t, "api.user.authorize_oauth_user.bad_response.app_error", err.Id)
|
assert.Equal(t, "api.user.authorize_oauth_user.bad_response.app_error", err.Id)
|
||||||
assert.Contains(t, err.DetailedError, "response_body=invalid")
|
assert.Contains(t, err.DetailedError, "response_body=invalid")
|
||||||
@@ -355,7 +355,7 @@ func TestAuthorizeOAuthUser(t *testing.T) {
|
|||||||
request := makeRequest(t, cookie)
|
request := makeRequest(t, cookie)
|
||||||
state := makeState(makeToken(th, cookie))
|
state := makeState(makeToken(th, cookie))
|
||||||
|
|
||||||
_, _, _, err := th.App.AuthorizeOAuthUser(&httptest.ResponseRecorder{}, request, model.SERVICE_GITLAB, "", state, "")
|
_, _, _, _, err := th.App.AuthorizeOAuthUser(&httptest.ResponseRecorder{}, request, model.SERVICE_GITLAB, "", state, "")
|
||||||
require.NotNil(t, err)
|
require.NotNil(t, err)
|
||||||
assert.Equal(t, "api.user.authorize_oauth_user.bad_token.app_error", err.Id)
|
assert.Equal(t, "api.user.authorize_oauth_user.bad_token.app_error", err.Id)
|
||||||
})
|
})
|
||||||
@@ -376,7 +376,7 @@ func TestAuthorizeOAuthUser(t *testing.T) {
|
|||||||
request := makeRequest(t, cookie)
|
request := makeRequest(t, cookie)
|
||||||
state := makeState(makeToken(th, cookie))
|
state := makeState(makeToken(th, cookie))
|
||||||
|
|
||||||
_, _, _, err := th.App.AuthorizeOAuthUser(&httptest.ResponseRecorder{}, request, model.SERVICE_GITLAB, "", state, "")
|
_, _, _, _, err := th.App.AuthorizeOAuthUser(&httptest.ResponseRecorder{}, request, model.SERVICE_GITLAB, "", state, "")
|
||||||
require.NotNil(t, err)
|
require.NotNil(t, err)
|
||||||
assert.Equal(t, "api.user.authorize_oauth_user.missing.app_error", err.Id)
|
assert.Equal(t, "api.user.authorize_oauth_user.missing.app_error", err.Id)
|
||||||
})
|
})
|
||||||
@@ -397,7 +397,7 @@ func TestAuthorizeOAuthUser(t *testing.T) {
|
|||||||
request := makeRequest(t, cookie)
|
request := makeRequest(t, cookie)
|
||||||
state := makeState(makeToken(th, cookie))
|
state := makeState(makeToken(th, cookie))
|
||||||
|
|
||||||
_, _, _, err := th.App.AuthorizeOAuthUser(&httptest.ResponseRecorder{}, request, model.SERVICE_GITLAB, "", state, "")
|
_, _, _, _, err := th.App.AuthorizeOAuthUser(&httptest.ResponseRecorder{}, request, model.SERVICE_GITLAB, "", state, "")
|
||||||
require.NotNil(t, err)
|
require.NotNil(t, err)
|
||||||
assert.Equal(t, "api.user.authorize_oauth_user.service.app_error", err.Id)
|
assert.Equal(t, "api.user.authorize_oauth_user.service.app_error", err.Id)
|
||||||
})
|
})
|
||||||
@@ -425,7 +425,7 @@ func TestAuthorizeOAuthUser(t *testing.T) {
|
|||||||
request := makeRequest(t, cookie)
|
request := makeRequest(t, cookie)
|
||||||
state := makeState(makeToken(th, cookie))
|
state := makeState(makeToken(th, cookie))
|
||||||
|
|
||||||
_, _, _, err := th.App.AuthorizeOAuthUser(&httptest.ResponseRecorder{}, request, model.SERVICE_GITLAB, "", state, "")
|
_, _, _, _, err := th.App.AuthorizeOAuthUser(&httptest.ResponseRecorder{}, request, model.SERVICE_GITLAB, "", state, "")
|
||||||
require.NotNil(t, err)
|
require.NotNil(t, err)
|
||||||
assert.Equal(t, "api.user.authorize_oauth_user.response.app_error", err.Id)
|
assert.Equal(t, "api.user.authorize_oauth_user.response.app_error", err.Id)
|
||||||
})
|
})
|
||||||
@@ -454,7 +454,7 @@ func TestAuthorizeOAuthUser(t *testing.T) {
|
|||||||
request := makeRequest(t, cookie)
|
request := makeRequest(t, cookie)
|
||||||
state := makeState(makeToken(th, cookie))
|
state := makeState(makeToken(th, cookie))
|
||||||
|
|
||||||
_, _, _, err := th.App.AuthorizeOAuthUser(&httptest.ResponseRecorder{}, request, model.SERVICE_GITLAB, "", state, "")
|
_, _, _, _, err := th.App.AuthorizeOAuthUser(&httptest.ResponseRecorder{}, request, model.SERVICE_GITLAB, "", state, "")
|
||||||
require.NotNil(t, err)
|
require.NotNil(t, err)
|
||||||
assert.Equal(t, "oauth.gitlab.tos.error", err.Id)
|
assert.Equal(t, "oauth.gitlab.tos.error", err.Id)
|
||||||
})
|
})
|
||||||
@@ -504,7 +504,7 @@ func TestAuthorizeOAuthUser(t *testing.T) {
|
|||||||
state := base64.StdEncoding.EncodeToString([]byte(model.MapToJson(stateProps)))
|
state := base64.StdEncoding.EncodeToString([]byte(model.MapToJson(stateProps)))
|
||||||
|
|
||||||
recorder := httptest.ResponseRecorder{}
|
recorder := httptest.ResponseRecorder{}
|
||||||
body, receivedTeamId, receivedStateProps, err := th.App.AuthorizeOAuthUser(&recorder, request, model.SERVICE_GITLAB, "", state, "")
|
body, receivedTeamId, receivedStateProps, _, err := th.App.AuthorizeOAuthUser(&recorder, request, model.SERVICE_GITLAB, "", state, "")
|
||||||
|
|
||||||
require.NotNil(t, body)
|
require.NotNil(t, body)
|
||||||
bodyBytes, bodyErr := ioutil.ReadAll(body)
|
bodyBytes, bodyErr := ioutil.ReadAll(body)
|
||||||
@@ -533,7 +533,8 @@ func TestGetAuthorizationCode(t *testing.T) {
|
|||||||
|
|
||||||
_, err := th.App.GetAuthorizationCode(nil, nil, model.SERVICE_GITLAB, map[string]string{}, "")
|
_, err := th.App.GetAuthorizationCode(nil, nil, model.SERVICE_GITLAB, map[string]string{}, "")
|
||||||
require.NotNil(t, err)
|
require.NotNil(t, err)
|
||||||
assert.Equal(t, "api.user.get_authorization_code.unsupported.app_error", err.Id)
|
|
||||||
|
assert.Equal(t, "api.user.authorize_oauth_user.unsupported.app_error", err.Id)
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("enabled and properly configured", func(t *testing.T) {
|
t.Run("enabled and properly configured", func(t *testing.T) {
|
||||||
|
|||||||
@@ -687,7 +687,7 @@ func (a *OpenTracingAppLayer) AuthenticateUserForLogin(id string, loginId string
|
|||||||
return resultVar0, resultVar1
|
return resultVar0, resultVar1
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *OpenTracingAppLayer) AuthorizeOAuthUser(w http.ResponseWriter, r *http.Request, service string, code string, state string, redirectUri string) (io.ReadCloser, string, map[string]string, *model.AppError) {
|
func (a *OpenTracingAppLayer) AuthorizeOAuthUser(w http.ResponseWriter, r *http.Request, service string, code string, state string, redirectUri string) (io.ReadCloser, string, map[string]string, *model.User, *model.AppError) {
|
||||||
origCtx := a.ctx
|
origCtx := a.ctx
|
||||||
span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.AuthorizeOAuthUser")
|
span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.AuthorizeOAuthUser")
|
||||||
|
|
||||||
@@ -699,14 +699,14 @@ func (a *OpenTracingAppLayer) AuthorizeOAuthUser(w http.ResponseWriter, r *http.
|
|||||||
}()
|
}()
|
||||||
|
|
||||||
defer span.Finish()
|
defer span.Finish()
|
||||||
resultVar0, resultVar1, resultVar2, resultVar3 := a.app.AuthorizeOAuthUser(w, r, service, code, state, redirectUri)
|
resultVar0, resultVar1, resultVar2, resultVar3, resultVar4 := a.app.AuthorizeOAuthUser(w, r, service, code, state, redirectUri)
|
||||||
|
|
||||||
if resultVar3 != nil {
|
if resultVar4 != nil {
|
||||||
span.LogFields(spanlog.Error(resultVar3))
|
span.LogFields(spanlog.Error(resultVar4))
|
||||||
ext.Error.Set(span, true)
|
ext.Error.Set(span, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
return resultVar0, resultVar1, resultVar2, resultVar3
|
return resultVar0, resultVar1, resultVar2, resultVar3, resultVar4
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *OpenTracingAppLayer) AutocompleteChannels(teamId string, term string) (*model.ChannelList, *model.AppError) {
|
func (a *OpenTracingAppLayer) AutocompleteChannels(teamId string, term string) (*model.ChannelList, *model.AppError) {
|
||||||
@@ -1427,7 +1427,7 @@ func (a *OpenTracingAppLayer) CompareAndSetPluginKey(pluginId string, key string
|
|||||||
return resultVar0, resultVar1
|
return resultVar0, resultVar1
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *OpenTracingAppLayer) CompleteOAuth(service string, body io.ReadCloser, teamId string, props map[string]string) (*model.User, *model.AppError) {
|
func (a *OpenTracingAppLayer) CompleteOAuth(service string, body io.ReadCloser, teamId string, props map[string]string, tokenUser *model.User) (*model.User, *model.AppError) {
|
||||||
origCtx := a.ctx
|
origCtx := a.ctx
|
||||||
span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.CompleteOAuth")
|
span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.CompleteOAuth")
|
||||||
|
|
||||||
@@ -1439,7 +1439,7 @@ func (a *OpenTracingAppLayer) CompleteOAuth(service string, body io.ReadCloser,
|
|||||||
}()
|
}()
|
||||||
|
|
||||||
defer span.Finish()
|
defer span.Finish()
|
||||||
resultVar0, resultVar1 := a.app.CompleteOAuth(service, body, teamId, props)
|
resultVar0, resultVar1 := a.app.CompleteOAuth(service, body, teamId, props, tokenUser)
|
||||||
|
|
||||||
if resultVar1 != nil {
|
if resultVar1 != nil {
|
||||||
span.LogFields(spanlog.Error(resultVar1))
|
span.LogFields(spanlog.Error(resultVar1))
|
||||||
@@ -1449,7 +1449,7 @@ func (a *OpenTracingAppLayer) CompleteOAuth(service string, body io.ReadCloser,
|
|||||||
return resultVar0, resultVar1
|
return resultVar0, resultVar1
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *OpenTracingAppLayer) CompleteSwitchWithOAuth(service string, userData io.Reader, email string) (*model.User, *model.AppError) {
|
func (a *OpenTracingAppLayer) CompleteSwitchWithOAuth(service string, userData io.Reader, email string, tokenUser *model.User) (*model.User, *model.AppError) {
|
||||||
origCtx := a.ctx
|
origCtx := a.ctx
|
||||||
span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.CompleteSwitchWithOAuth")
|
span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.CompleteSwitchWithOAuth")
|
||||||
|
|
||||||
@@ -1461,7 +1461,7 @@ func (a *OpenTracingAppLayer) CompleteSwitchWithOAuth(service string, userData i
|
|||||||
}()
|
}()
|
||||||
|
|
||||||
defer span.Finish()
|
defer span.Finish()
|
||||||
resultVar0, resultVar1 := a.app.CompleteSwitchWithOAuth(service, userData, email)
|
resultVar0, resultVar1 := a.app.CompleteSwitchWithOAuth(service, userData, email, tokenUser)
|
||||||
|
|
||||||
if resultVar1 != nil {
|
if resultVar1 != nil {
|
||||||
span.LogFields(spanlog.Error(resultVar1))
|
span.LogFields(spanlog.Error(resultVar1))
|
||||||
@@ -1932,7 +1932,7 @@ func (a *OpenTracingAppLayer) CreateOAuthStateToken(extra string) (*model.Token,
|
|||||||
return resultVar0, resultVar1
|
return resultVar0, resultVar1
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *OpenTracingAppLayer) CreateOAuthUser(service string, userData io.Reader, teamId string) (*model.User, *model.AppError) {
|
func (a *OpenTracingAppLayer) CreateOAuthUser(service string, userData io.Reader, teamId string, tokenUser *model.User) (*model.User, *model.AppError) {
|
||||||
origCtx := a.ctx
|
origCtx := a.ctx
|
||||||
span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.CreateOAuthUser")
|
span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.CreateOAuthUser")
|
||||||
|
|
||||||
@@ -1944,7 +1944,7 @@ func (a *OpenTracingAppLayer) CreateOAuthUser(service string, userData io.Reader
|
|||||||
}()
|
}()
|
||||||
|
|
||||||
defer span.Finish()
|
defer span.Finish()
|
||||||
resultVar0, resultVar1 := a.app.CreateOAuthUser(service, userData, teamId)
|
resultVar0, resultVar1 := a.app.CreateOAuthUser(service, userData, teamId, tokenUser)
|
||||||
|
|
||||||
if resultVar1 != nil {
|
if resultVar1 != nil {
|
||||||
span.LogFields(spanlog.Error(resultVar1))
|
span.LogFields(spanlog.Error(resultVar1))
|
||||||
@@ -10392,7 +10392,7 @@ func (a *OpenTracingAppLayer) LogAuditRecWithLevel(rec *audit.Record, level mlog
|
|||||||
a.app.LogAuditRecWithLevel(rec, level, err)
|
a.app.LogAuditRecWithLevel(rec, level, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *OpenTracingAppLayer) LoginByOAuth(service string, userData io.Reader, teamId string) (*model.User, *model.AppError) {
|
func (a *OpenTracingAppLayer) LoginByOAuth(service string, userData io.Reader, teamId string, tokenUser *model.User) (*model.User, *model.AppError) {
|
||||||
origCtx := a.ctx
|
origCtx := a.ctx
|
||||||
span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.LoginByOAuth")
|
span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.LoginByOAuth")
|
||||||
|
|
||||||
@@ -10404,7 +10404,7 @@ func (a *OpenTracingAppLayer) LoginByOAuth(service string, userData io.Reader, t
|
|||||||
}()
|
}()
|
||||||
|
|
||||||
defer span.Finish()
|
defer span.Finish()
|
||||||
resultVar0, resultVar1 := a.app.LoginByOAuth(service, userData, teamId)
|
resultVar0, resultVar1 := a.app.LoginByOAuth(service, userData, teamId, tokenUser)
|
||||||
|
|
||||||
if resultVar1 != nil {
|
if resultVar1 != nil {
|
||||||
span.LogFields(spanlog.Error(resultVar1))
|
span.LogFields(spanlog.Error(resultVar1))
|
||||||
@@ -14864,7 +14864,7 @@ func (a *OpenTracingAppLayer) UpdateMobileAppBadge(userId string) {
|
|||||||
a.app.UpdateMobileAppBadge(userId)
|
a.app.UpdateMobileAppBadge(userId)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *OpenTracingAppLayer) UpdateOAuthUserAttrs(userData io.Reader, user *model.User, provider einterfaces.OauthProvider, service string) *model.AppError {
|
func (a *OpenTracingAppLayer) UpdateOAuthUserAttrs(userData io.Reader, user *model.User, provider einterfaces.OauthProvider, service string, tokenUser *model.User) *model.AppError {
|
||||||
origCtx := a.ctx
|
origCtx := a.ctx
|
||||||
span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.UpdateOAuthUserAttrs")
|
span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.UpdateOAuthUserAttrs")
|
||||||
|
|
||||||
@@ -14876,7 +14876,7 @@ func (a *OpenTracingAppLayer) UpdateOAuthUserAttrs(userData io.Reader, user *mod
|
|||||||
}()
|
}()
|
||||||
|
|
||||||
defer span.Finish()
|
defer span.Finish()
|
||||||
resultVar0 := a.app.UpdateOAuthUserAttrs(userData, user, provider, service)
|
resultVar0 := a.app.UpdateOAuthUserAttrs(userData, user, provider, service, tokenUser)
|
||||||
|
|
||||||
if resultVar0 != nil {
|
if resultVar0 != nil {
|
||||||
span.LogFields(spanlog.Error(resultVar0))
|
span.LogFields(spanlog.Error(resultVar0))
|
||||||
|
|||||||
17
app/user.go
17
app/user.go
@@ -335,19 +335,22 @@ func (a *App) createUser(user *model.User) (*model.User, *model.AppError) {
|
|||||||
return ruser, nil
|
return ruser, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *App) CreateOAuthUser(service string, userData io.Reader, teamId string) (*model.User, *model.AppError) {
|
func (a *App) CreateOAuthUser(service string, userData io.Reader, teamId string, tokenUser *model.User) (*model.User, *model.AppError) {
|
||||||
if !*a.Config().TeamSettings.EnableUserCreation {
|
if !*a.Config().TeamSettings.EnableUserCreation {
|
||||||
return nil, model.NewAppError("CreateOAuthUser", "api.user.create_user.disabled.app_error", nil, "", http.StatusNotImplemented)
|
return nil, model.NewAppError("CreateOAuthUser", "api.user.create_user.disabled.app_error", nil, "", http.StatusNotImplemented)
|
||||||
}
|
}
|
||||||
|
|
||||||
provider := einterfaces.GetOauthProvider(service)
|
provider, e := a.getSSOProvider(service)
|
||||||
if provider == nil {
|
if e != nil {
|
||||||
return nil, model.NewAppError("CreateOAuthUser", "api.user.create_oauth_user.not_available.app_error", map[string]interface{}{"Service": strings.Title(service)}, "", http.StatusNotImplemented)
|
return nil, e
|
||||||
}
|
}
|
||||||
user, err1 := provider.GetUserFromJson(userData)
|
user, err1 := provider.GetUserFromJson(userData, tokenUser)
|
||||||
if err1 != nil {
|
if err1 != nil {
|
||||||
return nil, model.NewAppError("CreateOAuthUser", "api.user.create_oauth_user.create.app_error", map[string]interface{}{"Service": service}, err1.Error(), http.StatusInternalServerError)
|
return nil, model.NewAppError("CreateOAuthUser", "api.user.create_oauth_user.create.app_error", map[string]interface{}{"Service": service}, err1.Error(), http.StatusInternalServerError)
|
||||||
}
|
}
|
||||||
|
if user.AuthService == "" {
|
||||||
|
user.AuthService = service
|
||||||
|
}
|
||||||
|
|
||||||
suchan := make(chan store.StoreResult, 1)
|
suchan := make(chan store.StoreResult, 1)
|
||||||
euchan := make(chan store.StoreResult, 1)
|
euchan := make(chan store.StoreResult, 1)
|
||||||
@@ -1990,8 +1993,8 @@ func (a *App) AutocompleteUsersInTeam(teamId string, term string, options *model
|
|||||||
return autocomplete, nil
|
return autocomplete, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *App) UpdateOAuthUserAttrs(userData io.Reader, user *model.User, provider einterfaces.OauthProvider, service string) *model.AppError {
|
func (a *App) UpdateOAuthUserAttrs(userData io.Reader, user *model.User, provider einterfaces.OauthProvider, service string, tokenUser *model.User) *model.AppError {
|
||||||
oauthUser, err1 := provider.GetUserFromJson(userData)
|
oauthUser, err1 := provider.GetUserFromJson(userData, tokenUser)
|
||||||
if err1 != nil {
|
if err1 != nil {
|
||||||
return model.NewAppError("UpdateOAuthUserAttrs", "api.user.update_oauth_user_attrs.get_user.app_error", map[string]interface{}{"Service": service}, err1.Error(), http.StatusBadRequest)
|
return model.NewAppError("UpdateOAuthUserAttrs", "api.user.update_oauth_user_attrs.get_user.app_error", map[string]interface{}{"Service": service}, err1.Error(), http.StatusBadRequest)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -76,10 +76,14 @@ func TestCreateOAuthUser(t *testing.T) {
|
|||||||
th := Setup(t).InitBasic()
|
th := Setup(t).InitBasic()
|
||||||
defer th.TearDown()
|
defer th.TearDown()
|
||||||
|
|
||||||
|
th.App.UpdateConfig(func(cfg *model.Config) {
|
||||||
|
*cfg.GitLabSettings.Enable = true
|
||||||
|
})
|
||||||
|
|
||||||
glUser := oauthgitlab.GitLabUser{Id: 42, Username: "o" + model.NewId(), Email: model.NewId() + "@simulator.amazonses.com", Name: "Joram Wilander"}
|
glUser := oauthgitlab.GitLabUser{Id: 42, Username: "o" + model.NewId(), Email: model.NewId() + "@simulator.amazonses.com", Name: "Joram Wilander"}
|
||||||
|
|
||||||
json := glUser.ToJson()
|
json := glUser.ToJson()
|
||||||
user, err := th.App.CreateOAuthUser(model.USER_AUTH_SERVICE_GITLAB, strings.NewReader(json), th.BasicTeam.Id)
|
user, err := th.App.CreateOAuthUser(model.USER_AUTH_SERVICE_GITLAB, strings.NewReader(json), th.BasicTeam.Id, nil)
|
||||||
require.Nil(t, err)
|
require.Nil(t, err)
|
||||||
|
|
||||||
require.Equal(t, glUser.Username, user.Username, "usernames didn't match")
|
require.Equal(t, glUser.Username, user.Username, "usernames didn't match")
|
||||||
@@ -88,7 +92,7 @@ func TestCreateOAuthUser(t *testing.T) {
|
|||||||
|
|
||||||
*th.App.Config().TeamSettings.EnableUserCreation = false
|
*th.App.Config().TeamSettings.EnableUserCreation = false
|
||||||
|
|
||||||
_, err = th.App.CreateOAuthUser(model.USER_AUTH_SERVICE_GITLAB, strings.NewReader(json), th.BasicTeam.Id)
|
_, err = th.App.CreateOAuthUser(model.USER_AUTH_SERVICE_GITLAB, strings.NewReader(json), th.BasicTeam.Id, nil)
|
||||||
require.NotNil(t, err, "should have failed - user creation disabled")
|
require.NotNil(t, err, "should have failed - user creation disabled")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -269,6 +273,9 @@ func TestUpdateOAuthUserAttrs(t *testing.T) {
|
|||||||
|
|
||||||
id := model.NewId()
|
id := model.NewId()
|
||||||
id2 := model.NewId()
|
id2 := model.NewId()
|
||||||
|
th.App.UpdateConfig(func(cfg *model.Config) {
|
||||||
|
*cfg.GitLabSettings.Enable = true
|
||||||
|
})
|
||||||
gitlabProvider := einterfaces.GetOauthProvider("gitlab")
|
gitlabProvider := einterfaces.GetOauthProvider("gitlab")
|
||||||
|
|
||||||
username := "user" + id
|
username := "user" + id
|
||||||
@@ -289,7 +296,7 @@ func TestUpdateOAuthUserAttrs(t *testing.T) {
|
|||||||
data := bytes.NewReader(gitlabUser)
|
data := bytes.NewReader(gitlabUser)
|
||||||
|
|
||||||
user = getUserFromDB(th.App, user.Id, t)
|
user = getUserFromDB(th.App, user.Id, t)
|
||||||
th.App.UpdateOAuthUserAttrs(data, user, gitlabProvider, "gitlab")
|
th.App.UpdateOAuthUserAttrs(data, user, gitlabProvider, "gitlab", nil)
|
||||||
user = getUserFromDB(th.App, user.Id, t)
|
user = getUserFromDB(th.App, user.Id, t)
|
||||||
|
|
||||||
require.Equal(t, gitlabUserObj.Username, user.Username, "user's username is not updated")
|
require.Equal(t, gitlabUserObj.Username, user.Username, "user's username is not updated")
|
||||||
@@ -302,7 +309,7 @@ func TestUpdateOAuthUserAttrs(t *testing.T) {
|
|||||||
data := bytes.NewReader(gitlabUser)
|
data := bytes.NewReader(gitlabUser)
|
||||||
|
|
||||||
user = getUserFromDB(th.App, user.Id, t)
|
user = getUserFromDB(th.App, user.Id, t)
|
||||||
th.App.UpdateOAuthUserAttrs(data, user, gitlabProvider, "gitlab")
|
th.App.UpdateOAuthUserAttrs(data, user, gitlabProvider, "gitlab", nil)
|
||||||
user = getUserFromDB(th.App, user.Id, t)
|
user = getUserFromDB(th.App, user.Id, t)
|
||||||
|
|
||||||
require.NotEqual(t, gitlabUserObj.Username, user.Username, "user's username is updated though there already exists another user with the same username")
|
require.NotEqual(t, gitlabUserObj.Username, user.Username, "user's username is updated though there already exists another user with the same username")
|
||||||
@@ -316,7 +323,7 @@ func TestUpdateOAuthUserAttrs(t *testing.T) {
|
|||||||
data := bytes.NewReader(gitlabUser)
|
data := bytes.NewReader(gitlabUser)
|
||||||
|
|
||||||
user = getUserFromDB(th.App, user.Id, t)
|
user = getUserFromDB(th.App, user.Id, t)
|
||||||
th.App.UpdateOAuthUserAttrs(data, user, gitlabProvider, "gitlab")
|
th.App.UpdateOAuthUserAttrs(data, user, gitlabProvider, "gitlab", nil)
|
||||||
user = getUserFromDB(th.App, user.Id, t)
|
user = getUserFromDB(th.App, user.Id, t)
|
||||||
|
|
||||||
require.Equal(t, gitlabUserObj.Email, user.Email, "user's email is not updated")
|
require.Equal(t, gitlabUserObj.Email, user.Email, "user's email is not updated")
|
||||||
@@ -331,7 +338,7 @@ func TestUpdateOAuthUserAttrs(t *testing.T) {
|
|||||||
data := bytes.NewReader(gitlabUser)
|
data := bytes.NewReader(gitlabUser)
|
||||||
|
|
||||||
user = getUserFromDB(th.App, user.Id, t)
|
user = getUserFromDB(th.App, user.Id, t)
|
||||||
th.App.UpdateOAuthUserAttrs(data, user, gitlabProvider, "gitlab")
|
th.App.UpdateOAuthUserAttrs(data, user, gitlabProvider, "gitlab", nil)
|
||||||
user = getUserFromDB(th.App, user.Id, t)
|
user = getUserFromDB(th.App, user.Id, t)
|
||||||
|
|
||||||
require.NotEqual(t, gitlabUserObj.Email, user.Email, "user's email is updated though there already exists another user with the same email")
|
require.NotEqual(t, gitlabUserObj.Email, user.Email, "user's email is updated though there already exists another user with the same email")
|
||||||
@@ -344,7 +351,7 @@ func TestUpdateOAuthUserAttrs(t *testing.T) {
|
|||||||
data := bytes.NewReader(gitlabUser)
|
data := bytes.NewReader(gitlabUser)
|
||||||
|
|
||||||
user = getUserFromDB(th.App, user.Id, t)
|
user = getUserFromDB(th.App, user.Id, t)
|
||||||
th.App.UpdateOAuthUserAttrs(data, user, gitlabProvider, "gitlab")
|
th.App.UpdateOAuthUserAttrs(data, user, gitlabProvider, "gitlab", nil)
|
||||||
user = getUserFromDB(th.App, user.Id, t)
|
user = getUserFromDB(th.App, user.Id, t)
|
||||||
|
|
||||||
require.Equal(t, "Updated", user.FirstName, "user's first name is not updated")
|
require.Equal(t, "Updated", user.FirstName, "user's first name is not updated")
|
||||||
@@ -356,7 +363,7 @@ func TestUpdateOAuthUserAttrs(t *testing.T) {
|
|||||||
data := bytes.NewReader(gitlabUser)
|
data := bytes.NewReader(gitlabUser)
|
||||||
|
|
||||||
user = getUserFromDB(th.App, user.Id, t)
|
user = getUserFromDB(th.App, user.Id, t)
|
||||||
th.App.UpdateOAuthUserAttrs(data, user, gitlabProvider, "gitlab")
|
th.App.UpdateOAuthUserAttrs(data, user, gitlabProvider, "gitlab", nil)
|
||||||
user = getUserFromDB(th.App, user.Id, t)
|
user = getUserFromDB(th.App, user.Id, t)
|
||||||
|
|
||||||
require.Equal(t, "Lastname", user.LastName, "user's last name is not updated")
|
require.Equal(t, "Lastname", user.LastName, "user's last name is not updated")
|
||||||
@@ -532,7 +539,7 @@ func createGitlabUser(t *testing.T, a *App, id int64, username string, email str
|
|||||||
var user *model.User
|
var user *model.User
|
||||||
var err *model.AppError
|
var err *model.AppError
|
||||||
|
|
||||||
user, err = a.CreateOAuthUser("gitlab", bytes.NewReader(gitlabUser), "")
|
user, err = a.CreateOAuthUser("gitlab", bytes.NewReader(gitlabUser), "", nil)
|
||||||
require.Nil(t, err, "unable to create the user", err)
|
require.Nil(t, err, "unable to create the user", err)
|
||||||
|
|
||||||
return user, gitlabUserObj
|
return user, gitlabUserObj
|
||||||
|
|||||||
@@ -288,6 +288,9 @@ func GenerateLimitedClientConfig(c *model.Config, telemetryID string, license *m
|
|||||||
props["SamlLoginButtonTextColor"] = ""
|
props["SamlLoginButtonTextColor"] = ""
|
||||||
props["EnableSignUpWithGoogle"] = "false"
|
props["EnableSignUpWithGoogle"] = "false"
|
||||||
props["EnableSignUpWithOffice365"] = "false"
|
props["EnableSignUpWithOffice365"] = "false"
|
||||||
|
props["EnableSignUpWithOpenId"] = "false"
|
||||||
|
props["OpenIdButtonText"] = ""
|
||||||
|
props["OpenIdButtonColor"] = ""
|
||||||
props["CWSUrl"] = ""
|
props["CWSUrl"] = ""
|
||||||
props["EnableCustomBrand"] = strconv.FormatBool(*c.TeamSettings.EnableCustomBrand)
|
props["EnableCustomBrand"] = strconv.FormatBool(*c.TeamSettings.EnableCustomBrand)
|
||||||
props["CustomBrandText"] = *c.TeamSettings.CustomBrandText
|
props["CustomBrandText"] = *c.TeamSettings.CustomBrandText
|
||||||
@@ -322,6 +325,12 @@ func GenerateLimitedClientConfig(c *model.Config, telemetryID string, license *m
|
|||||||
props["EnableSignUpWithOffice365"] = strconv.FormatBool(*c.Office365Settings.Enable)
|
props["EnableSignUpWithOffice365"] = strconv.FormatBool(*c.Office365Settings.Enable)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if *license.Features.OpenId {
|
||||||
|
props["EnableSignUpWithOpenId"] = strconv.FormatBool(*c.OpenIdSettings.Enable)
|
||||||
|
props["OpenIdButtonColor"] = *c.OpenIdSettings.ButtonColor
|
||||||
|
props["OpenIdButtonText"] = *c.OpenIdSettings.ButtonText
|
||||||
|
}
|
||||||
|
|
||||||
if *license.Features.CustomTermsOfService {
|
if *license.Features.CustomTermsOfService {
|
||||||
props["EnableCustomTermsOfService"] = strconv.FormatBool(*c.SupportSettings.CustomTermsOfServiceEnabled)
|
props["EnableCustomTermsOfService"] = strconv.FormatBool(*c.SupportSettings.CustomTermsOfServiceEnabled)
|
||||||
props["CustomTermsOfServiceReAcceptancePeriod"] = strconv.FormatInt(int64(*c.SupportSettings.CustomTermsOfServiceReAcceptancePeriod), 10)
|
props["CustomTermsOfServiceReAcceptancePeriod"] = strconv.FormatInt(int64(*c.SupportSettings.CustomTermsOfServiceReAcceptancePeriod), 10)
|
||||||
|
|||||||
@@ -42,6 +42,10 @@ func desanitize(actual, target *model.Config) {
|
|||||||
target.Office365Settings.Secret = actual.Office365Settings.Secret
|
target.Office365Settings.Secret = actual.Office365Settings.Secret
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if target.OpenIdSettings.Secret != nil && *target.OpenIdSettings.Secret == model.FAKE_SETTING {
|
||||||
|
target.OpenIdSettings.Secret = actual.OpenIdSettings.Secret
|
||||||
|
}
|
||||||
|
|
||||||
if *target.SqlSettings.DataSource == model.FAKE_SETTING {
|
if *target.SqlSettings.DataSource == model.FAKE_SETTING {
|
||||||
*target.SqlSettings.DataSource = *actual.SqlSettings.DataSource
|
*target.SqlSettings.DataSource = *actual.SqlSettings.DataSource
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ func TestDesanitize(t *testing.T) {
|
|||||||
actual.FileSettings.AmazonS3SecretAccessKey = sToP("amazon_s3_secret_access_key")
|
actual.FileSettings.AmazonS3SecretAccessKey = sToP("amazon_s3_secret_access_key")
|
||||||
actual.EmailSettings.SMTPPassword = sToP("smtp_password")
|
actual.EmailSettings.SMTPPassword = sToP("smtp_password")
|
||||||
actual.GitLabSettings.Secret = sToP("secret")
|
actual.GitLabSettings.Secret = sToP("secret")
|
||||||
|
actual.OpenIdSettings.Secret = sToP("secret")
|
||||||
actual.SqlSettings.DataSource = sToP("data_source")
|
actual.SqlSettings.DataSource = sToP("data_source")
|
||||||
actual.SqlSettings.AtRestEncryptKey = sToP("at_rest_encrypt_key")
|
actual.SqlSettings.AtRestEncryptKey = sToP("at_rest_encrypt_key")
|
||||||
actual.ElasticsearchSettings.Password = sToP("password")
|
actual.ElasticsearchSettings.Password = sToP("password")
|
||||||
@@ -46,6 +47,7 @@ func TestDesanitize(t *testing.T) {
|
|||||||
target.FileSettings.AmazonS3SecretAccessKey = sToP(model.FAKE_SETTING)
|
target.FileSettings.AmazonS3SecretAccessKey = sToP(model.FAKE_SETTING)
|
||||||
target.EmailSettings.SMTPPassword = sToP(model.FAKE_SETTING)
|
target.EmailSettings.SMTPPassword = sToP(model.FAKE_SETTING)
|
||||||
target.GitLabSettings.Secret = sToP(model.FAKE_SETTING)
|
target.GitLabSettings.Secret = sToP(model.FAKE_SETTING)
|
||||||
|
target.OpenIdSettings.Secret = sToP(model.FAKE_SETTING)
|
||||||
target.SqlSettings.DataSource = sToP(model.FAKE_SETTING)
|
target.SqlSettings.DataSource = sToP(model.FAKE_SETTING)
|
||||||
target.SqlSettings.AtRestEncryptKey = sToP(model.FAKE_SETTING)
|
target.SqlSettings.AtRestEncryptKey = sToP(model.FAKE_SETTING)
|
||||||
target.ElasticsearchSettings.Password = sToP(model.FAKE_SETTING)
|
target.ElasticsearchSettings.Password = sToP(model.FAKE_SETTING)
|
||||||
@@ -66,6 +68,7 @@ func TestDesanitize(t *testing.T) {
|
|||||||
assert.Equal(t, *actual.FileSettings.AmazonS3SecretAccessKey, *target.FileSettings.AmazonS3SecretAccessKey)
|
assert.Equal(t, *actual.FileSettings.AmazonS3SecretAccessKey, *target.FileSettings.AmazonS3SecretAccessKey)
|
||||||
assert.Equal(t, *actual.EmailSettings.SMTPPassword, *target.EmailSettings.SMTPPassword)
|
assert.Equal(t, *actual.EmailSettings.SMTPPassword, *target.EmailSettings.SMTPPassword)
|
||||||
assert.Equal(t, *actual.GitLabSettings.Secret, *target.GitLabSettings.Secret)
|
assert.Equal(t, *actual.GitLabSettings.Secret, *target.GitLabSettings.Secret)
|
||||||
|
assert.Equal(t, *actual.OpenIdSettings.Secret, *target.OpenIdSettings.Secret)
|
||||||
assert.Equal(t, *actual.SqlSettings.DataSource, *target.SqlSettings.DataSource)
|
assert.Equal(t, *actual.SqlSettings.DataSource, *target.SqlSettings.DataSource)
|
||||||
assert.Equal(t, *actual.SqlSettings.AtRestEncryptKey, *target.SqlSettings.AtRestEncryptKey)
|
assert.Equal(t, *actual.SqlSettings.AtRestEncryptKey, *target.SqlSettings.AtRestEncryptKey)
|
||||||
assert.Equal(t, *actual.ElasticsearchSettings.Password, *target.ElasticsearchSettings.Password)
|
assert.Equal(t, *actual.ElasticsearchSettings.Password, *target.ElasticsearchSettings.Password)
|
||||||
|
|||||||
@@ -10,7 +10,9 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type OauthProvider interface {
|
type OauthProvider interface {
|
||||||
GetUserFromJson(data io.Reader) (*model.User, error)
|
GetUserFromJson(data io.Reader, tokenUser *model.User) (*model.User, error)
|
||||||
|
GetSSOSettings(config *model.Config, service string) (*model.SSOSettings, error)
|
||||||
|
GetUserFromIdToken(idToken string) (*model.User, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
var oauthProviders = make(map[string]OauthProvider)
|
var oauthProviders = make(map[string]OauthProvider)
|
||||||
|
|||||||
14
i18n/en.json
14
i18n/en.json
@@ -3148,7 +3148,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "api.user.authorize_oauth_user.unsupported.app_error",
|
"id": "api.user.authorize_oauth_user.unsupported.app_error",
|
||||||
"translation": "Unsupported OAuth service provider."
|
"translation": "{{.Service}} SSO through OAuth 2.0 not available on this server."
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "api.user.autocomplete_users.missing_team_id.app_error",
|
"id": "api.user.autocomplete_users.missing_team_id.app_error",
|
||||||
@@ -3174,10 +3174,6 @@
|
|||||||
"id": "api.user.complete_switch_with_oauth.parse.app_error",
|
"id": "api.user.complete_switch_with_oauth.parse.app_error",
|
||||||
"translation": "Could not parse auth data out of {{.Service}} user object."
|
"translation": "Could not parse auth data out of {{.Service}} user object."
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"id": "api.user.complete_switch_with_oauth.unavailable.app_error",
|
|
||||||
"translation": "{{.Service}} SSO through OAuth 2.0 not available on this server."
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"id": "api.user.create_email_token.error",
|
"id": "api.user.create_email_token.error",
|
||||||
"translation": "Failed to create token data for email verification"
|
"translation": "Failed to create token data for email verification"
|
||||||
@@ -3190,10 +3186,6 @@
|
|||||||
"id": "api.user.create_oauth_user.create.app_error",
|
"id": "api.user.create_oauth_user.create.app_error",
|
||||||
"translation": "Could not create user out of {{.Service}} user object."
|
"translation": "Could not create user out of {{.Service}} user object."
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"id": "api.user.create_oauth_user.not_available.app_error",
|
|
||||||
"translation": "{{.Service}} SSO through OAuth 2.0 not available on this server."
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"id": "api.user.create_password_token.error",
|
"id": "api.user.create_password_token.error",
|
||||||
"translation": "Unable to create password recovery token"
|
"translation": "Unable to create password recovery token"
|
||||||
@@ -3271,8 +3263,8 @@
|
|||||||
"translation": "Authentication Transfer not configured or available on this server."
|
"translation": "Authentication Transfer not configured or available on this server."
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "api.user.get_authorization_code.unsupported.app_error",
|
"id": "api.user.get_authorization_code.endpoint.app_error",
|
||||||
"translation": "Unsupported OAuth service provider."
|
"translation": ""
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "api.user.get_uploads_for_user.forbidden.app_error",
|
"id": "api.user.get_uploads_for_user.forbidden.app_error",
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ type AccessResponse struct {
|
|||||||
ExpiresIn int32 `json:"expires_in"`
|
ExpiresIn int32 `json:"expires_in"`
|
||||||
Scope string `json:"scope"`
|
Scope string `json:"scope"`
|
||||||
RefreshToken string `json:"refresh_token"`
|
RefreshToken string `json:"refresh_token"`
|
||||||
|
IdToken string `json:"id_token"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsValid validates the AccessData and returns an error if it isn't configured
|
// IsValid validates the AccessData and returns an error if it isn't configured
|
||||||
|
|||||||
@@ -45,6 +45,7 @@ const (
|
|||||||
SERVICE_GITLAB = "gitlab"
|
SERVICE_GITLAB = "gitlab"
|
||||||
SERVICE_GOOGLE = "google"
|
SERVICE_GOOGLE = "google"
|
||||||
SERVICE_OFFICE365 = "office365"
|
SERVICE_OFFICE365 = "office365"
|
||||||
|
SERVICE_OPENID = "openid"
|
||||||
|
|
||||||
GENERIC_NO_CHANNEL_NOTIFICATION = "generic_no_channel"
|
GENERIC_NO_CHANNEL_NOTIFICATION = "generic_no_channel"
|
||||||
GENERIC_NOTIFICATION = "generic"
|
GENERIC_NOTIFICATION = "generic"
|
||||||
@@ -230,6 +231,7 @@ const (
|
|||||||
OFFICE365_SETTINGS_DEFAULT_USER_API_ENDPOINT = "https://graph.microsoft.com/v1.0/me"
|
OFFICE365_SETTINGS_DEFAULT_USER_API_ENDPOINT = "https://graph.microsoft.com/v1.0/me"
|
||||||
|
|
||||||
CLOUD_SETTINGS_DEFAULT_CWS_URL = "https://customers.mattermost.com"
|
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"
|
LOCAL_MODE_SOCKET_PATH = "/var/tmp/mattermost_local.socket"
|
||||||
)
|
)
|
||||||
@@ -960,16 +962,19 @@ func (s *AnalyticsSettings) SetDefaults() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type SSOSettings struct {
|
type SSOSettings struct {
|
||||||
Enable *bool `access:"authentication"`
|
Enable *bool `access:"authentication"`
|
||||||
Secret *string `access:"authentication"`
|
Secret *string `access:"authentication"`
|
||||||
Id *string `access:"authentication"`
|
Id *string `access:"authentication"`
|
||||||
Scope *string `access:"authentication"`
|
Scope *string `access:"authentication"`
|
||||||
AuthEndpoint *string `access:"authentication"`
|
AuthEndpoint *string `access:"authentication"`
|
||||||
TokenEndpoint *string `access:"authentication"`
|
TokenEndpoint *string `access:"authentication"`
|
||||||
UserApiEndpoint *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 {
|
if s.Enable == nil {
|
||||||
s.Enable = NewBool(false)
|
s.Enable = NewBool(false)
|
||||||
}
|
}
|
||||||
@@ -986,6 +991,10 @@ func (s *SSOSettings) setDefaults(scope, authEndpoint, tokenEndpoint, userApiEnd
|
|||||||
s.Scope = NewString(scope)
|
s.Scope = NewString(scope)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if s.DiscoveryEndpoint == nil {
|
||||||
|
s.DiscoveryEndpoint = NewString("")
|
||||||
|
}
|
||||||
|
|
||||||
if s.AuthEndpoint == nil {
|
if s.AuthEndpoint == nil {
|
||||||
s.AuthEndpoint = NewString(authEndpoint)
|
s.AuthEndpoint = NewString(authEndpoint)
|
||||||
}
|
}
|
||||||
@@ -997,17 +1006,26 @@ func (s *SSOSettings) setDefaults(scope, authEndpoint, tokenEndpoint, userApiEnd
|
|||||||
if s.UserApiEndpoint == nil {
|
if s.UserApiEndpoint == nil {
|
||||||
s.UserApiEndpoint = NewString(userApiEndpoint)
|
s.UserApiEndpoint = NewString(userApiEndpoint)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if s.ButtonText == nil {
|
||||||
|
s.ButtonText = NewString("")
|
||||||
|
}
|
||||||
|
|
||||||
|
if s.ButtonColor == nil {
|
||||||
|
s.ButtonColor = NewString(buttonColor)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type Office365Settings struct {
|
type Office365Settings struct {
|
||||||
Enable *bool `access:"authentication"`
|
Enable *bool `access:"authentication"`
|
||||||
Secret *string `access:"authentication"`
|
Secret *string `access:"authentication"`
|
||||||
Id *string `access:"authentication"`
|
Id *string `access:"authentication"`
|
||||||
Scope *string `access:"authentication"`
|
Scope *string `access:"authentication"`
|
||||||
AuthEndpoint *string `access:"authentication"`
|
AuthEndpoint *string `access:"authentication"`
|
||||||
TokenEndpoint *string `access:"authentication"`
|
TokenEndpoint *string `access:"authentication"`
|
||||||
UserApiEndpoint *string `access:"authentication"`
|
UserApiEndpoint *string `access:"authentication"`
|
||||||
DirectoryId *string `access:"authentication"`
|
DiscoveryEndpoint *string `access:"authentication"`
|
||||||
|
DirectoryId *string `access:"authentication"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Office365Settings) setDefaults() {
|
func (s *Office365Settings) setDefaults() {
|
||||||
@@ -1027,6 +1045,10 @@ func (s *Office365Settings) setDefaults() {
|
|||||||
s.Scope = NewString(OFFICE365_SETTINGS_DEFAULT_SCOPE)
|
s.Scope = NewString(OFFICE365_SETTINGS_DEFAULT_SCOPE)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if s.DiscoveryEndpoint == nil {
|
||||||
|
s.DiscoveryEndpoint = NewString("")
|
||||||
|
}
|
||||||
|
|
||||||
if s.AuthEndpoint == nil {
|
if s.AuthEndpoint == nil {
|
||||||
s.AuthEndpoint = NewString(OFFICE365_SETTINGS_DEFAULT_AUTH_ENDPOINT)
|
s.AuthEndpoint = NewString(OFFICE365_SETTINGS_DEFAULT_AUTH_ENDPOINT)
|
||||||
}
|
}
|
||||||
@@ -1050,6 +1072,7 @@ func (s *Office365Settings) SSOSettings() *SSOSettings {
|
|||||||
ssoSettings.Secret = s.Secret
|
ssoSettings.Secret = s.Secret
|
||||||
ssoSettings.Id = s.Id
|
ssoSettings.Id = s.Id
|
||||||
ssoSettings.Scope = s.Scope
|
ssoSettings.Scope = s.Scope
|
||||||
|
ssoSettings.DiscoveryEndpoint = s.DiscoveryEndpoint
|
||||||
ssoSettings.AuthEndpoint = s.AuthEndpoint
|
ssoSettings.AuthEndpoint = s.AuthEndpoint
|
||||||
ssoSettings.TokenEndpoint = s.TokenEndpoint
|
ssoSettings.TokenEndpoint = s.TokenEndpoint
|
||||||
ssoSettings.UserApiEndpoint = s.UserApiEndpoint
|
ssoSettings.UserApiEndpoint = s.UserApiEndpoint
|
||||||
@@ -2948,6 +2971,7 @@ type Config struct {
|
|||||||
GitLabSettings SSOSettings
|
GitLabSettings SSOSettings
|
||||||
GoogleSettings SSOSettings
|
GoogleSettings SSOSettings
|
||||||
Office365Settings Office365Settings
|
Office365Settings Office365Settings
|
||||||
|
OpenIdSettings SSOSettings
|
||||||
LdapSettings LdapSettings
|
LdapSettings LdapSettings
|
||||||
ComplianceSettings ComplianceSettings
|
ComplianceSettings ComplianceSettings
|
||||||
LocalizationSettings LocalizationSettings
|
LocalizationSettings LocalizationSettings
|
||||||
@@ -3004,6 +3028,8 @@ func (o *Config) GetSSOService(service string) *SSOSettings {
|
|||||||
return &o.GoogleSettings
|
return &o.GoogleSettings
|
||||||
case SERVICE_OFFICE365:
|
case SERVICE_OFFICE365:
|
||||||
return o.Office365Settings.SSOSettings()
|
return o.Office365Settings.SSOSettings()
|
||||||
|
case SERVICE_OPENID:
|
||||||
|
return &o.OpenIdSettings
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
@@ -3039,8 +3065,10 @@ func (o *Config) SetDefaults() {
|
|||||||
o.EmailSettings.SetDefaults(isUpdate)
|
o.EmailSettings.SetDefaults(isUpdate)
|
||||||
o.PrivacySettings.setDefaults()
|
o.PrivacySettings.setDefaults()
|
||||||
o.Office365Settings.setDefaults()
|
o.Office365Settings.setDefaults()
|
||||||
o.GitLabSettings.setDefaults("", "", "", "")
|
o.Office365Settings.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.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.ServiceSettings.SetDefaults(isUpdate)
|
||||||
o.PasswordSettings.SetDefaults()
|
o.PasswordSettings.SetDefaults()
|
||||||
o.TeamSettings.SetDefaults()
|
o.TeamSettings.SetDefaults()
|
||||||
@@ -3691,6 +3719,10 @@ func (o *Config) Sanitize() {
|
|||||||
*o.Office365Settings.Secret = FAKE_SETTING
|
*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.DataSource = FAKE_SETTING
|
||||||
*o.SqlSettings.AtRestEncryptKey = FAKE_SETTING
|
*o.SqlSettings.AtRestEncryptKey = FAKE_SETTING
|
||||||
|
|
||||||
|
|||||||
@@ -1322,6 +1322,7 @@ func TestConfigSanitize(t *testing.T) {
|
|||||||
*c.FileSettings.AmazonS3SecretAccessKey = "bar"
|
*c.FileSettings.AmazonS3SecretAccessKey = "bar"
|
||||||
*c.EmailSettings.SMTPPassword = "baz"
|
*c.EmailSettings.SMTPPassword = "baz"
|
||||||
*c.GitLabSettings.Secret = "bingo"
|
*c.GitLabSettings.Secret = "bingo"
|
||||||
|
*c.OpenIdSettings.Secret = "secret"
|
||||||
c.SqlSettings.DataSourceReplicas = []string{"stuff"}
|
c.SqlSettings.DataSourceReplicas = []string{"stuff"}
|
||||||
c.SqlSettings.DataSourceSearchReplicas = []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.FileSettings.AmazonS3SecretAccessKey)
|
||||||
assert.Equal(t, FAKE_SETTING, *c.EmailSettings.SMTPPassword)
|
assert.Equal(t, FAKE_SETTING, *c.EmailSettings.SMTPPassword)
|
||||||
assert.Equal(t, FAKE_SETTING, *c.GitLabSettings.Secret)
|
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.DataSource)
|
||||||
assert.Equal(t, FAKE_SETTING, *c.SqlSettings.AtRestEncryptKey)
|
assert.Equal(t, FAKE_SETTING, *c.SqlSettings.AtRestEncryptKey)
|
||||||
assert.Equal(t, FAKE_SETTING, *c.ElasticsearchSettings.Password)
|
assert.Equal(t, FAKE_SETTING, *c.ElasticsearchSettings.Password)
|
||||||
|
|||||||
@@ -91,7 +91,7 @@ func (glu *GitLabUser) getAuthData() string {
|
|||||||
return strconv.FormatInt(glu.Id, 10)
|
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)
|
glu, err := gitLabUserFromJson(data)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -102,3 +102,11 @@ func (m *GitLabProvider) GetUserFromJson(data io.Reader) (*model.User, error) {
|
|||||||
|
|
||||||
return userFromGitLabUser(glu), nil
|
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"`
|
MFA *bool `json:"mfa"`
|
||||||
GoogleOAuth *bool `json:"google_oauth"`
|
GoogleOAuth *bool `json:"google_oauth"`
|
||||||
Office365OAuth *bool `json:"office365_oauth"`
|
Office365OAuth *bool `json:"office365_oauth"`
|
||||||
|
OpenId *bool `json:"openid"`
|
||||||
Compliance *bool `json:"compliance"`
|
Compliance *bool `json:"compliance"`
|
||||||
Cluster *bool `json:"cluster"`
|
Cluster *bool `json:"cluster"`
|
||||||
Metrics *bool `json:"metrics"`
|
Metrics *bool `json:"metrics"`
|
||||||
@@ -95,6 +96,7 @@ func (f *Features) ToMap() map[string]interface{} {
|
|||||||
"mfa": *f.MFA,
|
"mfa": *f.MFA,
|
||||||
"google": *f.GoogleOAuth,
|
"google": *f.GoogleOAuth,
|
||||||
"office365": *f.Office365OAuth,
|
"office365": *f.Office365OAuth,
|
||||||
|
"openid": *f.OpenId,
|
||||||
"compliance": *f.Compliance,
|
"compliance": *f.Compliance,
|
||||||
"cluster": *f.Cluster,
|
"cluster": *f.Cluster,
|
||||||
"metrics": *f.Metrics,
|
"metrics": *f.Metrics,
|
||||||
@@ -145,6 +147,10 @@ func (f *Features) SetDefaults() {
|
|||||||
f.Office365OAuth = NewBool(*f.FutureFeatures)
|
f.Office365OAuth = NewBool(*f.FutureFeatures)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if f.OpenId == nil {
|
||||||
|
f.OpenId = NewBool(*f.FutureFeatures)
|
||||||
|
}
|
||||||
|
|
||||||
if f.Compliance == nil {
|
if f.Compliance == nil {
|
||||||
f.Compliance = NewBool(*f.FutureFeatures)
|
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_SAML ||
|
||||||
o.NewService == USER_AUTH_SERVICE_GITLAB ||
|
o.NewService == USER_AUTH_SERVICE_GITLAB ||
|
||||||
o.NewService == SERVICE_GOOGLE ||
|
o.NewService == SERVICE_GOOGLE ||
|
||||||
o.NewService == SERVICE_OFFICE365)
|
o.NewService == SERVICE_OFFICE365 ||
|
||||||
|
o.NewService == SERVICE_OPENID)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (o *SwitchRequest) OAuthToEmail() bool {
|
func (o *SwitchRequest) OAuthToEmail() bool {
|
||||||
return (o.CurrentService == USER_AUTH_SERVICE_SAML ||
|
return (o.CurrentService == USER_AUTH_SERVICE_SAML ||
|
||||||
o.CurrentService == USER_AUTH_SERVICE_GITLAB ||
|
o.CurrentService == USER_AUTH_SERVICE_GITLAB ||
|
||||||
o.CurrentService == SERVICE_GOOGLE ||
|
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 {
|
func (o *SwitchRequest) EmailToLdap() bool {
|
||||||
|
|||||||
@@ -588,8 +588,12 @@ func (ts *TelemetryService) trackConfig() {
|
|||||||
|
|
||||||
ts.sendTelemetry(TRACK_CONFIG_OAUTH, map[string]interface{}{
|
ts.sendTelemetry(TRACK_CONFIG_OAUTH, map[string]interface{}{
|
||||||
"enable_gitlab": cfg.GitLabSettings.Enable,
|
"enable_gitlab": cfg.GitLabSettings.Enable,
|
||||||
|
"openid_gitlab": *cfg.GitLabSettings.Enable && strings.Contains(*cfg.GitLabSettings.Scope, model.SERVICE_OPENID),
|
||||||
"enable_google": cfg.GoogleSettings.Enable,
|
"enable_google": cfg.GoogleSettings.Enable,
|
||||||
|
"openid_google": *cfg.GoogleSettings.Enable && strings.Contains(*cfg.GoogleSettings.Scope, model.SERVICE_OPENID),
|
||||||
"enable_office365": cfg.Office365Settings.Enable,
|
"enable_office365": cfg.Office365Settings.Enable,
|
||||||
|
"openid_office365": *cfg.Office365Settings.Enable && strings.Contains(*cfg.Office365Settings.Scope, model.SERVICE_OPENID),
|
||||||
|
"enable_openid": cfg.OpenIdSettings.Enable,
|
||||||
})
|
})
|
||||||
|
|
||||||
ts.sendTelemetry(TRACK_CONFIG_SUPPORT, map[string]interface{}{
|
ts.sendTelemetry(TRACK_CONFIG_SUPPORT, map[string]interface{}{
|
||||||
|
|||||||
@@ -139,6 +139,7 @@ func GetClientLicense(l *model.License) map[string]string {
|
|||||||
props["Metrics"] = strconv.FormatBool(*l.Features.Metrics)
|
props["Metrics"] = strconv.FormatBool(*l.Features.Metrics)
|
||||||
props["GoogleOAuth"] = strconv.FormatBool(*l.Features.GoogleOAuth)
|
props["GoogleOAuth"] = strconv.FormatBool(*l.Features.GoogleOAuth)
|
||||||
props["Office365OAuth"] = strconv.FormatBool(*l.Features.Office365OAuth)
|
props["Office365OAuth"] = strconv.FormatBool(*l.Features.Office365OAuth)
|
||||||
|
props["OpenId"] = strconv.FormatBool(*l.Features.OpenId)
|
||||||
props["Compliance"] = strconv.FormatBool(*l.Features.Compliance)
|
props["Compliance"] = strconv.FormatBool(*l.Features.Compliance)
|
||||||
props["MHPNS"] = strconv.FormatBool(*l.Features.MHPNS)
|
props["MHPNS"] = strconv.FormatBool(*l.Features.MHPNS)
|
||||||
props["Announcement"] = strconv.FormatBool(*l.Features.Announcement)
|
props["Announcement"] = strconv.FormatBool(*l.Features.Announcement)
|
||||||
|
|||||||
@@ -270,7 +270,7 @@ func completeOAuth(c *Context, w http.ResponseWriter, r *http.Request) {
|
|||||||
|
|
||||||
uri := c.GetSiteURLHeader() + "/signup/" + service + "/complete"
|
uri := c.GetSiteURLHeader() + "/signup/" + service + "/complete"
|
||||||
|
|
||||||
body, teamId, props, err := c.App.AuthorizeOAuthUser(w, r, service, code, state, uri)
|
body, teamId, props, tokenUser, err := c.App.AuthorizeOAuthUser(w, r, service, code, state, uri)
|
||||||
|
|
||||||
action := ""
|
action := ""
|
||||||
if props != nil {
|
if props != nil {
|
||||||
@@ -288,7 +288,7 @@ func completeOAuth(c *Context, w http.ResponseWriter, r *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
user, err := c.App.CompleteOAuth(service, body, teamId, props)
|
user, err := c.App.CompleteOAuth(service, body, teamId, props, tokenUser)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err.Translate(c.App.T)
|
err.Translate(c.App.T)
|
||||||
mlog.Error(err.Error())
|
mlog.Error(err.Error())
|
||||||
|
|||||||
@@ -549,12 +549,20 @@ func closeBody(r *http.Response) {
|
|||||||
type MattermostTestProvider struct {
|
type MattermostTestProvider struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *MattermostTestProvider) GetUserFromJson(data io.Reader) (*model.User, error) {
|
func (m *MattermostTestProvider) GetUserFromJson(data io.Reader, tokenUser *model.User) (*model.User, error) {
|
||||||
user := model.UserFromJson(data)
|
user := model.UserFromJson(data)
|
||||||
user.AuthData = &user.Email
|
user.AuthData = &user.Email
|
||||||
return user, nil
|
return user, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (m *MattermostTestProvider) GetSSOSettings(config *model.Config, service string) (*model.SSOSettings, error) {
|
||||||
|
return &config.GitLabSettings, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *MattermostTestProvider) GetUserFromIdToken(token string) (*model.User, error) {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
func GenerateTestAppName() string {
|
func GenerateTestAppName() string {
|
||||||
return "fakeoauthapp" + model.NewRandomString(10)
|
return "fakeoauthapp" + model.NewRandomString(10)
|
||||||
}
|
}
|
||||||
|
|||||||
Ссылка в новой задаче
Block a user