Files
mattermost/api4/oauth_test.go
Emil Velikov f17c15c9d8 Simplify oauth (#8972)
* Remove unused OauthProvider::GetIdentifier

Signed-off-by: Emil Velikov <emil.velikov@collabora.com>

* Reuse gitlab's getAuthData() instead of open-coding it

Signed-off-by: Emil Velikov <emil.velikov@collabora.com>

* Remove OauthProvider::GetAuthDataFromJson interface

The data is already available via GetUserFromJson().AuthData

Signed-off-by: Emil Velikov <emil.velikov@collabora.com>
2018-06-26 17:23:13 -07:00

1135 lines
34 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) 2017 Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package api4
import (
"encoding/base64"
"io"
"io/ioutil"
"net/http"
"net/url"
"strconv"
"testing"
"github.com/stretchr/testify/assert"
"github.com/mattermost/mattermost-server/einterfaces"
"github.com/mattermost/mattermost-server/model"
"github.com/mattermost/mattermost-server/utils"
)
func TestCreateOAuthApp(t *testing.T) {
th := Setup().InitBasic().InitSystemAdmin()
defer th.TearDown()
Client := th.Client
AdminClient := th.SystemAdminClient
defaultRolePermissions := th.SaveDefaultRolePermissions()
defer func() {
th.RestoreDefaultRolePermissions(defaultRolePermissions)
}()
// Grant permission to regular users.
th.AddPermissionToRole(model.PERMISSION_MANAGE_OAUTH.Id, model.SYSTEM_USER_ROLE_ID)
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"}, IsTrusted: true}
rapp, resp := AdminClient.CreateOAuthApp(oapp)
CheckNoError(t, resp)
CheckCreatedStatus(t, resp)
if rapp.Name != oapp.Name {
t.Fatal("names did not match")
}
if rapp.IsTrusted != oapp.IsTrusted {
t.Fatal("trusted did no match")
}
// Revoke permission from regular users.
th.RemovePermissionFromRole(model.PERMISSION_MANAGE_OAUTH.Id, model.SYSTEM_USER_ROLE_ID)
_, resp = Client.CreateOAuthApp(oapp)
CheckForbiddenStatus(t, resp)
// Grant permission to regular users.
th.AddPermissionToRole(model.PERMISSION_MANAGE_OAUTH.Id, model.SYSTEM_USER_ROLE_ID)
rapp, resp = Client.CreateOAuthApp(oapp)
CheckNoError(t, resp)
CheckCreatedStatus(t, resp)
if rapp.IsTrusted {
t.Fatal("trusted should be false - created by non admin")
}
oapp.Name = ""
_, resp = AdminClient.CreateOAuthApp(oapp)
CheckBadRequestStatus(t, resp)
if r, err := Client.DoApiPost("/oauth/apps", "garbage"); err == nil {
t.Fatal("should have failed")
} else {
if r.StatusCode != http.StatusBadRequest {
t.Log("actual: " + strconv.Itoa(r.StatusCode))
t.Log("expected: " + strconv.Itoa(http.StatusBadRequest))
t.Fatal("wrong status code")
}
}
Client.Logout()
_, resp = Client.CreateOAuthApp(oapp)
CheckUnauthorizedStatus(t, resp)
th.App.UpdateConfig(func(cfg *model.Config) { cfg.ServiceSettings.EnableOAuthServiceProvider = false })
oapp.Name = GenerateTestAppName()
_, resp = AdminClient.CreateOAuthApp(oapp)
CheckNotImplementedStatus(t, resp)
}
func TestUpdateOAuthApp(t *testing.T) {
th := Setup().InitBasic().InitSystemAdmin()
defer th.TearDown()
Client := th.Client
AdminClient := th.SystemAdminClient
defaultRolePermissions := th.SaveDefaultRolePermissions()
defer func() {
th.RestoreDefaultRolePermissions(defaultRolePermissions)
}()
// Grant permission to regular users.
th.AddPermissionToRole(model.PERMISSION_MANAGE_OAUTH.Id, model.SYSTEM_USER_ROLE_ID)
th.App.UpdateConfig(func(cfg *model.Config) { cfg.ServiceSettings.EnableOAuthServiceProvider = true })
oapp := &model.OAuthApp{
Name: "oapp",
IsTrusted: false,
IconURL: "https://nowhere.com/img",
Homepage: "https://nowhere.com",
Description: "test",
CallbackUrls: []string{"https://callback.com"},
}
oapp, _ = AdminClient.CreateOAuthApp(oapp)
oapp.Name = "oapp_update"
oapp.IsTrusted = true
oapp.IconURL = "https://nowhere.com/img_update"
oapp.Homepage = "https://nowhere_update.com"
oapp.Description = "test_update"
oapp.CallbackUrls = []string{"https://callback_update.com", "https://another_callback.com"}
updatedApp, resp := AdminClient.UpdateOAuthApp(oapp)
CheckNoError(t, resp)
if updatedApp.Id != oapp.Id {
t.Fatal("Id should have not updated")
}
if updatedApp.CreatorId != oapp.CreatorId {
t.Fatal("CreatorId should have not updated")
}
if updatedApp.CreateAt != oapp.CreateAt {
t.Fatal("CreateAt should have not updated")
}
if updatedApp.UpdateAt == oapp.UpdateAt {
t.Fatal("UpdateAt should have updated")
}
if updatedApp.ClientSecret != oapp.ClientSecret {
t.Fatal("ClientSecret should have not updated")
}
if updatedApp.Name != oapp.Name {
t.Fatal("Name should have updated")
}
if updatedApp.Description != oapp.Description {
t.Fatal("Description should have updated")
}
if updatedApp.IconURL != oapp.IconURL {
t.Fatal("IconURL should have updated")
}
if len(updatedApp.CallbackUrls) == len(oapp.CallbackUrls) {
for i, callbackUrl := range updatedApp.CallbackUrls {
if callbackUrl != oapp.CallbackUrls[i] {
t.Fatal("Description should have updated")
}
}
}
if updatedApp.Homepage != oapp.Homepage {
t.Fatal("Homepage should have updated")
}
if updatedApp.IsTrusted != oapp.IsTrusted {
t.Fatal("IsTrusted should have updated")
}
th.LoginBasic2()
updatedApp.CreatorId = th.BasicUser2.Id
_, resp = Client.UpdateOAuthApp(oapp)
CheckForbiddenStatus(t, resp)
th.LoginBasic()
// Revoke permission from regular users.
th.RemovePermissionFromRole(model.PERMISSION_MANAGE_OAUTH.Id, model.SYSTEM_USER_ROLE_ID)
_, resp = Client.UpdateOAuthApp(oapp)
CheckForbiddenStatus(t, resp)
oapp.Id = "zhk9d1ggatrqz236c7h87im7bc"
_, resp = AdminClient.UpdateOAuthApp(oapp)
CheckNotFoundStatus(t, resp)
th.App.UpdateConfig(func(cfg *model.Config) { cfg.ServiceSettings.EnableOAuthServiceProvider = false })
_, resp = AdminClient.UpdateOAuthApp(oapp)
CheckNotImplementedStatus(t, resp)
Client.Logout()
_, resp = Client.UpdateOAuthApp(oapp)
CheckUnauthorizedStatus(t, resp)
oapp.Id = "junk"
_, resp = AdminClient.UpdateOAuthApp(oapp)
CheckBadRequestStatus(t, resp)
}
func TestGetOAuthApps(t *testing.T) {
th := Setup().InitBasic().InitSystemAdmin()
defer th.TearDown()
Client := th.Client
AdminClient := th.SystemAdminClient
defaultRolePermissions := th.SaveDefaultRolePermissions()
defer func() {
th.RestoreDefaultRolePermissions(defaultRolePermissions)
}()
// Grant permission to regular users.
th.AddPermissionToRole(model.PERMISSION_MANAGE_OAUTH.Id, model.SYSTEM_USER_ROLE_ID)
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"}}
rapp, resp := AdminClient.CreateOAuthApp(oapp)
CheckNoError(t, resp)
oapp.Name = GenerateTestAppName()
rapp2, resp := Client.CreateOAuthApp(oapp)
CheckNoError(t, resp)
apps, resp := AdminClient.GetOAuthApps(0, 1000)
CheckNoError(t, resp)
found1 := false
found2 := false
for _, a := range apps {
if a.Id == rapp.Id {
found1 = true
}
if a.Id == rapp2.Id {
found2 = true
}
}
if !found1 || !found2 {
t.Fatal("missing oauth app")
}
apps, resp = AdminClient.GetOAuthApps(1, 1)
CheckNoError(t, resp)
if len(apps) != 1 {
t.Fatal("paging failed")
}
apps, resp = Client.GetOAuthApps(0, 1000)
CheckNoError(t, resp)
if len(apps) != 1 && apps[0].Id != rapp2.Id {
t.Fatal("wrong apps returned")
}
// Revoke permission from regular users.
th.RemovePermissionFromRole(model.PERMISSION_MANAGE_OAUTH.Id, model.SYSTEM_USER_ROLE_ID)
_, resp = Client.GetOAuthApps(0, 1000)
CheckForbiddenStatus(t, resp)
Client.Logout()
_, resp = Client.GetOAuthApps(0, 1000)
CheckUnauthorizedStatus(t, resp)
th.App.UpdateConfig(func(cfg *model.Config) { cfg.ServiceSettings.EnableOAuthServiceProvider = false })
_, resp = AdminClient.GetOAuthApps(0, 1000)
CheckNotImplementedStatus(t, resp)
}
func TestGetOAuthApp(t *testing.T) {
th := Setup().InitBasic().InitSystemAdmin()
defer th.TearDown()
Client := th.Client
AdminClient := th.SystemAdminClient
defaultRolePermissions := th.SaveDefaultRolePermissions()
defer func() {
th.RestoreDefaultRolePermissions(defaultRolePermissions)
}()
// Grant permission to regular users.
th.AddPermissionToRole(model.PERMISSION_MANAGE_OAUTH.Id, model.SYSTEM_USER_ROLE_ID)
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"}}
rapp, resp := AdminClient.CreateOAuthApp(oapp)
CheckNoError(t, resp)
oapp.Name = GenerateTestAppName()
rapp2, resp := Client.CreateOAuthApp(oapp)
CheckNoError(t, resp)
rrapp, resp := AdminClient.GetOAuthApp(rapp.Id)
CheckNoError(t, resp)
if rapp.Id != rrapp.Id {
t.Fatal("wrong app")
}
if rrapp.ClientSecret == "" {
t.Fatal("should not be sanitized")
}
rrapp2, resp := AdminClient.GetOAuthApp(rapp2.Id)
CheckNoError(t, resp)
if rapp2.Id != rrapp2.Id {
t.Fatal("wrong app")
}
if rrapp2.ClientSecret == "" {
t.Fatal("should not be sanitized")
}
_, resp = Client.GetOAuthApp(rapp2.Id)
CheckNoError(t, resp)
_, resp = Client.GetOAuthApp(rapp.Id)
CheckForbiddenStatus(t, resp)
// Revoke permission from regular users.
th.RemovePermissionFromRole(model.PERMISSION_MANAGE_OAUTH.Id, model.SYSTEM_USER_ROLE_ID)
_, resp = Client.GetOAuthApp(rapp2.Id)
CheckForbiddenStatus(t, resp)
Client.Logout()
_, resp = Client.GetOAuthApp(rapp2.Id)
CheckUnauthorizedStatus(t, resp)
_, resp = AdminClient.GetOAuthApp("junk")
CheckBadRequestStatus(t, resp)
_, resp = AdminClient.GetOAuthApp(model.NewId())
CheckNotFoundStatus(t, resp)
th.App.UpdateConfig(func(cfg *model.Config) { cfg.ServiceSettings.EnableOAuthServiceProvider = false })
_, resp = AdminClient.GetOAuthApp(rapp.Id)
CheckNotImplementedStatus(t, resp)
}
func TestGetOAuthAppInfo(t *testing.T) {
th := Setup().InitBasic().InitSystemAdmin()
defer th.TearDown()
Client := th.Client
AdminClient := th.SystemAdminClient
defaultRolePermissions := th.SaveDefaultRolePermissions()
defer func() {
th.RestoreDefaultRolePermissions(defaultRolePermissions)
}()
// Grant permission to regular users.
th.AddPermissionToRole(model.PERMISSION_MANAGE_OAUTH.Id, model.SYSTEM_USER_ROLE_ID)
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"}}
rapp, resp := AdminClient.CreateOAuthApp(oapp)
CheckNoError(t, resp)
oapp.Name = GenerateTestAppName()
rapp2, resp := Client.CreateOAuthApp(oapp)
CheckNoError(t, resp)
rrapp, resp := AdminClient.GetOAuthAppInfo(rapp.Id)
CheckNoError(t, resp)
if rapp.Id != rrapp.Id {
t.Fatal("wrong app")
}
if rrapp.ClientSecret != "" {
t.Fatal("should be sanitized")
}
rrapp2, resp := AdminClient.GetOAuthAppInfo(rapp2.Id)
CheckNoError(t, resp)
if rapp2.Id != rrapp2.Id {
t.Fatal("wrong app")
}
if rrapp2.ClientSecret != "" {
t.Fatal("should be sanitized")
}
_, resp = Client.GetOAuthAppInfo(rapp2.Id)
CheckNoError(t, resp)
_, resp = Client.GetOAuthAppInfo(rapp.Id)
CheckNoError(t, resp)
// Revoke permission from regular users.
th.RemovePermissionFromRole(model.PERMISSION_MANAGE_OAUTH.Id, model.SYSTEM_USER_ROLE_ID)
_, resp = Client.GetOAuthAppInfo(rapp2.Id)
CheckNoError(t, resp)
Client.Logout()
_, resp = Client.GetOAuthAppInfo(rapp2.Id)
CheckUnauthorizedStatus(t, resp)
_, resp = AdminClient.GetOAuthAppInfo("junk")
CheckBadRequestStatus(t, resp)
_, resp = AdminClient.GetOAuthAppInfo(model.NewId())
CheckNotFoundStatus(t, resp)
th.App.UpdateConfig(func(cfg *model.Config) { cfg.ServiceSettings.EnableOAuthServiceProvider = false })
_, resp = AdminClient.GetOAuthAppInfo(rapp.Id)
CheckNotImplementedStatus(t, resp)
}
func TestDeleteOAuthApp(t *testing.T) {
th := Setup().InitBasic().InitSystemAdmin()
defer th.TearDown()
Client := th.Client
AdminClient := th.SystemAdminClient
defaultRolePermissions := th.SaveDefaultRolePermissions()
defer func() {
th.RestoreDefaultRolePermissions(defaultRolePermissions)
}()
// Grant permission to regular users.
th.AddPermissionToRole(model.PERMISSION_MANAGE_OAUTH.Id, model.SYSTEM_USER_ROLE_ID)
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"}}
rapp, resp := AdminClient.CreateOAuthApp(oapp)
CheckNoError(t, resp)
oapp.Name = GenerateTestAppName()
rapp2, resp := Client.CreateOAuthApp(oapp)
CheckNoError(t, resp)
pass, resp := AdminClient.DeleteOAuthApp(rapp.Id)
CheckNoError(t, resp)
if !pass {
t.Fatal("should have passed")
}
_, resp = AdminClient.DeleteOAuthApp(rapp2.Id)
CheckNoError(t, resp)
rapp, resp = AdminClient.CreateOAuthApp(oapp)
CheckNoError(t, resp)
oapp.Name = GenerateTestAppName()
rapp2, resp = Client.CreateOAuthApp(oapp)
CheckNoError(t, resp)
_, resp = Client.DeleteOAuthApp(rapp.Id)
CheckForbiddenStatus(t, resp)
_, resp = Client.DeleteOAuthApp(rapp2.Id)
CheckNoError(t, resp)
// Revoke permission from regular users.
th.RemovePermissionFromRole(model.PERMISSION_MANAGE_OAUTH.Id, model.SYSTEM_USER_ROLE_ID)
_, resp = Client.DeleteOAuthApp(rapp.Id)
CheckForbiddenStatus(t, resp)
Client.Logout()
_, resp = Client.DeleteOAuthApp(rapp.Id)
CheckUnauthorizedStatus(t, resp)
_, resp = AdminClient.DeleteOAuthApp("junk")
CheckBadRequestStatus(t, resp)
_, resp = AdminClient.DeleteOAuthApp(model.NewId())
CheckNotFoundStatus(t, resp)
th.App.UpdateConfig(func(cfg *model.Config) { cfg.ServiceSettings.EnableOAuthServiceProvider = false })
_, resp = AdminClient.DeleteOAuthApp(rapp.Id)
CheckNotImplementedStatus(t, resp)
}
func TestRegenerateOAuthAppSecret(t *testing.T) {
th := Setup().InitBasic().InitSystemAdmin()
defer th.TearDown()
Client := th.Client
AdminClient := th.SystemAdminClient
defaultRolePermissions := th.SaveDefaultRolePermissions()
defer func() {
th.RestoreDefaultRolePermissions(defaultRolePermissions)
}()
// Grant permission to regular users.
th.AddPermissionToRole(model.PERMISSION_MANAGE_OAUTH.Id, model.SYSTEM_USER_ROLE_ID)
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"}}
rapp, resp := AdminClient.CreateOAuthApp(oapp)
CheckNoError(t, resp)
oapp.Name = GenerateTestAppName()
rapp2, resp := Client.CreateOAuthApp(oapp)
CheckNoError(t, resp)
rrapp, resp := AdminClient.RegenerateOAuthAppSecret(rapp.Id)
CheckNoError(t, resp)
if rrapp.Id != rapp.Id {
t.Fatal("wrong app")
}
if rrapp.ClientSecret == rapp.ClientSecret {
t.Fatal("secret didn't change")
}
_, resp = AdminClient.RegenerateOAuthAppSecret(rapp2.Id)
CheckNoError(t, resp)
rapp, resp = AdminClient.CreateOAuthApp(oapp)
CheckNoError(t, resp)
oapp.Name = GenerateTestAppName()
rapp2, resp = Client.CreateOAuthApp(oapp)
CheckNoError(t, resp)
_, resp = Client.RegenerateOAuthAppSecret(rapp.Id)
CheckForbiddenStatus(t, resp)
_, resp = Client.RegenerateOAuthAppSecret(rapp2.Id)
CheckNoError(t, resp)
// Revoke permission from regular users.
th.RemovePermissionFromRole(model.PERMISSION_MANAGE_OAUTH.Id, model.SYSTEM_USER_ROLE_ID)
_, resp = Client.RegenerateOAuthAppSecret(rapp.Id)
CheckForbiddenStatus(t, resp)
Client.Logout()
_, resp = Client.RegenerateOAuthAppSecret(rapp.Id)
CheckUnauthorizedStatus(t, resp)
_, resp = AdminClient.RegenerateOAuthAppSecret("junk")
CheckBadRequestStatus(t, resp)
_, resp = AdminClient.RegenerateOAuthAppSecret(model.NewId())
CheckNotFoundStatus(t, resp)
th.App.UpdateConfig(func(cfg *model.Config) { cfg.ServiceSettings.EnableOAuthServiceProvider = false })
_, resp = AdminClient.RegenerateOAuthAppSecret(rapp.Id)
CheckNotImplementedStatus(t, resp)
}
func TestGetAuthorizedOAuthAppsForUser(t *testing.T) {
th := Setup().InitBasic().InitSystemAdmin()
defer th.TearDown()
Client := th.Client
AdminClient := th.SystemAdminClient
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"}}
rapp, resp := AdminClient.CreateOAuthApp(oapp)
CheckNoError(t, resp)
authRequest := &model.AuthorizeRequest{
ResponseType: model.AUTHCODE_RESPONSE_TYPE,
ClientId: rapp.Id,
RedirectUri: rapp.CallbackUrls[0],
Scope: "",
State: "123",
}
_, resp = Client.AuthorizeOAuthApp(authRequest)
CheckNoError(t, resp)
apps, resp := Client.GetAuthorizedOAuthAppsForUser(th.BasicUser.Id, 0, 1000)
CheckNoError(t, resp)
found := false
for _, a := range apps {
if a.Id == rapp.Id {
found = true
}
if a.ClientSecret != "" {
t.Fatal("not sanitized")
}
}
if !found {
t.Fatal("missing app")
}
_, resp = Client.GetAuthorizedOAuthAppsForUser(th.BasicUser2.Id, 0, 1000)
CheckForbiddenStatus(t, resp)
_, resp = Client.GetAuthorizedOAuthAppsForUser("junk", 0, 1000)
CheckBadRequestStatus(t, resp)
Client.Logout()
_, resp = Client.GetAuthorizedOAuthAppsForUser(th.BasicUser.Id, 0, 1000)
CheckUnauthorizedStatus(t, resp)
_, resp = AdminClient.GetAuthorizedOAuthAppsForUser(th.BasicUser.Id, 0, 1000)
CheckNoError(t, resp)
}
func TestAuthorizeOAuthApp(t *testing.T) {
th := Setup().InitBasic().InitSystemAdmin()
defer th.TearDown()
Client := th.Client
AdminClient := th.SystemAdminClient
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"}}
rapp, resp := AdminClient.CreateOAuthApp(oapp)
CheckNoError(t, resp)
authRequest := &model.AuthorizeRequest{
ResponseType: model.AUTHCODE_RESPONSE_TYPE,
ClientId: rapp.Id,
RedirectUri: rapp.CallbackUrls[0],
Scope: "",
State: "123",
}
ruri, resp := Client.AuthorizeOAuthApp(authRequest)
CheckNoError(t, resp)
if len(ruri) == 0 {
t.Fatal("redirect url should be set")
}
ru, _ := url.Parse(ruri)
if ru == nil {
t.Fatal("redirect url unparseable")
} else {
if len(ru.Query().Get("code")) == 0 {
t.Fatal("authorization code not returned")
}
if ru.Query().Get("state") != authRequest.State {
t.Fatal("returned state doesn't match")
}
}
authRequest.RedirectUri = ""
_, resp = Client.AuthorizeOAuthApp(authRequest)
CheckBadRequestStatus(t, resp)
authRequest.RedirectUri = "http://somewhereelse.com"
_, resp = Client.AuthorizeOAuthApp(authRequest)
CheckBadRequestStatus(t, resp)
authRequest.RedirectUri = rapp.CallbackUrls[0]
authRequest.ResponseType = ""
_, resp = Client.AuthorizeOAuthApp(authRequest)
CheckBadRequestStatus(t, resp)
authRequest.ResponseType = model.AUTHCODE_RESPONSE_TYPE
authRequest.ClientId = ""
_, resp = Client.AuthorizeOAuthApp(authRequest)
CheckBadRequestStatus(t, resp)
authRequest.ClientId = model.NewId()
_, resp = Client.AuthorizeOAuthApp(authRequest)
CheckNotFoundStatus(t, resp)
}
func TestDeauthorizeOAuthApp(t *testing.T) {
th := Setup().InitBasic().InitSystemAdmin()
defer th.TearDown()
Client := th.Client
AdminClient := th.SystemAdminClient
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"}}
rapp, resp := AdminClient.CreateOAuthApp(oapp)
CheckNoError(t, resp)
authRequest := &model.AuthorizeRequest{
ResponseType: model.AUTHCODE_RESPONSE_TYPE,
ClientId: rapp.Id,
RedirectUri: rapp.CallbackUrls[0],
Scope: "",
State: "123",
}
_, resp = Client.AuthorizeOAuthApp(authRequest)
CheckNoError(t, resp)
pass, resp := Client.DeauthorizeOAuthApp(rapp.Id)
CheckNoError(t, resp)
if !pass {
t.Fatal("should have passed")
}
_, resp = Client.DeauthorizeOAuthApp("junk")
CheckBadRequestStatus(t, resp)
_, resp = Client.DeauthorizeOAuthApp(model.NewId())
CheckNoError(t, resp)
Client.Logout()
_, resp = Client.DeauthorizeOAuthApp(rapp.Id)
CheckUnauthorizedStatus(t, resp)
}
func TestOAuthAccessToken(t *testing.T) {
if testing.Short() {
t.SkipNow()
}
th := Setup().InitBasic()
defer th.TearDown()
Client := th.Client
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"}}
oauthApp = Client.Must(Client.CreateOAuthApp(oauthApp)).(*model.OAuthApp)
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]}}
if _, resp := Client.GetOAuthAccessToken(data); resp.Error == nil {
t.Log(resp.StatusCode)
t.Fatal("should have failed - oauth providing turned off")
}
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 := Client.AuthorizeOAuthApp(authRequest)
CheckNoError(t, resp)
rurl, _ := url.Parse(redirect)
Client.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]}}
if _, resp := Client.GetOAuthAccessToken(data); resp.Error == nil {
t.Fatal("should have failed - bad grant type")
}
data.Set("grant_type", model.ACCESS_TOKEN_GRANT_TYPE)
data.Set("client_id", "")
if _, resp := Client.GetOAuthAccessToken(data); resp.Error == nil {
t.Fatal("should have failed - missing client id")
}
data.Set("client_id", "junk")
if _, resp := Client.GetOAuthAccessToken(data); resp.Error == nil {
t.Fatal("should have failed - bad client id")
}
data.Set("client_id", oauthApp.Id)
data.Set("client_secret", "")
if _, resp := Client.GetOAuthAccessToken(data); resp.Error == nil {
t.Fatal("should have failed - missing client secret")
}
data.Set("client_secret", "junk")
if _, resp := Client.GetOAuthAccessToken(data); resp.Error == nil {
t.Fatal("should have failed - bad client secret")
}
data.Set("client_secret", oauthApp.ClientSecret)
data.Set("code", "")
if _, resp := Client.GetOAuthAccessToken(data); resp.Error == nil {
t.Fatal("should have failed - missing code")
}
data.Set("code", "junk")
if _, resp := Client.GetOAuthAccessToken(data); resp.Error == nil {
t.Fatal("should have failed - bad code")
}
data.Set("code", rurl.Query().Get("code"))
data.Set("redirect_uri", "junk")
if _, resp := Client.GetOAuthAccessToken(data); resp.Error == nil {
t.Fatal("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 := ""
if rsp, resp := Client.GetOAuthAccessToken(data); resp.Error != nil {
t.Fatal(resp.Error)
} else {
if len(rsp.AccessToken) == 0 {
t.Fatal("access token not returned")
} else if len(rsp.RefreshToken) == 0 {
t.Fatal("refresh token not returned")
} else {
token = rsp.AccessToken
refreshToken = rsp.RefreshToken
}
if rsp.TokenType != model.ACCESS_TOKEN_TYPE {
t.Fatal("access token type incorrect")
}
}
if _, err := Client.DoApiGet("/users?page=0&per_page=100&access_token="+token, ""); err != nil {
t.Fatal(err)
}
if _, resp := Client.GetUsers(0, 100, ""); resp.Error == nil {
t.Fatal("should have failed - no access token provided")
}
if _, resp := Client.GetUsers(0, 100, ""); resp.Error == nil {
t.Fatal("should have failed - bad access token provided")
}
Client.SetOAuthToken(token)
if users, resp := Client.GetUsers(0, 100, ""); resp.Error != nil {
t.Fatal(resp.Error)
} else {
if len(users) == 0 {
t.Fatal("users empty - did not get results correctly")
}
}
if _, resp := Client.GetOAuthAccessToken(data); resp.Error == nil {
t.Fatal("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")
if _, resp := Client.GetOAuthAccessToken(data); resp.Error == nil {
t.Fatal("Should have failed - refresh token empty")
}
data.Set("refresh_token", refreshToken)
if rsp, resp := Client.GetOAuthAccessToken(data); resp.Error != nil {
t.Fatal(resp.Error)
} else {
if len(rsp.AccessToken) == 0 {
t.Fatal("access token not returned")
} else if len(rsp.RefreshToken) == 0 {
t.Fatal("refresh token not returned")
} else if rsp.RefreshToken == refreshToken {
t.Fatal("refresh token did not update")
}
if rsp.TokenType != model.ACCESS_TOKEN_TYPE {
t.Fatal("access token type incorrect")
}
Client.SetOAuthToken(rsp.AccessToken)
_, resp = Client.GetMe("")
if resp.Error != nil {
t.Fatal(resp.Error)
}
data.Set("refresh_token", rsp.RefreshToken)
}
if rsp, resp := Client.GetOAuthAccessToken(data); resp.Error != nil {
t.Fatal(resp.Error)
} else {
if len(rsp.AccessToken) == 0 {
t.Fatal("access token not returned")
} else if len(rsp.RefreshToken) == 0 {
t.Fatal("refresh token not returned")
} else if rsp.RefreshToken == refreshToken {
t.Fatal("refresh token did not update")
}
if rsp.TokenType != model.ACCESS_TOKEN_TYPE {
t.Fatal("access token type incorrect")
}
Client.SetOAuthToken(rsp.AccessToken)
_, resp = Client.GetMe("")
if resp.Error != nil {
t.Fatal(resp.Error)
}
}
authData := &model.AuthData{ClientId: oauthApp.Id, RedirectUri: oauthApp.CallbackUrls[0], UserId: th.BasicUser.Id, Code: model.NewId(), ExpiresIn: -1}
<-th.App.Srv.Store.OAuth().SaveAuthData(authData)
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")
if _, resp := Client.GetOAuthAccessToken(data); resp.Error == nil {
t.Fatal("Should have failed - code is expired")
}
Client.ClearOAuthToken()
}
func TestOAuthComplete(t *testing.T) {
if testing.Short() {
t.SkipNow()
}
th := Setup().InitBasic()
defer th.TearDown()
Client := th.Client
r, err := HttpGet(Client.Url+"/login/gitlab/complete?code=123", Client.HttpClient, "", true)
assert.NotNil(t, err)
closeBody(r)
th.App.UpdateConfig(func(cfg *model.Config) { cfg.GitLabSettings.Enable = true })
r, err = HttpGet(Client.Url+"/login/gitlab/complete?code=123&state=!#$#F@#Yˆ&~ñ", Client.HttpClient, "", true)
assert.NotNil(t, err)
closeBody(r)
th.App.UpdateConfig(func(cfg *model.Config) { cfg.GitLabSettings.AuthEndpoint = Client.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(Client.Url+"/login/gitlab/complete?code=123&state="+url.QueryEscape(state), Client.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(Client.Url+"/login/gitlab/complete?code=123&state="+url.QueryEscape(state), Client.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{
Client.Url + "/signup/" + model.SERVICE_GITLAB + "/complete",
Client.Url + "/login/" + model.SERVICE_GITLAB + "/complete",
},
IsTrusted: true,
}
oauthApp = Client.Must(Client.CreateOAuthApp(oauthApp)).(*model.OAuthApp)
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 = Client.Url + "/oauth/authorize" })
th.App.UpdateConfig(func(cfg *model.Config) { cfg.GitLabSettings.TokenEndpoint = Client.Url + "/oauth/access_token" })
th.App.UpdateConfig(func(cfg *model.Config) { cfg.GitLabSettings.UserApiEndpoint = Client.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 := Client.AuthorizeOAuthApp(authRequest)
CheckNoError(t, resp)
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)))
if r, err := HttpGet(Client.Url+"/login/"+model.SERVICE_GITLAB+"/complete?code="+url.QueryEscape(code)+"&state="+url.QueryEscape(state), Client.HttpClient, "", false); err == nil {
closeBody(r)
}
einterfaces.RegisterOauthProvider(model.SERVICE_GITLAB, provider)
redirect, resp = Client.AuthorizeOAuthApp(authRequest)
CheckNoError(t, resp)
rurl, _ = url.Parse(redirect)
code = rurl.Query().Get("code")
if r, err := HttpGet(Client.Url+"/login/"+model.SERVICE_GITLAB+"/complete?code="+url.QueryEscape(code)+"&state="+url.QueryEscape(state), Client.HttpClient, "", false); err == nil {
closeBody(r)
}
if result := <-th.App.Srv.Store.User().UpdateAuthData(
th.BasicUser.Id, model.SERVICE_GITLAB, &th.BasicUser.Email, th.BasicUser.Email, true); result.Err != nil {
t.Fatal(result.Err)
}
redirect, resp = Client.AuthorizeOAuthApp(authRequest)
CheckNoError(t, resp)
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(Client.Url+"/login/"+model.SERVICE_GITLAB+"/complete?code="+url.QueryEscape(code)+"&state="+url.QueryEscape(state), Client.HttpClient, "", false); err == nil {
closeBody(r)
}
redirect, resp = Client.AuthorizeOAuthApp(authRequest)
CheckNoError(t, resp)
rurl, _ = url.Parse(redirect)
code = rurl.Query().Get("code")
delete(stateProps, "action")
state = base64.StdEncoding.EncodeToString([]byte(model.MapToJson(stateProps)))
if r, err := HttpGet(Client.Url+"/login/"+model.SERVICE_GITLAB+"/complete?code="+url.QueryEscape(code)+"&state="+url.QueryEscape(state), Client.HttpClient, "", false); err == nil {
closeBody(r)
}
redirect, resp = Client.AuthorizeOAuthApp(authRequest)
CheckNoError(t, resp)
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(Client.Url+"/login/"+model.SERVICE_GITLAB+"/complete?code="+url.QueryEscape(code)+"&state="+url.QueryEscape(state), Client.HttpClient, "", false); err == nil {
closeBody(r)
}
}
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 len(authToken) > 0 {
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) *model.User {
user := model.UserFromJson(data)
user.AuthData = &user.Email
return user
}