github.com/adacta-ru/mattermost-server/v6@v6.0.0/web/oauth_test.go (about)

     1  // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
     2  // See LICENSE.txt for license information.
     3  
     4  package web
     5  
     6  import (
     7  	"encoding/base64"
     8  	"io"
     9  	"io/ioutil"
    10  	"net/http"
    11  	"net/http/httptest"
    12  	"net/url"
    13  	"strings"
    14  	"testing"
    15  
    16  	"github.com/adacta-ru/mattermost-server/v6/einterfaces"
    17  	"github.com/adacta-ru/mattermost-server/v6/model"
    18  	"github.com/adacta-ru/mattermost-server/v6/utils"
    19  	"github.com/stretchr/testify/assert"
    20  	"github.com/stretchr/testify/require"
    21  )
    22  
    23  func TestOAuthComplete_AccessDenied(t *testing.T) {
    24  	th := Setup(t).InitBasic()
    25  	defer th.TearDown()
    26  
    27  	c := &Context{
    28  		App: th.App,
    29  		Params: &Params{
    30  			Service: "TestService",
    31  		},
    32  	}
    33  	responseWriter := httptest.NewRecorder()
    34  	request, _ := http.NewRequest(http.MethodGet, th.App.GetSiteURL()+"/signup/TestService/complete?error=access_denied", nil)
    35  
    36  	completeOAuth(c, responseWriter, request)
    37  
    38  	response := responseWriter.Result()
    39  
    40  	assert.Equal(t, http.StatusTemporaryRedirect, response.StatusCode)
    41  
    42  	location, _ := url.Parse(response.Header.Get("Location"))
    43  	assert.Equal(t, "oauth_access_denied", location.Query().Get("type"))
    44  	assert.Equal(t, "TestService", location.Query().Get("service"))
    45  }
    46  
    47  func TestAuthorizeOAuthApp(t *testing.T) {
    48  	th := Setup(t).InitBasic()
    49  	th.Login(ApiClient, th.SystemAdminUser)
    50  	defer th.TearDown()
    51  
    52  	enableOAuth := *th.App.Config().ServiceSettings.EnableOAuthServiceProvider
    53  	defer func() {
    54  		th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableOAuthServiceProvider = enableOAuth })
    55  	}()
    56  
    57  	th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableOAuthServiceProvider = true })
    58  
    59  	oapp := &model.OAuthApp{
    60  		Name:         GenerateTestAppName(),
    61  		Homepage:     "https://nowhere.com",
    62  		Description:  "test",
    63  		CallbackUrls: []string{"https://nowhere.com"},
    64  		CreatorId:    th.SystemAdminUser.Id,
    65  	}
    66  
    67  	rapp, appErr := th.App.CreateOAuthApp(oapp)
    68  	require.Nil(t, appErr)
    69  
    70  	authRequest := &model.AuthorizeRequest{
    71  		ResponseType: model.AUTHCODE_RESPONSE_TYPE,
    72  		ClientId:     rapp.Id,
    73  		RedirectUri:  rapp.CallbackUrls[0],
    74  		Scope:        "",
    75  		State:        "123",
    76  	}
    77  
    78  	// Test auth code flow
    79  	ruri, resp := ApiClient.AuthorizeOAuthApp(authRequest)
    80  	require.Nil(t, resp.Error)
    81  
    82  	require.NotEmpty(t, ruri, "redirect url should be set")
    83  
    84  	ru, _ := url.Parse(ruri)
    85  	require.NotNil(t, ru, "redirect url unparseable")
    86  	require.NotEmpty(t, ru.Query().Get("code"), "authorization code not returned")
    87  	require.Equal(t, ru.Query().Get("state"), authRequest.State, "returned state doesn't match")
    88  
    89  	// Test implicit flow
    90  	authRequest.ResponseType = model.IMPLICIT_RESPONSE_TYPE
    91  	ruri, resp = ApiClient.AuthorizeOAuthApp(authRequest)
    92  	require.Nil(t, resp.Error)
    93  	require.False(t, len(ruri) == 0, "redirect url should be set")
    94  
    95  	ru, _ = url.Parse(ruri)
    96  	require.NotNil(t, ru, "redirect url unparseable")
    97  	values, err := url.ParseQuery(ru.Fragment)
    98  	require.Nil(t, err)
    99  	assert.False(t, len(values.Get("access_token")) == 0, "access_token not returned")
   100  	assert.Equal(t, authRequest.State, values.Get("state"), "returned state doesn't match")
   101  
   102  	oldToken := ApiClient.AuthToken
   103  	ApiClient.AuthToken = values.Get("access_token")
   104  	_, resp = ApiClient.AuthorizeOAuthApp(authRequest)
   105  	CheckForbiddenStatus(t, resp)
   106  
   107  	ApiClient.AuthToken = oldToken
   108  
   109  	authRequest.RedirectUri = ""
   110  	_, resp = ApiClient.AuthorizeOAuthApp(authRequest)
   111  	CheckBadRequestStatus(t, resp)
   112  
   113  	authRequest.RedirectUri = "http://somewhereelse.com"
   114  	_, resp = ApiClient.AuthorizeOAuthApp(authRequest)
   115  	CheckBadRequestStatus(t, resp)
   116  
   117  	authRequest.RedirectUri = rapp.CallbackUrls[0]
   118  	authRequest.ResponseType = ""
   119  	_, resp = ApiClient.AuthorizeOAuthApp(authRequest)
   120  	CheckBadRequestStatus(t, resp)
   121  
   122  	authRequest.ResponseType = model.AUTHCODE_RESPONSE_TYPE
   123  	authRequest.ClientId = ""
   124  	_, resp = ApiClient.AuthorizeOAuthApp(authRequest)
   125  	CheckBadRequestStatus(t, resp)
   126  
   127  	authRequest.ClientId = model.NewId()
   128  	_, resp = ApiClient.AuthorizeOAuthApp(authRequest)
   129  	CheckNotFoundStatus(t, resp)
   130  }
   131  
   132  func TestNilAuthorizeOAuthApp(t *testing.T) {
   133  	th := Setup(t).InitBasic()
   134  	th.Login(ApiClient, th.SystemAdminUser)
   135  	defer th.TearDown()
   136  
   137  	_, resp := ApiClient.AuthorizeOAuthApp(nil)
   138  	require.NotNil(t, resp.Error)
   139  	assert.Equal(t, "api.context.invalid_body_param.app_error", resp.Error.Id)
   140  }
   141  
   142  func TestDeauthorizeOAuthApp(t *testing.T) {
   143  	th := Setup(t).InitBasic()
   144  	th.Login(ApiClient, th.SystemAdminUser)
   145  	defer th.TearDown()
   146  
   147  	enableOAuth := th.App.Config().ServiceSettings.EnableOAuthServiceProvider
   148  	defer func() {
   149  		th.App.UpdateConfig(func(cfg *model.Config) { cfg.ServiceSettings.EnableOAuthServiceProvider = enableOAuth })
   150  	}()
   151  	th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableOAuthServiceProvider = true })
   152  
   153  	oapp := &model.OAuthApp{
   154  		Name:         GenerateTestAppName(),
   155  		Homepage:     "https://nowhere.com",
   156  		Description:  "test",
   157  		CallbackUrls: []string{"https://nowhere.com"},
   158  		CreatorId:    th.SystemAdminUser.Id,
   159  	}
   160  
   161  	rapp, appErr := th.App.CreateOAuthApp(oapp)
   162  	require.Nil(t, appErr)
   163  
   164  	authRequest := &model.AuthorizeRequest{
   165  		ResponseType: model.AUTHCODE_RESPONSE_TYPE,
   166  		ClientId:     rapp.Id,
   167  		RedirectUri:  rapp.CallbackUrls[0],
   168  		Scope:        "",
   169  		State:        "123",
   170  	}
   171  
   172  	_, resp := ApiClient.AuthorizeOAuthApp(authRequest)
   173  	require.Nil(t, resp.Error)
   174  
   175  	pass, resp := ApiClient.DeauthorizeOAuthApp(rapp.Id)
   176  	require.Nil(t, resp.Error)
   177  
   178  	require.True(t, pass, "should have passed")
   179  
   180  	_, resp = ApiClient.DeauthorizeOAuthApp("junk")
   181  	CheckBadRequestStatus(t, resp)
   182  
   183  	_, resp = ApiClient.DeauthorizeOAuthApp(model.NewId())
   184  	require.Nil(t, resp.Error)
   185  
   186  	th.Logout(ApiClient)
   187  	_, resp = ApiClient.DeauthorizeOAuthApp(rapp.Id)
   188  	CheckUnauthorizedStatus(t, resp)
   189  }
   190  
   191  func TestOAuthAccessToken(t *testing.T) {
   192  	if testing.Short() {
   193  		t.SkipNow()
   194  	}
   195  
   196  	th := Setup(t).InitBasic()
   197  	th.Login(ApiClient, th.SystemAdminUser)
   198  	defer th.TearDown()
   199  
   200  	enableOAuth := th.App.Config().ServiceSettings.EnableOAuthServiceProvider
   201  	defer func() {
   202  		th.App.UpdateConfig(func(cfg *model.Config) { cfg.ServiceSettings.EnableOAuthServiceProvider = enableOAuth })
   203  	}()
   204  	th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableOAuthServiceProvider = true })
   205  
   206  	defaultRolePermissions := th.SaveDefaultRolePermissions()
   207  	defer func() {
   208  		th.RestoreDefaultRolePermissions(defaultRolePermissions)
   209  	}()
   210  	th.AddPermissionToRole(model.PERMISSION_MANAGE_OAUTH.Id, model.TEAM_USER_ROLE_ID)
   211  	th.AddPermissionToRole(model.PERMISSION_MANAGE_OAUTH.Id, model.SYSTEM_USER_ROLE_ID)
   212  
   213  	oauthApp := &model.OAuthApp{
   214  		Name:         "TestApp5" + model.NewId(),
   215  		Homepage:     "https://nowhere.com",
   216  		Description:  "test",
   217  		CallbackUrls: []string{"https://nowhere.com"},
   218  		CreatorId:    th.SystemAdminUser.Id,
   219  	}
   220  	oauthApp, appErr := th.App.CreateOAuthApp(oauthApp)
   221  	require.Nil(t, appErr)
   222  
   223  	th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableOAuthServiceProvider = false })
   224  	data := url.Values{"grant_type": []string{"junk"}, "client_id": []string{"12345678901234567890123456"}, "client_secret": []string{"12345678901234567890123456"}, "code": []string{"junk"}, "redirect_uri": []string{oauthApp.CallbackUrls[0]}}
   225  
   226  	_, resp := ApiClient.GetOAuthAccessToken(data)
   227  	require.NotNil(t, resp.Error, "should have failed - oauth providing turned off - response status code: %v", resp.StatusCode)
   228  	th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableOAuthServiceProvider = true })
   229  
   230  	authRequest := &model.AuthorizeRequest{
   231  		ResponseType: model.AUTHCODE_RESPONSE_TYPE,
   232  		ClientId:     oauthApp.Id,
   233  		RedirectUri:  oauthApp.CallbackUrls[0],
   234  		Scope:        "all",
   235  		State:        "123",
   236  	}
   237  
   238  	redirect, resp := ApiClient.AuthorizeOAuthApp(authRequest)
   239  	require.Nil(t, resp.Error)
   240  	rurl, _ := url.Parse(redirect)
   241  
   242  	ApiClient.Logout()
   243  
   244  	data = url.Values{"grant_type": []string{"junk"}, "client_id": []string{oauthApp.Id}, "client_secret": []string{oauthApp.ClientSecret}, "code": []string{rurl.Query().Get("code")}, "redirect_uri": []string{oauthApp.CallbackUrls[0]}}
   245  
   246  	_, resp = ApiClient.GetOAuthAccessToken(data)
   247  	require.NotNil(t, resp.Error, "should have failed - bad grant type")
   248  
   249  	data.Set("grant_type", model.ACCESS_TOKEN_GRANT_TYPE)
   250  	data.Set("client_id", "")
   251  	_, resp = ApiClient.GetOAuthAccessToken(data)
   252  	require.NotNil(t, resp.Error, "should have failed - missing client id")
   253  
   254  	data.Set("client_id", "junk")
   255  	_, resp = ApiClient.GetOAuthAccessToken(data)
   256  	require.NotNil(t, resp.Error, "should have failed - bad client id")
   257  
   258  	data.Set("client_id", oauthApp.Id)
   259  	data.Set("client_secret", "")
   260  	_, resp = ApiClient.GetOAuthAccessToken(data)
   261  	require.NotNil(t, resp.Error, "should have failed - missing client secret")
   262  
   263  	data.Set("client_secret", "junk")
   264  	_, resp = ApiClient.GetOAuthAccessToken(data)
   265  	require.NotNil(t, resp.Error, "should have failed - bad client secret")
   266  
   267  	data.Set("client_secret", oauthApp.ClientSecret)
   268  	data.Set("code", "")
   269  	_, resp = ApiClient.GetOAuthAccessToken(data)
   270  	require.NotNil(t, resp.Error, "should have failed - missing code")
   271  
   272  	data.Set("code", "junk")
   273  	_, resp = ApiClient.GetOAuthAccessToken(data)
   274  	require.NotNil(t, resp.Error, "should have failed - bad code")
   275  
   276  	data.Set("code", rurl.Query().Get("code"))
   277  	data.Set("redirect_uri", "junk")
   278  	_, resp = ApiClient.GetOAuthAccessToken(data)
   279  	require.NotNil(t, resp.Error, "should have failed - non-matching redirect uri")
   280  
   281  	// reset data for successful request
   282  	data.Set("grant_type", model.ACCESS_TOKEN_GRANT_TYPE)
   283  	data.Set("client_id", oauthApp.Id)
   284  	data.Set("client_secret", oauthApp.ClientSecret)
   285  	data.Set("code", rurl.Query().Get("code"))
   286  	data.Set("redirect_uri", oauthApp.CallbackUrls[0])
   287  
   288  	token := ""
   289  	refreshToken := ""
   290  	rsp, resp := ApiClient.GetOAuthAccessToken(data)
   291  	require.Nil(t, resp.Error)
   292  	require.NotEmpty(t, rsp.AccessToken, "access token not returned")
   293  	require.NotEmpty(t, rsp.RefreshToken, "refresh token not returned")
   294  	token, refreshToken = rsp.AccessToken, rsp.RefreshToken
   295  	require.Equal(t, rsp.TokenType, model.ACCESS_TOKEN_TYPE, "access token type incorrect")
   296  
   297  	_, err := ApiClient.DoApiGet("/oauth_test", "")
   298  	require.Nil(t, err)
   299  
   300  	ApiClient.SetOAuthToken("")
   301  	_, err = ApiClient.DoApiGet("/oauth_test", "")
   302  	require.NotNil(t, err, "should have failed - no access token provided")
   303  
   304  	ApiClient.SetOAuthToken("badtoken")
   305  	_, err = ApiClient.DoApiGet("/oauth_test", "")
   306  	require.NotNil(t, err, "should have failed - bad token provided")
   307  
   308  	ApiClient.SetOAuthToken(token)
   309  	_, err = ApiClient.DoApiGet("/oauth_test", "")
   310  	require.Nil(t, err)
   311  
   312  	_, resp = ApiClient.GetOAuthAccessToken(data)
   313  	require.NotNil(t, resp.Error, "should have failed - tried to reuse auth code")
   314  
   315  	data.Set("grant_type", model.REFRESH_TOKEN_GRANT_TYPE)
   316  	data.Set("client_id", oauthApp.Id)
   317  	data.Set("client_secret", oauthApp.ClientSecret)
   318  	data.Set("refresh_token", "")
   319  	data.Set("redirect_uri", oauthApp.CallbackUrls[0])
   320  	data.Del("code")
   321  	_, resp = ApiClient.GetOAuthAccessToken(data)
   322  	require.NotNil(t, resp.Error, "Should have failed - refresh token empty")
   323  
   324  	data.Set("refresh_token", refreshToken)
   325  	rsp, resp = ApiClient.GetOAuthAccessToken(data)
   326  	require.Nil(t, resp.Error)
   327  	require.NotEmpty(t, rsp.AccessToken, "access token not returned")
   328  	require.NotEmpty(t, rsp.RefreshToken, "refresh token not returned")
   329  	require.NotEqual(t, rsp.RefreshToken, refreshToken, "refresh token did not update")
   330  	require.Equal(t, rsp.TokenType, model.ACCESS_TOKEN_TYPE, "access token type incorrect")
   331  
   332  	ApiClient.SetOAuthToken(rsp.AccessToken)
   333  	_, err = ApiClient.DoApiGet("/oauth_test", "")
   334  	require.Nil(t, err)
   335  
   336  	data.Set("refresh_token", rsp.RefreshToken)
   337  	rsp, resp = ApiClient.GetOAuthAccessToken(data)
   338  	require.Nil(t, resp.Error)
   339  	require.NotEmpty(t, rsp.AccessToken, "access token not returned")
   340  	require.NotEmpty(t, rsp.RefreshToken, "refresh token not returned")
   341  	require.NotEqual(t, rsp.RefreshToken, refreshToken, "refresh token did not update")
   342  	require.Equal(t, rsp.TokenType, model.ACCESS_TOKEN_TYPE, "access token type incorrect")
   343  
   344  	ApiClient.SetOAuthToken(rsp.AccessToken)
   345  	_, err = ApiClient.DoApiGet("/oauth_test", "")
   346  	require.Nil(t, err)
   347  
   348  	authData := &model.AuthData{ClientId: oauthApp.Id, RedirectUri: oauthApp.CallbackUrls[0], UserId: th.BasicUser.Id, Code: model.NewId(), ExpiresIn: -1}
   349  	_, nErr := th.App.Srv().Store.OAuth().SaveAuthData(authData)
   350  	require.Nil(t, nErr)
   351  
   352  	data.Set("grant_type", model.ACCESS_TOKEN_GRANT_TYPE)
   353  	data.Set("client_id", oauthApp.Id)
   354  	data.Set("client_secret", oauthApp.ClientSecret)
   355  	data.Set("redirect_uri", oauthApp.CallbackUrls[0])
   356  	data.Set("code", authData.Code)
   357  	data.Del("refresh_token")
   358  	_, resp = ApiClient.GetOAuthAccessToken(data)
   359  	require.NotNil(t, resp.Error, "Should have failed - code is expired")
   360  
   361  	ApiClient.ClearOAuthToken()
   362  }
   363  
   364  func TestOAuthComplete(t *testing.T) {
   365  	if testing.Short() {
   366  		t.SkipNow()
   367  	}
   368  
   369  	th := Setup(t).InitBasic()
   370  	th.Login(ApiClient, th.SystemAdminUser)
   371  	defer th.TearDown()
   372  
   373  	gitLabSettingsEnable := th.App.Config().GitLabSettings.Enable
   374  	gitLabSettingsAuthEndpoint := th.App.Config().GitLabSettings.AuthEndpoint
   375  	gitLabSettingsId := th.App.Config().GitLabSettings.Id
   376  	gitLabSettingsSecret := th.App.Config().GitLabSettings.Secret
   377  	gitLabSettingsTokenEndpoint := th.App.Config().GitLabSettings.TokenEndpoint
   378  	gitLabSettingsUserApiEndpoint := th.App.Config().GitLabSettings.UserApiEndpoint
   379  	enableOAuthServiceProvider := th.App.Config().ServiceSettings.EnableOAuthServiceProvider
   380  	defer func() {
   381  		th.App.UpdateConfig(func(cfg *model.Config) { cfg.GitLabSettings.Enable = gitLabSettingsEnable })
   382  		th.App.UpdateConfig(func(cfg *model.Config) { cfg.GitLabSettings.AuthEndpoint = gitLabSettingsAuthEndpoint })
   383  		th.App.UpdateConfig(func(cfg *model.Config) { cfg.GitLabSettings.Id = gitLabSettingsId })
   384  		th.App.UpdateConfig(func(cfg *model.Config) { cfg.GitLabSettings.Secret = gitLabSettingsSecret })
   385  		th.App.UpdateConfig(func(cfg *model.Config) { cfg.GitLabSettings.TokenEndpoint = gitLabSettingsTokenEndpoint })
   386  		th.App.UpdateConfig(func(cfg *model.Config) { cfg.GitLabSettings.UserApiEndpoint = gitLabSettingsUserApiEndpoint })
   387  		th.App.UpdateConfig(func(cfg *model.Config) { cfg.ServiceSettings.EnableOAuthServiceProvider = enableOAuthServiceProvider })
   388  	}()
   389  
   390  	r, err := HttpGet(ApiClient.Url+"/login/gitlab/complete?code=123", ApiClient.HttpClient, "", true)
   391  	assert.NotNil(t, err)
   392  	closeBody(r)
   393  
   394  	th.App.UpdateConfig(func(cfg *model.Config) { *cfg.GitLabSettings.Enable = true })
   395  	r, err = HttpGet(ApiClient.Url+"/login/gitlab/complete?code=123&state=!#$#F@#Yˆ&~ñ", ApiClient.HttpClient, "", true)
   396  	assert.NotNil(t, err)
   397  	closeBody(r)
   398  
   399  	th.App.UpdateConfig(func(cfg *model.Config) { *cfg.GitLabSettings.AuthEndpoint = ApiClient.Url + "/oauth/authorize" })
   400  	th.App.UpdateConfig(func(cfg *model.Config) { *cfg.GitLabSettings.Id = model.NewId() })
   401  
   402  	stateProps := map[string]string{}
   403  	stateProps["action"] = model.OAUTH_ACTION_LOGIN
   404  	stateProps["team_id"] = th.BasicTeam.Id
   405  	stateProps["redirect_to"] = *th.App.Config().GitLabSettings.AuthEndpoint
   406  
   407  	state := base64.StdEncoding.EncodeToString([]byte(model.MapToJson(stateProps)))
   408  	r, err = HttpGet(ApiClient.Url+"/login/gitlab/complete?code=123&state="+url.QueryEscape(state), ApiClient.HttpClient, "", true)
   409  	assert.NotNil(t, err)
   410  	closeBody(r)
   411  
   412  	stateProps["hash"] = utils.HashSha256(*th.App.Config().GitLabSettings.Id)
   413  	state = base64.StdEncoding.EncodeToString([]byte(model.MapToJson(stateProps)))
   414  	r, err = HttpGet(ApiClient.Url+"/login/gitlab/complete?code=123&state="+url.QueryEscape(state), ApiClient.HttpClient, "", true)
   415  	assert.NotNil(t, err)
   416  	closeBody(r)
   417  
   418  	// We are going to use mattermost as the provider emulating gitlab
   419  	th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableOAuthServiceProvider = true })
   420  
   421  	defaultRolePermissions := th.SaveDefaultRolePermissions()
   422  	defer func() {
   423  		th.RestoreDefaultRolePermissions(defaultRolePermissions)
   424  	}()
   425  	th.AddPermissionToRole(model.PERMISSION_MANAGE_OAUTH.Id, model.TEAM_USER_ROLE_ID)
   426  	th.AddPermissionToRole(model.PERMISSION_MANAGE_OAUTH.Id, model.SYSTEM_USER_ROLE_ID)
   427  
   428  	oauthApp := &model.OAuthApp{
   429  		Name:        "TestApp5" + model.NewId(),
   430  		Homepage:    "https://nowhere.com",
   431  		Description: "test",
   432  		CallbackUrls: []string{
   433  			ApiClient.Url + "/signup/" + model.SERVICE_GITLAB + "/complete",
   434  			ApiClient.Url + "/login/" + model.SERVICE_GITLAB + "/complete",
   435  		},
   436  		CreatorId: th.SystemAdminUser.Id,
   437  		IsTrusted: true,
   438  	}
   439  	oauthApp, appErr := th.App.CreateOAuthApp(oauthApp)
   440  	require.Nil(t, appErr)
   441  
   442  	th.App.UpdateConfig(func(cfg *model.Config) { *cfg.GitLabSettings.Id = oauthApp.Id })
   443  	th.App.UpdateConfig(func(cfg *model.Config) { *cfg.GitLabSettings.Secret = oauthApp.ClientSecret })
   444  	th.App.UpdateConfig(func(cfg *model.Config) { *cfg.GitLabSettings.AuthEndpoint = ApiClient.Url + "/oauth/authorize" })
   445  	th.App.UpdateConfig(func(cfg *model.Config) { *cfg.GitLabSettings.TokenEndpoint = ApiClient.Url + "/oauth/access_token" })
   446  	th.App.UpdateConfig(func(cfg *model.Config) { *cfg.GitLabSettings.UserApiEndpoint = ApiClient.ApiUrl + "/users/me" })
   447  
   448  	provider := &MattermostTestProvider{}
   449  
   450  	authRequest := &model.AuthorizeRequest{
   451  		ResponseType: model.AUTHCODE_RESPONSE_TYPE,
   452  		ClientId:     oauthApp.Id,
   453  		RedirectUri:  oauthApp.CallbackUrls[0],
   454  		Scope:        "all",
   455  		State:        "123",
   456  	}
   457  
   458  	redirect, resp := ApiClient.AuthorizeOAuthApp(authRequest)
   459  	require.Nil(t, resp.Error)
   460  	rurl, _ := url.Parse(redirect)
   461  
   462  	code := rurl.Query().Get("code")
   463  	stateProps["action"] = model.OAUTH_ACTION_EMAIL_TO_SSO
   464  	delete(stateProps, "team_id")
   465  	stateProps["redirect_to"] = *th.App.Config().GitLabSettings.AuthEndpoint
   466  	stateProps["hash"] = utils.HashSha256(*th.App.Config().GitLabSettings.Id)
   467  	stateProps["redirect_to"] = "/oauth/authorize"
   468  	state = base64.StdEncoding.EncodeToString([]byte(model.MapToJson(stateProps)))
   469  	r, err = HttpGet(ApiClient.Url+"/login/"+model.SERVICE_GITLAB+"/complete?code="+url.QueryEscape(code)+"&state="+url.QueryEscape(state), ApiClient.HttpClient, "", false)
   470  	if err == nil {
   471  		closeBody(r)
   472  	}
   473  
   474  	einterfaces.RegisterOauthProvider(model.SERVICE_GITLAB, provider)
   475  
   476  	redirect, resp = ApiClient.AuthorizeOAuthApp(authRequest)
   477  	require.Nil(t, resp.Error)
   478  	rurl, _ = url.Parse(redirect)
   479  
   480  	code = rurl.Query().Get("code")
   481  	r, err = HttpGet(ApiClient.Url+"/login/"+model.SERVICE_GITLAB+"/complete?code="+url.QueryEscape(code)+"&state="+url.QueryEscape(state), ApiClient.HttpClient, "", false)
   482  	if err == nil {
   483  		closeBody(r)
   484  	}
   485  
   486  	_, nErr := th.App.Srv().Store.User().UpdateAuthData(
   487  		th.BasicUser.Id, model.SERVICE_GITLAB, &th.BasicUser.Email, th.BasicUser.Email, true)
   488  	require.Nil(t, nErr)
   489  
   490  	redirect, resp = ApiClient.AuthorizeOAuthApp(authRequest)
   491  	require.Nil(t, resp.Error)
   492  	rurl, _ = url.Parse(redirect)
   493  
   494  	code = rurl.Query().Get("code")
   495  	stateProps["action"] = model.OAUTH_ACTION_LOGIN
   496  	state = base64.StdEncoding.EncodeToString([]byte(model.MapToJson(stateProps)))
   497  	if r, err := HttpGet(ApiClient.Url+"/login/"+model.SERVICE_GITLAB+"/complete?code="+url.QueryEscape(code)+"&state="+url.QueryEscape(state), ApiClient.HttpClient, "", false); err == nil {
   498  		closeBody(r)
   499  	}
   500  
   501  	redirect, resp = ApiClient.AuthorizeOAuthApp(authRequest)
   502  	require.Nil(t, resp.Error)
   503  	rurl, _ = url.Parse(redirect)
   504  
   505  	code = rurl.Query().Get("code")
   506  	delete(stateProps, "action")
   507  	state = base64.StdEncoding.EncodeToString([]byte(model.MapToJson(stateProps)))
   508  	if r, err := HttpGet(ApiClient.Url+"/login/"+model.SERVICE_GITLAB+"/complete?code="+url.QueryEscape(code)+"&state="+url.QueryEscape(state), ApiClient.HttpClient, "", false); err == nil {
   509  		closeBody(r)
   510  	}
   511  
   512  	redirect, resp = ApiClient.AuthorizeOAuthApp(authRequest)
   513  	require.Nil(t, resp.Error)
   514  	rurl, _ = url.Parse(redirect)
   515  
   516  	code = rurl.Query().Get("code")
   517  	stateProps["action"] = model.OAUTH_ACTION_SIGNUP
   518  	state = base64.StdEncoding.EncodeToString([]byte(model.MapToJson(stateProps)))
   519  	if r, err := HttpGet(ApiClient.Url+"/login/"+model.SERVICE_GITLAB+"/complete?code="+url.QueryEscape(code)+"&state="+url.QueryEscape(state), ApiClient.HttpClient, "", false); err == nil {
   520  		closeBody(r)
   521  	}
   522  }
   523  
   524  func HttpGet(url string, httpClient *http.Client, authToken string, followRedirect bool) (*http.Response, *model.AppError) {
   525  	rq, _ := http.NewRequest("GET", url, nil)
   526  	rq.Close = true
   527  
   528  	if len(authToken) > 0 {
   529  		rq.Header.Set(model.HEADER_AUTH, authToken)
   530  	}
   531  
   532  	if !followRedirect {
   533  		httpClient.CheckRedirect = func(req *http.Request, via []*http.Request) error {
   534  			return http.ErrUseLastResponse
   535  		}
   536  	}
   537  
   538  	if rp, err := httpClient.Do(rq); err != nil {
   539  		return nil, model.NewAppError(url, "model.client.connecting.app_error", nil, err.Error(), 0)
   540  	} else if rp.StatusCode == 304 {
   541  		return rp, nil
   542  	} else if rp.StatusCode == 307 {
   543  		return rp, nil
   544  	} else if rp.StatusCode >= 300 {
   545  		defer closeBody(rp)
   546  		return rp, model.AppErrorFromJson(rp.Body)
   547  	} else {
   548  		return rp, nil
   549  	}
   550  }
   551  
   552  func closeBody(r *http.Response) {
   553  	if r != nil && r.Body != nil {
   554  		ioutil.ReadAll(r.Body)
   555  		r.Body.Close()
   556  	}
   557  }
   558  
   559  type MattermostTestProvider struct {
   560  }
   561  
   562  func (m *MattermostTestProvider) GetUserFromJson(data io.Reader, tokenUser *model.User) (*model.User, error) {
   563  	user := model.UserFromJson(data)
   564  	user.AuthData = &user.Email
   565  	return user, nil
   566  }
   567  
   568  func (m *MattermostTestProvider) GetSSOSettings(config *model.Config, service string) (*model.SSOSettings, error) {
   569  	return &config.GitLabSettings, nil
   570  }
   571  
   572  func (m *MattermostTestProvider) GetUserFromIdToken(token string) (*model.User, error) {
   573  	return nil, nil
   574  }
   575  
   576  func GenerateTestAppName() string {
   577  	return "fakeoauthapp" + model.NewRandomString(10)
   578  }
   579  
   580  func checkHTTPStatus(t *testing.T, resp *model.Response, expectedStatus int, expectError bool) {
   581  	t.Helper()
   582  
   583  	require.NotNil(t, resp, "Unexpected nil response, expected http:%v, expectError:%v)", expectedStatus, expectError)
   584  
   585  	if expectError {
   586  		require.NotNil(t, resp.Error, "Expected a non-nil error and http status:%v, got nil, %v", expectedStatus, resp.StatusCode)
   587  	} else {
   588  		require.Nil(t, resp.Error, "Expected no error and http status:%v, got %q, http:%v", expectedStatus, resp.Error, resp.StatusCode)
   589  	}
   590  
   591  	require.Equal(t, resp.StatusCode, expectedStatus, "Expected http status:%v, got %v (err: %q)", expectedStatus, resp.StatusCode, resp.Error)
   592  }
   593  
   594  func CheckForbiddenStatus(t *testing.T, resp *model.Response) {
   595  	t.Helper()
   596  	checkHTTPStatus(t, resp, http.StatusForbidden, true)
   597  }
   598  
   599  func CheckUnauthorizedStatus(t *testing.T, resp *model.Response) {
   600  	t.Helper()
   601  	checkHTTPStatus(t, resp, http.StatusUnauthorized, true)
   602  }
   603  
   604  func CheckNotFoundStatus(t *testing.T, resp *model.Response) {
   605  	t.Helper()
   606  	checkHTTPStatus(t, resp, http.StatusNotFound, true)
   607  }
   608  
   609  func CheckBadRequestStatus(t *testing.T, resp *model.Response) {
   610  	t.Helper()
   611  	checkHTTPStatus(t, resp, http.StatusBadRequest, true)
   612  }
   613  
   614  func (th *TestHelper) Login(client *model.Client4, user *model.User) {
   615  	session := &model.Session{
   616  		UserId:  user.Id,
   617  		Roles:   user.GetRawRoles(),
   618  		IsOAuth: false,
   619  	}
   620  	session, _ = th.App.CreateSession(session)
   621  	client.AuthToken = session.Token
   622  	client.AuthType = model.HEADER_BEARER
   623  }
   624  
   625  func (th *TestHelper) Logout(client *model.Client4) {
   626  	client.AuthToken = ""
   627  }
   628  
   629  func (th *TestHelper) SaveDefaultRolePermissions() map[string][]string {
   630  	utils.DisableDebugLogForTest()
   631  
   632  	results := make(map[string][]string)
   633  
   634  	for _, roleName := range []string{
   635  		"system_user",
   636  		"system_admin",
   637  		"team_user",
   638  		"team_admin",
   639  		"channel_user",
   640  		"channel_admin",
   641  	} {
   642  		role, err1 := th.App.GetRoleByName(roleName)
   643  		if err1 != nil {
   644  			utils.EnableDebugLogForTest()
   645  			panic(err1)
   646  		}
   647  
   648  		results[roleName] = role.Permissions
   649  	}
   650  
   651  	utils.EnableDebugLogForTest()
   652  	return results
   653  }
   654  
   655  func (th *TestHelper) RestoreDefaultRolePermissions(data map[string][]string) {
   656  	utils.DisableDebugLogForTest()
   657  
   658  	for roleName, permissions := range data {
   659  		role, err1 := th.App.GetRoleByName(roleName)
   660  		if err1 != nil {
   661  			utils.EnableDebugLogForTest()
   662  			panic(err1)
   663  		}
   664  
   665  		if strings.Join(role.Permissions, " ") == strings.Join(permissions, " ") {
   666  			continue
   667  		}
   668  
   669  		role.Permissions = permissions
   670  
   671  		_, err2 := th.App.UpdateRole(role)
   672  		if err2 != nil {
   673  			utils.EnableDebugLogForTest()
   674  			panic(err2)
   675  		}
   676  	}
   677  
   678  	utils.EnableDebugLogForTest()
   679  }
   680  
   681  // func (th *TestHelper) RemovePermissionFromRole(permission string, roleName string) {
   682  // 	utils.DisableDebugLogForTest()
   683  
   684  // 	role, err1 := th.App.GetRoleByName(roleName)
   685  // 	if err1 != nil {
   686  // 		utils.EnableDebugLogForTest()
   687  // 		panic(err1)
   688  // 	}
   689  
   690  // 	var newPermissions []string
   691  // 	for _, p := range role.Permissions {
   692  // 		if p != permission {
   693  // 			newPermissions = append(newPermissions, p)
   694  // 		}
   695  // 	}
   696  
   697  // 	if strings.Join(role.Permissions, " ") == strings.Join(newPermissions, " ") {
   698  // 		utils.EnableDebugLogForTest()
   699  // 		return
   700  // 	}
   701  
   702  // 	role.Permissions = newPermissions
   703  
   704  // 	_, err2 := th.App.UpdateRole(role)
   705  // 	if err2 != nil {
   706  // 		utils.EnableDebugLogForTest()
   707  // 		panic(err2)
   708  // 	}
   709  
   710  // 	utils.EnableDebugLogForTest()
   711  // }
   712  
   713  func (th *TestHelper) AddPermissionToRole(permission string, roleName string) {
   714  	utils.DisableDebugLogForTest()
   715  
   716  	role, err1 := th.App.GetRoleByName(roleName)
   717  	if err1 != nil {
   718  		utils.EnableDebugLogForTest()
   719  		panic(err1)
   720  	}
   721  
   722  	for _, existingPermission := range role.Permissions {
   723  		if existingPermission == permission {
   724  			utils.EnableDebugLogForTest()
   725  			return
   726  		}
   727  	}
   728  
   729  	role.Permissions = append(role.Permissions, permission)
   730  
   731  	_, err2 := th.App.UpdateRole(role)
   732  	if err2 != nil {
   733  		utils.EnableDebugLogForTest()
   734  		panic(err2)
   735  	}
   736  
   737  	utils.EnableDebugLogForTest()
   738  }