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
|
||||
enableEmail := *config.EmailSettings.EnableSignInWithEmail
|
||||
samlEnabled := *config.SamlSettings.Enable
|
||||
gitlabEnabled := *config.GetSSOService("gitlab").Enable
|
||||
googleEnabled := *config.GetSSOService("google").Enable
|
||||
gitlabEnabled := *config.GitLabSettings.Enable
|
||||
openidEnabled := *config.OpenIdSettings.Enable
|
||||
googleEnabled := *config.GoogleSettings.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)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -376,7 +376,7 @@ type AppIface interface {
|
||||
AttachDeviceId(sessionId string, deviceId string, expiresAt int64) *model.AppError
|
||||
AttachSessionCookies(w http.ResponseWriter, r *http.Request)
|
||||
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)
|
||||
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)
|
||||
@@ -412,8 +412,8 @@ type AppIface interface {
|
||||
Cluster() einterfaces.ClusterInterface
|
||||
CompareAndDeletePluginKey(pluginId string, key string, oldValue []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)
|
||||
CompleteSwitchWithOAuth(service string, userData io.Reader, email 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, tokenUser *model.User) (*model.User, *model.AppError)
|
||||
Compliance() einterfaces.ComplianceInterface
|
||||
Config() *model.Config
|
||||
Context() context.Context
|
||||
@@ -429,7 +429,7 @@ type AppIface interface {
|
||||
CreateJob(job *model.Job) (*model.Job, *model.AppError)
|
||||
CreateOAuthApp(app *model.OAuthApp) (*model.OAuthApp, *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)
|
||||
CreatePasswordRecoveryToken(userId, email string) (*model.Token, *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)
|
||||
ListTeamCommands(teamId string) ([]*model.Command, *model.AppError)
|
||||
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
|
||||
MarkChannelsAsViewed(channelIds []string, userId string, currentSessionId string) (map[string]int64, *model.AppError)
|
||||
MaxPostSize() int
|
||||
@@ -982,7 +982,7 @@ type AppIface interface {
|
||||
UpdateLastActivityAtIfNeeded(session model.Session)
|
||||
UpdateMfa(activate bool, userId, token string) *model.AppError
|
||||
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)
|
||||
UpdateOutgoingWebhook(oldHook, updatedHook *model.OutgoingWebhook) (*model.OutgoingWebhook, *model.AppError)
|
||||
UpdatePassword(user *model.User, newPassword string) *model.AppError
|
||||
|
||||
124
app/oauth.go
124
app/oauth.go
@@ -26,6 +26,7 @@ import (
|
||||
const (
|
||||
OAUTH_COOKIE_MAX_AGE_SECONDS = 30 * 60 // 30 minutes
|
||||
COOKIE_OAUTH = "MMOAUTH"
|
||||
OPENID_SCOPE = "openid"
|
||||
)
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
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()
|
||||
|
||||
action := props["action"]
|
||||
|
||||
switch action {
|
||||
case model.OAUTH_ACTION_SIGNUP:
|
||||
return a.CreateOAuthUser(service, body, teamId)
|
||||
return a.CreateOAuthUser(service, body, teamId, tokenUser)
|
||||
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:
|
||||
return a.CompleteSwitchWithOAuth(service, body, props["email"])
|
||||
return a.CompleteSwitchWithOAuth(service, body, props["email"], tokenUser)
|
||||
case model.OAUTH_ACTION_SSO_TO_EMAIL:
|
||||
return a.LoginByOAuth(service, body, teamId)
|
||||
return a.LoginByOAuth(service, body, teamId, tokenUser)
|
||||
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) {
|
||||
provider := einterfaces.GetOauthProvider(service)
|
||||
func (a *App) getSSOProvider(service string) (einterfaces.OauthProvider, *model.AppError) {
|
||||
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 {
|
||||
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)
|
||||
}
|
||||
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{}
|
||||
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)
|
||||
}
|
||||
|
||||
authUser, err1 := provider.GetUserFromJson(bytes.NewReader(buf.Bytes()))
|
||||
authUser, err1 := provider.GetUserFromJson(bytes.NewReader(buf.Bytes()), tokenUser)
|
||||
if err1 != nil {
|
||||
return nil, model.NewAppError("LoginByOAuth", "api.user.login_by_oauth.parse.app_error",
|
||||
map[string]interface{}{"Service": service}, err1.Error(), http.StatusBadRequest)
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
user, err := a.GetUserByAuth(model.NewString(*authUser.AuthData), service)
|
||||
if err != nil {
|
||||
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 {
|
||||
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)
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
if len(teamId) > 0 {
|
||||
@@ -616,18 +634,17 @@ func (a *App) LoginByOAuth(service string, userData io.Reader, teamId string) (*
|
||||
return user, nil
|
||||
}
|
||||
|
||||
func (a *App) CompleteSwitchWithOAuth(service string, userData io.Reader, email string) (*model.User, *model.AppError) {
|
||||
provider := einterfaces.GetOauthProvider(service)
|
||||
if provider == nil {
|
||||
return nil, model.NewAppError("CompleteSwitchWithOAuth", "api.user.complete_switch_with_oauth.unavailable.app_error",
|
||||
map[string]interface{}{"Service": strings.Title(service)}, "", http.StatusNotImplemented)
|
||||
func (a *App) CompleteSwitchWithOAuth(service string, userData io.Reader, email string, tokenUser *model.User) (*model.User, *model.AppError) {
|
||||
provider, e := a.getSSOProvider(service)
|
||||
if e != nil {
|
||||
return nil, e
|
||||
}
|
||||
|
||||
if email == "" {
|
||||
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 {
|
||||
return nil, model.NewAppError("CompleteSwitchWithOAuth", "api.user.complete_switch_with_oauth.parse.app_error",
|
||||
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) {
|
||||
sso := a.Config().GetSSOService(service)
|
||||
if sso == nil || !*sso.Enable {
|
||||
return "", model.NewAppError("GetAuthorizationCode", "api.user.get_authorization_code.unsupported.app_error", nil, "service="+service, http.StatusNotImplemented)
|
||||
provider, e := a.getSSOProvider(service)
|
||||
if e != nil {
|
||||
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
|
||||
@@ -755,40 +777,44 @@ func (a *App) GetAuthorizationCode(w http.ResponseWriter, r *http.Request, servi
|
||||
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) {
|
||||
sso := a.Config().GetSSOService(service)
|
||||
if sso == nil || !*sso.Enable {
|
||||
return nil, "", nil, model.NewAppError("AuthorizeOAuthUser", "api.user.authorize_oauth_user.unsupported.app_error", nil, "service="+service, http.StatusNotImplemented)
|
||||
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) {
|
||||
provider, e := a.getSSOProvider(service)
|
||||
if e != nil {
|
||||
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)
|
||||
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)
|
||||
|
||||
stateProps := model.MapFromJson(strings.NewReader(stateStr))
|
||||
|
||||
expectedToken, appErr := a.GetOAuthStateToken(stateProps["token"])
|
||||
if appErr != nil {
|
||||
return nil, "", stateProps, appErr
|
||||
return nil, "", stateProps, nil, appErr
|
||||
}
|
||||
|
||||
stateEmail := stateProps["email"]
|
||||
stateAction := stateProps["action"]
|
||||
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)
|
||||
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)
|
||||
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)
|
||||
@@ -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()))
|
||||
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")
|
||||
@@ -827,31 +853,39 @@ func (a *App) AuthorizeOAuthUser(w http.ResponseWriter, r *http.Request, service
|
||||
|
||||
resp, err := a.HTTPService().MakeClient(true).Do(req)
|
||||
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()
|
||||
|
||||
var buf bytes.Buffer
|
||||
tee := io.TeeReader(resp.Body, &buf)
|
||||
ar := model.AccessResponseFromJson(tee)
|
||||
|
||||
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 {
|
||||
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 {
|
||||
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.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(""))
|
||||
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")
|
||||
@@ -860,7 +894,7 @@ func (a *App) AuthorizeOAuthUser(w http.ResponseWriter, r *http.Request, service
|
||||
|
||||
resp, err = a.HTTPService().MakeClient(true).Do(req)
|
||||
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 {
|
||||
defer resp.Body.Close()
|
||||
|
||||
@@ -868,18 +902,18 @@ func (a *App) AuthorizeOAuthUser(w http.ResponseWriter, r *http.Request, service
|
||||
bodyBytes, _ := ioutil.ReadAll(resp.Body)
|
||||
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") {
|
||||
// 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
|
||||
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) {
|
||||
|
||||
@@ -191,7 +191,7 @@ func TestAuthorizeOAuthUser(t *testing.T) {
|
||||
th := setup(t, false, true, true, "")
|
||||
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)
|
||||
assert.Equal(t, "api.user.authorize_oauth_user.unsupported.app_error", err.Id)
|
||||
})
|
||||
@@ -202,7 +202,7 @@ func TestAuthorizeOAuthUser(t *testing.T) {
|
||||
|
||||
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)
|
||||
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(),
|
||||
})))
|
||||
|
||||
_, _, _, err := th.App.AuthorizeOAuthUser(nil, nil, model.SERVICE_GITLAB, "", state, "")
|
||||
_, _, _, _, err := th.App.AuthorizeOAuthUser(nil, nil, model.SERVICE_GITLAB, "", state, "")
|
||||
require.NotNil(t, err)
|
||||
assert.Equal(t, "api.oauth.invalid_state_token.app_error", err.Id)
|
||||
assert.NotEqual(t, "", err.DetailedError)
|
||||
@@ -230,7 +230,7 @@ func TestAuthorizeOAuthUser(t *testing.T) {
|
||||
|
||||
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)
|
||||
assert.Equal(t, "api.oauth.invalid_state_token.app_error", err.Id)
|
||||
assert.Equal(t, "", err.DetailedError)
|
||||
@@ -253,7 +253,7 @@ func TestAuthorizeOAuthUser(t *testing.T) {
|
||||
"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)
|
||||
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, "")
|
||||
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)
|
||||
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)
|
||||
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)
|
||||
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)
|
||||
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)
|
||||
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)
|
||||
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)
|
||||
assert.Equal(t, "api.user.authorize_oauth_user.bad_response.app_error", err.Id)
|
||||
assert.Contains(t, err.DetailedError, "status_code=418")
|
||||
@@ -333,7 +333,7 @@ func TestAuthorizeOAuthUser(t *testing.T) {
|
||||
request := makeRequest(t, 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)
|
||||
assert.Equal(t, "api.user.authorize_oauth_user.bad_response.app_error", err.Id)
|
||||
assert.Contains(t, err.DetailedError, "response_body=invalid")
|
||||
@@ -355,7 +355,7 @@ func TestAuthorizeOAuthUser(t *testing.T) {
|
||||
request := makeRequest(t, 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)
|
||||
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)
|
||||
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)
|
||||
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)
|
||||
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)
|
||||
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)
|
||||
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)
|
||||
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)
|
||||
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)
|
||||
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)))
|
||||
|
||||
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)
|
||||
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{}, "")
|
||||
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) {
|
||||
|
||||
@@ -687,7 +687,7 @@ func (a *OpenTracingAppLayer) AuthenticateUserForLogin(id string, loginId string
|
||||
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
|
||||
span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.AuthorizeOAuthUser")
|
||||
|
||||
@@ -699,14 +699,14 @@ func (a *OpenTracingAppLayer) AuthorizeOAuthUser(w http.ResponseWriter, r *http.
|
||||
}()
|
||||
|
||||
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 {
|
||||
span.LogFields(spanlog.Error(resultVar3))
|
||||
if resultVar4 != nil {
|
||||
span.LogFields(spanlog.Error(resultVar4))
|
||||
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) {
|
||||
@@ -1427,7 +1427,7 @@ func (a *OpenTracingAppLayer) CompareAndSetPluginKey(pluginId string, key string
|
||||
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
|
||||
span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.CompleteOAuth")
|
||||
|
||||
@@ -1439,7 +1439,7 @@ func (a *OpenTracingAppLayer) CompleteOAuth(service string, body io.ReadCloser,
|
||||
}()
|
||||
|
||||
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 {
|
||||
span.LogFields(spanlog.Error(resultVar1))
|
||||
@@ -1449,7 +1449,7 @@ func (a *OpenTracingAppLayer) CompleteOAuth(service string, body io.ReadCloser,
|
||||
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
|
||||
span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.CompleteSwitchWithOAuth")
|
||||
|
||||
@@ -1461,7 +1461,7 @@ func (a *OpenTracingAppLayer) CompleteSwitchWithOAuth(service string, userData i
|
||||
}()
|
||||
|
||||
defer span.Finish()
|
||||
resultVar0, resultVar1 := a.app.CompleteSwitchWithOAuth(service, userData, email)
|
||||
resultVar0, resultVar1 := a.app.CompleteSwitchWithOAuth(service, userData, email, tokenUser)
|
||||
|
||||
if resultVar1 != nil {
|
||||
span.LogFields(spanlog.Error(resultVar1))
|
||||
@@ -1932,7 +1932,7 @@ func (a *OpenTracingAppLayer) CreateOAuthStateToken(extra string) (*model.Token,
|
||||
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
|
||||
span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.CreateOAuthUser")
|
||||
|
||||
@@ -1944,7 +1944,7 @@ func (a *OpenTracingAppLayer) CreateOAuthUser(service string, userData io.Reader
|
||||
}()
|
||||
|
||||
defer span.Finish()
|
||||
resultVar0, resultVar1 := a.app.CreateOAuthUser(service, userData, teamId)
|
||||
resultVar0, resultVar1 := a.app.CreateOAuthUser(service, userData, teamId, tokenUser)
|
||||
|
||||
if resultVar1 != nil {
|
||||
span.LogFields(spanlog.Error(resultVar1))
|
||||
@@ -10392,7 +10392,7 @@ func (a *OpenTracingAppLayer) LogAuditRecWithLevel(rec *audit.Record, level mlog
|
||||
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
|
||||
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()
|
||||
resultVar0, resultVar1 := a.app.LoginByOAuth(service, userData, teamId)
|
||||
resultVar0, resultVar1 := a.app.LoginByOAuth(service, userData, teamId, tokenUser)
|
||||
|
||||
if resultVar1 != nil {
|
||||
span.LogFields(spanlog.Error(resultVar1))
|
||||
@@ -14864,7 +14864,7 @@ func (a *OpenTracingAppLayer) UpdateMobileAppBadge(userId string) {
|
||||
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
|
||||
span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.UpdateOAuthUserAttrs")
|
||||
|
||||
@@ -14876,7 +14876,7 @@ func (a *OpenTracingAppLayer) UpdateOAuthUserAttrs(userData io.Reader, user *mod
|
||||
}()
|
||||
|
||||
defer span.Finish()
|
||||
resultVar0 := a.app.UpdateOAuthUserAttrs(userData, user, provider, service)
|
||||
resultVar0 := a.app.UpdateOAuthUserAttrs(userData, user, provider, service, tokenUser)
|
||||
|
||||
if resultVar0 != nil {
|
||||
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
|
||||
}
|
||||
|
||||
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 {
|
||||
return nil, model.NewAppError("CreateOAuthUser", "api.user.create_user.disabled.app_error", nil, "", http.StatusNotImplemented)
|
||||
}
|
||||
|
||||
provider := einterfaces.GetOauthProvider(service)
|
||||
if provider == nil {
|
||||
return nil, model.NewAppError("CreateOAuthUser", "api.user.create_oauth_user.not_available.app_error", map[string]interface{}{"Service": strings.Title(service)}, "", http.StatusNotImplemented)
|
||||
provider, e := a.getSSOProvider(service)
|
||||
if e != nil {
|
||||
return nil, e
|
||||
}
|
||||
user, err1 := provider.GetUserFromJson(userData)
|
||||
user, err1 := provider.GetUserFromJson(userData, tokenUser)
|
||||
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)
|
||||
}
|
||||
if user.AuthService == "" {
|
||||
user.AuthService = service
|
||||
}
|
||||
|
||||
suchan := 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
|
||||
}
|
||||
|
||||
func (a *App) UpdateOAuthUserAttrs(userData io.Reader, user *model.User, provider einterfaces.OauthProvider, service string) *model.AppError {
|
||||
oauthUser, err1 := provider.GetUserFromJson(userData)
|
||||
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, tokenUser)
|
||||
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)
|
||||
}
|
||||
|
||||
@@ -76,10 +76,14 @@ func TestCreateOAuthUser(t *testing.T) {
|
||||
th := Setup(t).InitBasic()
|
||||
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"}
|
||||
|
||||
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.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
|
||||
|
||||
_, 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")
|
||||
}
|
||||
|
||||
@@ -269,6 +273,9 @@ func TestUpdateOAuthUserAttrs(t *testing.T) {
|
||||
|
||||
id := model.NewId()
|
||||
id2 := model.NewId()
|
||||
th.App.UpdateConfig(func(cfg *model.Config) {
|
||||
*cfg.GitLabSettings.Enable = true
|
||||
})
|
||||
gitlabProvider := einterfaces.GetOauthProvider("gitlab")
|
||||
|
||||
username := "user" + id
|
||||
@@ -289,7 +296,7 @@ func TestUpdateOAuthUserAttrs(t *testing.T) {
|
||||
data := bytes.NewReader(gitlabUser)
|
||||
|
||||
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)
|
||||
|
||||
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)
|
||||
|
||||
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)
|
||||
|
||||
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)
|
||||
|
||||
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)
|
||||
|
||||
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)
|
||||
|
||||
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)
|
||||
|
||||
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)
|
||||
|
||||
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)
|
||||
|
||||
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)
|
||||
|
||||
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)
|
||||
|
||||
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 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)
|
||||
|
||||
return user, gitlabUserObj
|
||||
|
||||
@@ -288,6 +288,9 @@ func GenerateLimitedClientConfig(c *model.Config, telemetryID string, license *m
|
||||
props["SamlLoginButtonTextColor"] = ""
|
||||
props["EnableSignUpWithGoogle"] = "false"
|
||||
props["EnableSignUpWithOffice365"] = "false"
|
||||
props["EnableSignUpWithOpenId"] = "false"
|
||||
props["OpenIdButtonText"] = ""
|
||||
props["OpenIdButtonColor"] = ""
|
||||
props["CWSUrl"] = ""
|
||||
props["EnableCustomBrand"] = strconv.FormatBool(*c.TeamSettings.EnableCustomBrand)
|
||||
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)
|
||||
}
|
||||
|
||||
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 {
|
||||
props["EnableCustomTermsOfService"] = strconv.FormatBool(*c.SupportSettings.CustomTermsOfServiceEnabled)
|
||||
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
|
||||
}
|
||||
|
||||
if target.OpenIdSettings.Secret != nil && *target.OpenIdSettings.Secret == model.FAKE_SETTING {
|
||||
target.OpenIdSettings.Secret = actual.OpenIdSettings.Secret
|
||||
}
|
||||
|
||||
if *target.SqlSettings.DataSource == model.FAKE_SETTING {
|
||||
*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.EmailSettings.SMTPPassword = sToP("smtp_password")
|
||||
actual.GitLabSettings.Secret = sToP("secret")
|
||||
actual.OpenIdSettings.Secret = sToP("secret")
|
||||
actual.SqlSettings.DataSource = sToP("data_source")
|
||||
actual.SqlSettings.AtRestEncryptKey = sToP("at_rest_encrypt_key")
|
||||
actual.ElasticsearchSettings.Password = sToP("password")
|
||||
@@ -46,6 +47,7 @@ func TestDesanitize(t *testing.T) {
|
||||
target.FileSettings.AmazonS3SecretAccessKey = sToP(model.FAKE_SETTING)
|
||||
target.EmailSettings.SMTPPassword = 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.AtRestEncryptKey = 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.EmailSettings.SMTPPassword, *target.EmailSettings.SMTPPassword)
|
||||
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.AtRestEncryptKey, *target.SqlSettings.AtRestEncryptKey)
|
||||
assert.Equal(t, *actual.ElasticsearchSettings.Password, *target.ElasticsearchSettings.Password)
|
||||
|
||||
@@ -10,7 +10,9 @@ import (
|
||||
)
|
||||
|
||||
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)
|
||||
|
||||
14
i18n/en.json
14
i18n/en.json
@@ -3148,7 +3148,7 @@
|
||||
},
|
||||
{
|
||||
"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",
|
||||
@@ -3174,10 +3174,6 @@
|
||||
"id": "api.user.complete_switch_with_oauth.parse.app_error",
|
||||
"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",
|
||||
"translation": "Failed to create token data for email verification"
|
||||
@@ -3190,10 +3186,6 @@
|
||||
"id": "api.user.create_oauth_user.create.app_error",
|
||||
"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",
|
||||
"translation": "Unable to create password recovery token"
|
||||
@@ -3271,8 +3263,8 @@
|
||||
"translation": "Authentication Transfer not configured or available on this server."
|
||||
},
|
||||
{
|
||||
"id": "api.user.get_authorization_code.unsupported.app_error",
|
||||
"translation": "Unsupported OAuth service provider."
|
||||
"id": "api.user.get_authorization_code.endpoint.app_error",
|
||||
"translation": ""
|
||||
},
|
||||
{
|
||||
"id": "api.user.get_uploads_for_user.forbidden.app_error",
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -588,8 +588,12 @@ func (ts *TelemetryService) trackConfig() {
|
||||
|
||||
ts.sendTelemetry(TRACK_CONFIG_OAUTH, map[string]interface{}{
|
||||
"enable_gitlab": cfg.GitLabSettings.Enable,
|
||||
"openid_gitlab": *cfg.GitLabSettings.Enable && strings.Contains(*cfg.GitLabSettings.Scope, model.SERVICE_OPENID),
|
||||
"enable_google": cfg.GoogleSettings.Enable,
|
||||
"openid_google": *cfg.GoogleSettings.Enable && strings.Contains(*cfg.GoogleSettings.Scope, model.SERVICE_OPENID),
|
||||
"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{}{
|
||||
|
||||
@@ -139,6 +139,7 @@ func GetClientLicense(l *model.License) map[string]string {
|
||||
props["Metrics"] = strconv.FormatBool(*l.Features.Metrics)
|
||||
props["GoogleOAuth"] = strconv.FormatBool(*l.Features.GoogleOAuth)
|
||||
props["Office365OAuth"] = strconv.FormatBool(*l.Features.Office365OAuth)
|
||||
props["OpenId"] = strconv.FormatBool(*l.Features.OpenId)
|
||||
props["Compliance"] = strconv.FormatBool(*l.Features.Compliance)
|
||||
props["MHPNS"] = strconv.FormatBool(*l.Features.MHPNS)
|
||||
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"
|
||||
|
||||
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 := ""
|
||||
if props != nil {
|
||||
@@ -288,7 +288,7 @@ func completeOAuth(c *Context, w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
user, err := c.App.CompleteOAuth(service, body, teamId, props)
|
||||
user, err := c.App.CompleteOAuth(service, body, teamId, props, tokenUser)
|
||||
if err != nil {
|
||||
err.Translate(c.App.T)
|
||||
mlog.Error(err.Error())
|
||||
|
||||
@@ -549,12 +549,20 @@ func closeBody(r *http.Response) {
|
||||
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.AuthData = &user.Email
|
||||
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 {
|
||||
return "fakeoauthapp" + model.NewRandomString(10)
|
||||
}
|
||||
|
||||
Ссылка в новой задаче
Block a user