Files
mattermost/web/oauth_test.go
Jesús Espino 074a8e5fd9 Replacing require.nil in web package (#16954)
* Replacing require.nil in web package

* Fixing tests

* Address PR review comments

Co-authored-by: Mattermod <mattermod@users.noreply.github.com>
2021-02-26 07:30:22 +01:00

780 lines
26 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
package web
import (
"bytes"
"encoding/base64"
"io"
"io/ioutil"
"net/http"
"net/http/httptest"
"net/url"
"strings"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/mattermost/mattermost-server/v5/einterfaces"
"github.com/mattermost/mattermost-server/v5/mlog"
"github.com/mattermost/mattermost-server/v5/model"
"github.com/mattermost/mattermost-server/v5/utils"
)
func TestOAuthComplete_AccessDenied(t *testing.T) {
th := Setup(t).InitBasic()
defer th.TearDown()
c := &Context{
App: th.App,
Params: &Params{
Service: "TestService",
},
}
responseWriter := httptest.NewRecorder()
request, _ := http.NewRequest(http.MethodGet, th.App.GetSiteURL()+"/signup/TestService/complete?error=access_denied", nil)
completeOAuth(c, responseWriter, request)
response := responseWriter.Result()
assert.Equal(t, http.StatusTemporaryRedirect, response.StatusCode)
location, _ := url.Parse(response.Header.Get("Location"))
assert.Equal(t, "oauth_access_denied", location.Query().Get("type"))
assert.Equal(t, "TestService", location.Query().Get("service"))
}
func TestAuthorizeOAuthApp(t *testing.T) {
th := Setup(t).InitBasic()
th.Login(ApiClient, th.SystemAdminUser)
defer th.TearDown()
enableOAuth := *th.App.Config().ServiceSettings.EnableOAuthServiceProvider
defer func() {
th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableOAuthServiceProvider = enableOAuth })
}()
th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableOAuthServiceProvider = true })
oapp := &model.OAuthApp{
Name: GenerateTestAppName(),
Homepage: "https://nowhere.com",
Description: "test",
CallbackUrls: []string{"https://nowhere.com"},
CreatorId: th.SystemAdminUser.Id,
}
rapp, appErr := th.App.CreateOAuthApp(oapp)
require.Nil(t, appErr)
authRequest := &model.AuthorizeRequest{
ResponseType: model.AUTHCODE_RESPONSE_TYPE,
ClientId: rapp.Id,
RedirectUri: rapp.CallbackUrls[0],
Scope: "",
State: "123",
}
// Test auth code flow
ruri, resp := ApiClient.AuthorizeOAuthApp(authRequest)
require.Nil(t, resp.Error)
require.NotEmpty(t, ruri, "redirect url should be set")
ru, _ := url.Parse(ruri)
require.NotNil(t, ru, "redirect url unparseable")
require.NotEmpty(t, ru.Query().Get("code"), "authorization code not returned")
require.Equal(t, ru.Query().Get("state"), authRequest.State, "returned state doesn't match")
// Test implicit flow
authRequest.ResponseType = model.IMPLICIT_RESPONSE_TYPE
ruri, resp = ApiClient.AuthorizeOAuthApp(authRequest)
require.Nil(t, resp.Error)
require.False(t, ruri == "", "redirect url should be set")
ru, _ = url.Parse(ruri)
require.NotNil(t, ru, "redirect url unparseable")
values, err := url.ParseQuery(ru.Fragment)
require.NoError(t, err)
assert.False(t, values.Get("access_token") == "", "access_token not returned")
assert.Equal(t, authRequest.State, values.Get("state"), "returned state doesn't match")
oldToken := ApiClient.AuthToken
ApiClient.AuthToken = values.Get("access_token")
_, resp = ApiClient.AuthorizeOAuthApp(authRequest)
CheckForbiddenStatus(t, resp)
ApiClient.AuthToken = oldToken
authRequest.RedirectUri = ""
_, resp = ApiClient.AuthorizeOAuthApp(authRequest)
CheckBadRequestStatus(t, resp)
authRequest.RedirectUri = "http://somewhereelse.com"
_, resp = ApiClient.AuthorizeOAuthApp(authRequest)
CheckBadRequestStatus(t, resp)
authRequest.RedirectUri = rapp.CallbackUrls[0]
authRequest.ResponseType = ""
_, resp = ApiClient.AuthorizeOAuthApp(authRequest)
CheckBadRequestStatus(t, resp)
authRequest.ResponseType = model.AUTHCODE_RESPONSE_TYPE
authRequest.ClientId = ""
_, resp = ApiClient.AuthorizeOAuthApp(authRequest)
CheckBadRequestStatus(t, resp)
authRequest.ClientId = model.NewId()
_, resp = ApiClient.AuthorizeOAuthApp(authRequest)
CheckNotFoundStatus(t, resp)
}
func TestNilAuthorizeOAuthApp(t *testing.T) {
th := Setup(t).InitBasic()
th.Login(ApiClient, th.SystemAdminUser)
defer th.TearDown()
_, resp := ApiClient.AuthorizeOAuthApp(nil)
require.NotNil(t, resp.Error)
assert.Equal(t, "api.context.invalid_body_param.app_error", resp.Error.Id)
}
func TestDeauthorizeOAuthApp(t *testing.T) {
th := Setup(t).InitBasic()
th.Login(ApiClient, th.SystemAdminUser)
defer th.TearDown()
enableOAuth := th.App.Config().ServiceSettings.EnableOAuthServiceProvider
defer func() {
th.App.UpdateConfig(func(cfg *model.Config) { cfg.ServiceSettings.EnableOAuthServiceProvider = enableOAuth })
}()
th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableOAuthServiceProvider = true })
oapp := &model.OAuthApp{
Name: GenerateTestAppName(),
Homepage: "https://nowhere.com",
Description: "test",
CallbackUrls: []string{"https://nowhere.com"},
CreatorId: th.SystemAdminUser.Id,
}
rapp, appErr := th.App.CreateOAuthApp(oapp)
require.Nil(t, appErr)
authRequest := &model.AuthorizeRequest{
ResponseType: model.AUTHCODE_RESPONSE_TYPE,
ClientId: rapp.Id,
RedirectUri: rapp.CallbackUrls[0],
Scope: "",
State: "123",
}
_, resp := ApiClient.AuthorizeOAuthApp(authRequest)
require.Nil(t, resp.Error)
pass, resp := ApiClient.DeauthorizeOAuthApp(rapp.Id)
require.Nil(t, resp.Error)
require.True(t, pass, "should have passed")
_, resp = ApiClient.DeauthorizeOAuthApp("junk")
CheckBadRequestStatus(t, resp)
_, resp = ApiClient.DeauthorizeOAuthApp(model.NewId())
require.Nil(t, resp.Error)
th.Logout(ApiClient)
_, resp = ApiClient.DeauthorizeOAuthApp(rapp.Id)
CheckUnauthorizedStatus(t, resp)
}
func TestOAuthAccessToken(t *testing.T) {
if testing.Short() {
t.SkipNow()
}
th := Setup(t).InitBasic()
th.Login(ApiClient, th.SystemAdminUser)
defer th.TearDown()
enableOAuth := th.App.Config().ServiceSettings.EnableOAuthServiceProvider
defer func() {
th.App.UpdateConfig(func(cfg *model.Config) { cfg.ServiceSettings.EnableOAuthServiceProvider = enableOAuth })
}()
th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableOAuthServiceProvider = true })
defaultRolePermissions := th.SaveDefaultRolePermissions()
defer func() {
th.RestoreDefaultRolePermissions(defaultRolePermissions)
}()
th.AddPermissionToRole(model.PERMISSION_MANAGE_OAUTH.Id, model.TEAM_USER_ROLE_ID)
th.AddPermissionToRole(model.PERMISSION_MANAGE_OAUTH.Id, model.SYSTEM_USER_ROLE_ID)
oauthApp := &model.OAuthApp{
Name: "TestApp5" + model.NewId(),
Homepage: "https://nowhere.com",
Description: "test",
CallbackUrls: []string{"https://nowhere.com"},
CreatorId: th.SystemAdminUser.Id,
}
oauthApp, appErr := th.App.CreateOAuthApp(oauthApp)
require.Nil(t, appErr)
th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableOAuthServiceProvider = false })
data := url.Values{"grant_type": []string{"junk"}, "client_id": []string{"12345678901234567890123456"}, "client_secret": []string{"12345678901234567890123456"}, "code": []string{"junk"}, "redirect_uri": []string{oauthApp.CallbackUrls[0]}}
_, resp := ApiClient.GetOAuthAccessToken(data)
require.NotNil(t, resp.Error, "should have failed - oauth providing turned off - response status code: %v", resp.StatusCode)
th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableOAuthServiceProvider = true })
authRequest := &model.AuthorizeRequest{
ResponseType: model.AUTHCODE_RESPONSE_TYPE,
ClientId: oauthApp.Id,
RedirectUri: oauthApp.CallbackUrls[0],
Scope: "all",
State: "123",
}
redirect, resp := ApiClient.AuthorizeOAuthApp(authRequest)
require.Nil(t, resp.Error)
rurl, _ := url.Parse(redirect)
ApiClient.Logout()
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]}}
_, resp = ApiClient.GetOAuthAccessToken(data)
require.NotNil(t, resp.Error, "should have failed - bad grant type")
data.Set("grant_type", model.ACCESS_TOKEN_GRANT_TYPE)
data.Set("client_id", "")
_, resp = ApiClient.GetOAuthAccessToken(data)
require.NotNil(t, resp.Error, "should have failed - missing client id")
data.Set("client_id", "junk")
_, resp = ApiClient.GetOAuthAccessToken(data)
require.NotNil(t, resp.Error, "should have failed - bad client id")
data.Set("client_id", oauthApp.Id)
data.Set("client_secret", "")
_, resp = ApiClient.GetOAuthAccessToken(data)
require.NotNil(t, resp.Error, "should have failed - missing client secret")
data.Set("client_secret", "junk")
_, resp = ApiClient.GetOAuthAccessToken(data)
require.NotNil(t, resp.Error, "should have failed - bad client secret")
data.Set("client_secret", oauthApp.ClientSecret)
data.Set("code", "")
_, resp = ApiClient.GetOAuthAccessToken(data)
require.NotNil(t, resp.Error, "should have failed - missing code")
data.Set("code", "junk")
_, resp = ApiClient.GetOAuthAccessToken(data)
require.NotNil(t, resp.Error, "should have failed - bad code")
data.Set("code", rurl.Query().Get("code"))
data.Set("redirect_uri", "junk")
_, resp = ApiClient.GetOAuthAccessToken(data)
require.NotNil(t, resp.Error, "should have failed - non-matching redirect uri")
// reset data for successful request
data.Set("grant_type", model.ACCESS_TOKEN_GRANT_TYPE)
data.Set("client_id", oauthApp.Id)
data.Set("client_secret", oauthApp.ClientSecret)
data.Set("code", rurl.Query().Get("code"))
data.Set("redirect_uri", oauthApp.CallbackUrls[0])
token := ""
refreshToken := ""
rsp, resp := ApiClient.GetOAuthAccessToken(data)
require.Nil(t, resp.Error)
require.NotEmpty(t, rsp.AccessToken, "access token not returned")
require.NotEmpty(t, rsp.RefreshToken, "refresh token not returned")
token, refreshToken = rsp.AccessToken, rsp.RefreshToken
require.Equal(t, rsp.TokenType, model.ACCESS_TOKEN_TYPE, "access token type incorrect")
_, err := ApiClient.DoApiGet("/oauth_test", "")
require.Nil(t, err)
ApiClient.SetOAuthToken("")
_, err = ApiClient.DoApiGet("/oauth_test", "")
require.NotNil(t, err, "should have failed - no access token provided")
ApiClient.SetOAuthToken("badtoken")
_, err = ApiClient.DoApiGet("/oauth_test", "")
require.NotNil(t, err, "should have failed - bad token provided")
ApiClient.SetOAuthToken(token)
_, err = ApiClient.DoApiGet("/oauth_test", "")
require.Nil(t, err)
_, resp = ApiClient.GetOAuthAccessToken(data)
require.NotNil(t, resp.Error, "should have failed - tried to reuse auth code")
data.Set("grant_type", model.REFRESH_TOKEN_GRANT_TYPE)
data.Set("client_id", oauthApp.Id)
data.Set("client_secret", oauthApp.ClientSecret)
data.Set("refresh_token", "")
data.Set("redirect_uri", oauthApp.CallbackUrls[0])
data.Del("code")
_, resp = ApiClient.GetOAuthAccessToken(data)
require.NotNil(t, resp.Error, "Should have failed - refresh token empty")
data.Set("refresh_token", refreshToken)
rsp, resp = ApiClient.GetOAuthAccessToken(data)
require.Nil(t, resp.Error)
require.NotEmpty(t, rsp.AccessToken, "access token not returned")
require.NotEmpty(t, rsp.RefreshToken, "refresh token not returned")
require.NotEqual(t, rsp.RefreshToken, refreshToken, "refresh token did not update")
require.Equal(t, rsp.TokenType, model.ACCESS_TOKEN_TYPE, "access token type incorrect")
ApiClient.SetOAuthToken(rsp.AccessToken)
_, err = ApiClient.DoApiGet("/oauth_test", "")
require.Nil(t, err)
data.Set("refresh_token", rsp.RefreshToken)
rsp, resp = ApiClient.GetOAuthAccessToken(data)
require.Nil(t, resp.Error)
require.NotEmpty(t, rsp.AccessToken, "access token not returned")
require.NotEmpty(t, rsp.RefreshToken, "refresh token not returned")
require.NotEqual(t, rsp.RefreshToken, refreshToken, "refresh token did not update")
require.Equal(t, rsp.TokenType, model.ACCESS_TOKEN_TYPE, "access token type incorrect")
ApiClient.SetOAuthToken(rsp.AccessToken)
_, err = ApiClient.DoApiGet("/oauth_test", "")
require.Nil(t, err)
authData := &model.AuthData{ClientId: oauthApp.Id, RedirectUri: oauthApp.CallbackUrls[0], UserId: th.BasicUser.Id, Code: model.NewId(), ExpiresIn: -1}
_, nErr := th.App.Srv().Store.OAuth().SaveAuthData(authData)
require.NoError(t, nErr)
data.Set("grant_type", model.ACCESS_TOKEN_GRANT_TYPE)
data.Set("client_id", oauthApp.Id)
data.Set("client_secret", oauthApp.ClientSecret)
data.Set("redirect_uri", oauthApp.CallbackUrls[0])
data.Set("code", authData.Code)
data.Del("refresh_token")
_, resp = ApiClient.GetOAuthAccessToken(data)
require.NotNil(t, resp.Error, "Should have failed - code is expired")
ApiClient.ClearOAuthToken()
}
func TestOAuthComplete(t *testing.T) {
if testing.Short() {
t.SkipNow()
}
th := Setup(t).InitBasic()
th.Login(ApiClient, th.SystemAdminUser)
defer th.TearDown()
gitLabSettingsEnable := th.App.Config().GitLabSettings.Enable
gitLabSettingsAuthEndpoint := th.App.Config().GitLabSettings.AuthEndpoint
gitLabSettingsId := th.App.Config().GitLabSettings.Id
gitLabSettingsSecret := th.App.Config().GitLabSettings.Secret
gitLabSettingsTokenEndpoint := th.App.Config().GitLabSettings.TokenEndpoint
gitLabSettingsUserApiEndpoint := th.App.Config().GitLabSettings.UserApiEndpoint
enableOAuthServiceProvider := th.App.Config().ServiceSettings.EnableOAuthServiceProvider
defer func() {
th.App.UpdateConfig(func(cfg *model.Config) { cfg.GitLabSettings.Enable = gitLabSettingsEnable })
th.App.UpdateConfig(func(cfg *model.Config) { cfg.GitLabSettings.AuthEndpoint = gitLabSettingsAuthEndpoint })
th.App.UpdateConfig(func(cfg *model.Config) { cfg.GitLabSettings.Id = gitLabSettingsId })
th.App.UpdateConfig(func(cfg *model.Config) { cfg.GitLabSettings.Secret = gitLabSettingsSecret })
th.App.UpdateConfig(func(cfg *model.Config) { cfg.GitLabSettings.TokenEndpoint = gitLabSettingsTokenEndpoint })
th.App.UpdateConfig(func(cfg *model.Config) { cfg.GitLabSettings.UserApiEndpoint = gitLabSettingsUserApiEndpoint })
th.App.UpdateConfig(func(cfg *model.Config) { cfg.ServiceSettings.EnableOAuthServiceProvider = enableOAuthServiceProvider })
}()
r, err := HttpGet(ApiClient.Url+"/login/gitlab/complete?code=123", ApiClient.HttpClient, "", true)
assert.NotNil(t, err)
closeBody(r)
th.App.UpdateConfig(func(cfg *model.Config) { *cfg.GitLabSettings.Enable = true })
r, err = HttpGet(ApiClient.Url+"/login/gitlab/complete?code=123&state=!#$#F@#Yˆ&~ñ", ApiClient.HttpClient, "", true)
assert.NotNil(t, err)
closeBody(r)
th.App.UpdateConfig(func(cfg *model.Config) { *cfg.GitLabSettings.AuthEndpoint = ApiClient.Url + "/oauth/authorize" })
th.App.UpdateConfig(func(cfg *model.Config) { *cfg.GitLabSettings.Id = model.NewId() })
stateProps := map[string]string{}
stateProps["action"] = model.OAUTH_ACTION_LOGIN
stateProps["team_id"] = th.BasicTeam.Id
stateProps["redirect_to"] = *th.App.Config().GitLabSettings.AuthEndpoint
state := base64.StdEncoding.EncodeToString([]byte(model.MapToJson(stateProps)))
r, err = HttpGet(ApiClient.Url+"/login/gitlab/complete?code=123&state="+url.QueryEscape(state), ApiClient.HttpClient, "", true)
assert.NotNil(t, err)
closeBody(r)
stateProps["hash"] = utils.HashSha256(*th.App.Config().GitLabSettings.Id)
state = base64.StdEncoding.EncodeToString([]byte(model.MapToJson(stateProps)))
r, err = HttpGet(ApiClient.Url+"/login/gitlab/complete?code=123&state="+url.QueryEscape(state), ApiClient.HttpClient, "", true)
assert.NotNil(t, err)
closeBody(r)
// We are going to use mattermost as the provider emulating gitlab
th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableOAuthServiceProvider = true })
defaultRolePermissions := th.SaveDefaultRolePermissions()
defer func() {
th.RestoreDefaultRolePermissions(defaultRolePermissions)
}()
th.AddPermissionToRole(model.PERMISSION_MANAGE_OAUTH.Id, model.TEAM_USER_ROLE_ID)
th.AddPermissionToRole(model.PERMISSION_MANAGE_OAUTH.Id, model.SYSTEM_USER_ROLE_ID)
oauthApp := &model.OAuthApp{
Name: "TestApp5" + model.NewId(),
Homepage: "https://nowhere.com",
Description: "test",
CallbackUrls: []string{
ApiClient.Url + "/signup/" + model.SERVICE_GITLAB + "/complete",
ApiClient.Url + "/login/" + model.SERVICE_GITLAB + "/complete",
},
CreatorId: th.SystemAdminUser.Id,
IsTrusted: true,
}
oauthApp, appErr := th.App.CreateOAuthApp(oauthApp)
require.Nil(t, appErr)
th.App.UpdateConfig(func(cfg *model.Config) { *cfg.GitLabSettings.Id = oauthApp.Id })
th.App.UpdateConfig(func(cfg *model.Config) { *cfg.GitLabSettings.Secret = oauthApp.ClientSecret })
th.App.UpdateConfig(func(cfg *model.Config) { *cfg.GitLabSettings.AuthEndpoint = ApiClient.Url + "/oauth/authorize" })
th.App.UpdateConfig(func(cfg *model.Config) { *cfg.GitLabSettings.TokenEndpoint = ApiClient.Url + "/oauth/access_token" })
th.App.UpdateConfig(func(cfg *model.Config) { *cfg.GitLabSettings.UserApiEndpoint = ApiClient.ApiUrl + "/users/me" })
provider := &MattermostTestProvider{}
authRequest := &model.AuthorizeRequest{
ResponseType: model.AUTHCODE_RESPONSE_TYPE,
ClientId: oauthApp.Id,
RedirectUri: oauthApp.CallbackUrls[0],
Scope: "all",
State: "123",
}
redirect, resp := ApiClient.AuthorizeOAuthApp(authRequest)
require.Nil(t, resp.Error)
rurl, _ := url.Parse(redirect)
code := rurl.Query().Get("code")
stateProps["action"] = model.OAUTH_ACTION_EMAIL_TO_SSO
delete(stateProps, "team_id")
stateProps["redirect_to"] = *th.App.Config().GitLabSettings.AuthEndpoint
stateProps["hash"] = utils.HashSha256(*th.App.Config().GitLabSettings.Id)
stateProps["redirect_to"] = "/oauth/authorize"
state = base64.StdEncoding.EncodeToString([]byte(model.MapToJson(stateProps)))
r, err = HttpGet(ApiClient.Url+"/login/"+model.SERVICE_GITLAB+"/complete?code="+url.QueryEscape(code)+"&state="+url.QueryEscape(state), ApiClient.HttpClient, "", false)
if err == nil {
closeBody(r)
}
einterfaces.RegisterOauthProvider(model.SERVICE_GITLAB, provider)
redirect, resp = ApiClient.AuthorizeOAuthApp(authRequest)
require.Nil(t, resp.Error)
rurl, _ = url.Parse(redirect)
code = rurl.Query().Get("code")
r, err = HttpGet(ApiClient.Url+"/login/"+model.SERVICE_GITLAB+"/complete?code="+url.QueryEscape(code)+"&state="+url.QueryEscape(state), ApiClient.HttpClient, "", false)
if err == nil {
closeBody(r)
}
_, nErr := th.App.Srv().Store.User().UpdateAuthData(
th.BasicUser.Id, model.SERVICE_GITLAB, &th.BasicUser.Email, th.BasicUser.Email, true)
require.NoError(t, nErr)
redirect, resp = ApiClient.AuthorizeOAuthApp(authRequest)
require.Nil(t, resp.Error)
rurl, _ = url.Parse(redirect)
code = rurl.Query().Get("code")
stateProps["action"] = model.OAUTH_ACTION_LOGIN
state = base64.StdEncoding.EncodeToString([]byte(model.MapToJson(stateProps)))
if r, err := HttpGet(ApiClient.Url+"/login/"+model.SERVICE_GITLAB+"/complete?code="+url.QueryEscape(code)+"&state="+url.QueryEscape(state), ApiClient.HttpClient, "", false); err == nil {
closeBody(r)
}
redirect, resp = ApiClient.AuthorizeOAuthApp(authRequest)
require.Nil(t, resp.Error)
rurl, _ = url.Parse(redirect)
code = rurl.Query().Get("code")
delete(stateProps, "action")
state = base64.StdEncoding.EncodeToString([]byte(model.MapToJson(stateProps)))
if r, err := HttpGet(ApiClient.Url+"/login/"+model.SERVICE_GITLAB+"/complete?code="+url.QueryEscape(code)+"&state="+url.QueryEscape(state), ApiClient.HttpClient, "", false); err == nil {
closeBody(r)
}
redirect, resp = ApiClient.AuthorizeOAuthApp(authRequest)
require.Nil(t, resp.Error)
rurl, _ = url.Parse(redirect)
code = rurl.Query().Get("code")
stateProps["action"] = model.OAUTH_ACTION_SIGNUP
state = base64.StdEncoding.EncodeToString([]byte(model.MapToJson(stateProps)))
if r, err := HttpGet(ApiClient.Url+"/login/"+model.SERVICE_GITLAB+"/complete?code="+url.QueryEscape(code)+"&state="+url.QueryEscape(state), ApiClient.HttpClient, "", false); err == nil {
closeBody(r)
}
}
func TestOAuthComplete_ErrorMessages(t *testing.T) {
th := Setup(t).InitBasic()
defer th.TearDown()
c := &Context{
App: th.App,
Params: &Params{
Service: "gitlab",
},
}
translationFunc := utils.GetUserTranslations("en")
c.App.SetT(translationFunc)
buffer := &bytes.Buffer{}
c.Logger = mlog.NewTestingLogger(t, buffer)
th.App.UpdateConfig(func(cfg *model.Config) { *cfg.GitLabSettings.Enable = true })
th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableOAuthServiceProvider = true })
provider := &MattermostTestProvider{}
einterfaces.RegisterOauthProvider(model.SERVICE_GITLAB, provider)
responseWriter := httptest.NewRecorder()
// Renders for web & mobile app with webview
request, _ := http.NewRequest(http.MethodGet, th.App.GetSiteURL()+"/signup/gitlab/complete?code=1234", nil)
completeOAuth(c, responseWriter, request)
assert.Contains(t, responseWriter.Body.String(), "<!-- web error message -->")
// Renders for mobile app with redirect url
stateProps := map[string]string{}
stateProps["action"] = model.OAUTH_ACTION_MOBILE
stateProps["redirect_to"] = th.App.Config().NativeAppSettings.AppCustomURLSchemes[0]
state := base64.StdEncoding.EncodeToString([]byte(model.MapToJson(stateProps)))
request2, _ := http.NewRequest(http.MethodGet, th.App.GetSiteURL()+"/signup/gitlab/complete?code=1234&state="+url.QueryEscape(state), nil)
completeOAuth(c, responseWriter, request2)
assert.Contains(t, responseWriter.Body.String(), "<!-- mobile app message -->")
}
func HttpGet(url string, httpClient *http.Client, authToken string, followRedirect bool) (*http.Response, *model.AppError) {
rq, _ := http.NewRequest("GET", url, nil)
rq.Close = true
if authToken != "" {
rq.Header.Set(model.HEADER_AUTH, authToken)
}
if !followRedirect {
httpClient.CheckRedirect = func(req *http.Request, via []*http.Request) error {
return http.ErrUseLastResponse
}
}
if rp, err := httpClient.Do(rq); err != nil {
return nil, model.NewAppError(url, "model.client.connecting.app_error", nil, err.Error(), 0)
} else if rp.StatusCode == 304 {
return rp, nil
} else if rp.StatusCode == 307 {
return rp, nil
} else if rp.StatusCode >= 300 {
defer closeBody(rp)
return rp, model.AppErrorFromJson(rp.Body)
} else {
return rp, nil
}
}
func closeBody(r *http.Response) {
if r != nil && r.Body != nil {
ioutil.ReadAll(r.Body)
r.Body.Close()
}
}
type MattermostTestProvider struct {
}
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)
}
func checkHTTPStatus(t *testing.T, resp *model.Response, expectedStatus int, expectError bool) {
t.Helper()
require.NotNil(t, resp, "Unexpected nil response, expected http:%v, expectError:%v)", expectedStatus, expectError)
if expectError {
require.NotNil(t, resp.Error, "Expected a non-nil error and http status:%v, got nil, %v", expectedStatus, resp.StatusCode)
} else {
require.Nil(t, resp.Error, "Expected no error and http status:%v, got %q, http:%v", expectedStatus, resp.Error, resp.StatusCode)
}
require.Equal(t, resp.StatusCode, expectedStatus, "Expected http status:%v, got %v (err: %q)", expectedStatus, resp.StatusCode, resp.Error)
}
func CheckForbiddenStatus(t *testing.T, resp *model.Response) {
t.Helper()
checkHTTPStatus(t, resp, http.StatusForbidden, true)
}
func CheckUnauthorizedStatus(t *testing.T, resp *model.Response) {
t.Helper()
checkHTTPStatus(t, resp, http.StatusUnauthorized, true)
}
func CheckNotFoundStatus(t *testing.T, resp *model.Response) {
t.Helper()
checkHTTPStatus(t, resp, http.StatusNotFound, true)
}
func CheckBadRequestStatus(t *testing.T, resp *model.Response) {
t.Helper()
checkHTTPStatus(t, resp, http.StatusBadRequest, true)
}
func (th *TestHelper) Login(client *model.Client4, user *model.User) {
session := &model.Session{
UserId: user.Id,
Roles: user.GetRawRoles(),
IsOAuth: false,
}
session, _ = th.App.CreateSession(session)
client.AuthToken = session.Token
client.AuthType = model.HEADER_BEARER
}
func (th *TestHelper) Logout(client *model.Client4) {
client.AuthToken = ""
}
func (th *TestHelper) SaveDefaultRolePermissions() map[string][]string {
utils.DisableDebugLogForTest()
results := make(map[string][]string)
for _, roleName := range []string{
"system_user",
"system_admin",
"team_user",
"team_admin",
"channel_user",
"channel_admin",
} {
role, err1 := th.App.GetRoleByName(roleName)
if err1 != nil {
utils.EnableDebugLogForTest()
panic(err1)
}
results[roleName] = role.Permissions
}
utils.EnableDebugLogForTest()
return results
}
func (th *TestHelper) RestoreDefaultRolePermissions(data map[string][]string) {
utils.DisableDebugLogForTest()
for roleName, permissions := range data {
role, err1 := th.App.GetRoleByName(roleName)
if err1 != nil {
utils.EnableDebugLogForTest()
panic(err1)
}
if strings.Join(role.Permissions, " ") == strings.Join(permissions, " ") {
continue
}
role.Permissions = permissions
_, err2 := th.App.UpdateRole(role)
if err2 != nil {
utils.EnableDebugLogForTest()
panic(err2)
}
}
utils.EnableDebugLogForTest()
}
// func (th *TestHelper) RemovePermissionFromRole(permission string, roleName string) {
// utils.DisableDebugLogForTest()
// role, err1 := th.App.GetRoleByName(roleName)
// if err1 != nil {
// utils.EnableDebugLogForTest()
// panic(err1)
// }
// var newPermissions []string
// for _, p := range role.Permissions {
// if p != permission {
// newPermissions = append(newPermissions, p)
// }
// }
// if strings.Join(role.Permissions, " ") == strings.Join(newPermissions, " ") {
// utils.EnableDebugLogForTest()
// return
// }
// role.Permissions = newPermissions
// _, err2 := th.App.UpdateRole(role)
// if err2 != nil {
// utils.EnableDebugLogForTest()
// panic(err2)
// }
// utils.EnableDebugLogForTest()
// }
func (th *TestHelper) AddPermissionToRole(permission string, roleName string) {
utils.DisableDebugLogForTest()
role, err1 := th.App.GetRoleByName(roleName)
if err1 != nil {
utils.EnableDebugLogForTest()
panic(err1)
}
for _, existingPermission := range role.Permissions {
if existingPermission == permission {
utils.EnableDebugLogForTest()
return
}
}
role.Permissions = append(role.Permissions, permission)
_, err2 := th.App.UpdateRole(role)
if err2 != nil {
utils.EnableDebugLogForTest()
panic(err2)
}
utils.EnableDebugLogForTest()
}