mirror of
https://github.com/hanzoai/team.git
synced 2026-09-30 01:57:35 +00:00
* [MM-67605] Add DCR redirect URI allowlist enforcement Introduce ServiceSettings.DCRRedirectURIAllowlist with glob-based validation and enforce it during OAuth dynamic client registration to block unapproved redirect URIs. Add System Console wiring and tests for config validation, wildcard matching semantics, API error behavior, and localhost wildcard support. * Fix pre-commit checks: TypeScript type assertion, gofmt, and regenerate CI artifacts - admin_definition_dcr_allowlist.test.tsx: Add AdminDefinitionSettingInput type assertion for 'multiple' property - oauth_dcr_test.go: Fix comment spacing (gofmt) - Regenerate mocks, go.sum, gen-serialized, mmctl-docs per CI requirements * Revert unnecessary pre-commit regenerations Revert mmctl docs, mocks, go.sum, and gen-serialized to master. Keep only the TypeScript and gofmt fixes from the previous commit. * Fix import order in admin_definition_dcr_allowlist.test.tsx * Fix i18n * Update server/public/model/oauth_dcr.go Co-authored-by: Eva Sarafianou <[email protected]> * Fix --------- Co-authored-by: Eva Sarafianou <[email protected]> Co-authored-by: Mattermost Build <[email protected]> Co-authored-by: Hanzo Dev <[email protected]>
1003 lines
36 KiB
Go
1003 lines
36 KiB
Go
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
|
// See LICENSE.txt for license information.
|
|
|
|
package api4
|
|
|
|
import (
|
|
"bytes"
|
|
"context"
|
|
"encoding/json"
|
|
"fmt"
|
|
"io"
|
|
"net/http"
|
|
"os"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
|
|
"github.com/mattermost/mattermost/server/public/model"
|
|
"github.com/mattermost/mattermost/server/v8/channels/app"
|
|
)
|
|
|
|
func TestCreateOAuthApp(t *testing.T) {
|
|
mainHelper.Parallel(t)
|
|
th := Setup(t)
|
|
client := th.Client
|
|
adminClient := th.SystemAdminClient
|
|
|
|
defaultRolePermissions := th.SaveDefaultRolePermissions(t)
|
|
enableOAuthServiceProvider := th.App.Config().ServiceSettings.EnableOAuthServiceProvider
|
|
defer func() {
|
|
th.RestoreDefaultRolePermissions(t, defaultRolePermissions)
|
|
th.App.UpdateConfig(func(cfg *model.Config) { cfg.ServiceSettings.EnableOAuthServiceProvider = enableOAuthServiceProvider })
|
|
}()
|
|
|
|
// Grant permission to regular users.
|
|
th.AddPermissionToRole(t, model.PermissionManageOAuth.Id, model.SystemUserRoleId)
|
|
|
|
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, err := adminClient.CreateOAuthApp(context.Background(), oapp)
|
|
require.NoError(t, err)
|
|
CheckCreatedStatus(t, resp)
|
|
assert.Equal(t, oapp.Name, rapp.Name, "names did not match")
|
|
assert.Equal(t, oapp.IsTrusted, rapp.IsTrusted, "trusted did no match")
|
|
|
|
// Revoke permission from regular users.
|
|
th.RemovePermissionFromRole(t, model.PermissionManageOAuth.Id, model.SystemUserRoleId)
|
|
|
|
_, resp, err = client.CreateOAuthApp(context.Background(), oapp)
|
|
require.Error(t, err)
|
|
CheckForbiddenStatus(t, resp)
|
|
// Grant permission to regular users.
|
|
th.AddPermissionToRole(t, model.PermissionManageOAuth.Id, model.SystemUserRoleId)
|
|
|
|
rapp, resp, err = client.CreateOAuthApp(context.Background(), oapp)
|
|
require.NoError(t, err)
|
|
CheckCreatedStatus(t, resp)
|
|
|
|
assert.False(t, rapp.IsTrusted, "trusted should be false - created by non admin")
|
|
|
|
oapp.Name = ""
|
|
_, resp, err = adminClient.CreateOAuthApp(context.Background(), oapp)
|
|
require.Error(t, err)
|
|
CheckBadRequestStatus(t, resp)
|
|
|
|
r, err := client.DoAPIPost(context.Background(), "/oauth/apps", "garbage")
|
|
require.Error(t, err, "expected error from garbage post")
|
|
assert.Equal(t, http.StatusBadRequest, r.StatusCode)
|
|
|
|
_, err = client.Logout(context.Background())
|
|
require.NoError(t, err)
|
|
_, resp, err = client.CreateOAuthApp(context.Background(), oapp)
|
|
require.Error(t, err)
|
|
CheckUnauthorizedStatus(t, resp)
|
|
|
|
th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableOAuthServiceProvider = false })
|
|
oapp.Name = GenerateTestAppName()
|
|
_, resp, err = adminClient.CreateOAuthApp(context.Background(), oapp)
|
|
require.Error(t, err)
|
|
CheckNotImplementedStatus(t, resp)
|
|
}
|
|
|
|
func TestUpdateOAuthApp(t *testing.T) {
|
|
t.Skip("https://mattermost.atlassian.net/browse/MM-62895")
|
|
|
|
mainHelper.Parallel(t)
|
|
|
|
th := Setup(t).InitBasic(t)
|
|
client := th.Client
|
|
adminClient := th.SystemAdminClient
|
|
|
|
defaultRolePermissions := th.SaveDefaultRolePermissions(t)
|
|
enableOAuthServiceProvider := th.App.Config().ServiceSettings.EnableOAuthServiceProvider
|
|
defer func() {
|
|
th.RestoreDefaultRolePermissions(t, defaultRolePermissions)
|
|
th.App.UpdateConfig(func(cfg *model.Config) { cfg.ServiceSettings.EnableOAuthServiceProvider = enableOAuthServiceProvider })
|
|
}()
|
|
|
|
// Grant permission to regular users.
|
|
th.AddPermissionToRole(t, model.PermissionManageOAuth.Id, model.SystemUserRoleId)
|
|
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(context.Background(), 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, _, err := adminClient.UpdateOAuthApp(context.Background(), oapp)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, oapp.Id, updatedApp.Id, "Id should have not updated")
|
|
assert.Equal(t, oapp.CreatorId, updatedApp.CreatorId, "CreatorId should have not updated")
|
|
assert.Equal(t, oapp.CreateAt, updatedApp.CreateAt, "CreateAt should have not updated")
|
|
assert.NotEqual(t, oapp.UpdateAt, updatedApp.UpdateAt, "UpdateAt should have updated")
|
|
assert.Equal(t, oapp.ClientSecret, updatedApp.ClientSecret, "ClientSecret should have not updated")
|
|
assert.Equal(t, oapp.Name, updatedApp.Name, "Name should have updated")
|
|
assert.Equal(t, oapp.Description, updatedApp.Description, "Description should have updated")
|
|
assert.Equal(t, oapp.IconURL, updatedApp.IconURL, "IconURL should have updated")
|
|
|
|
if len(updatedApp.CallbackUrls) == len(oapp.CallbackUrls) {
|
|
for i, callbackURL := range updatedApp.CallbackUrls {
|
|
assert.Equal(t, oapp.CallbackUrls[i], callbackURL, "Description should have updated")
|
|
}
|
|
}
|
|
assert.Equal(t, oapp.Homepage, updatedApp.Homepage, "Homepage should have updated")
|
|
assert.Equal(t, oapp.IsTrusted, updatedApp.IsTrusted, "IsTrusted should have updated")
|
|
|
|
th.LoginBasic2(t)
|
|
updatedApp.CreatorId = th.BasicUser2.Id
|
|
_, resp, err := client.UpdateOAuthApp(context.Background(), oapp)
|
|
require.Error(t, err)
|
|
CheckForbiddenStatus(t, resp)
|
|
|
|
th.LoginBasic(t)
|
|
|
|
// Revoke permission from regular users.
|
|
th.RemovePermissionFromRole(t, model.PermissionManageOAuth.Id, model.SystemUserRoleId)
|
|
|
|
_, resp, err = client.UpdateOAuthApp(context.Background(), oapp)
|
|
require.Error(t, err)
|
|
CheckForbiddenStatus(t, resp)
|
|
|
|
oapp.Id = "zhk9d1ggatrqz236c7h87im7bc"
|
|
_, resp, err = adminClient.UpdateOAuthApp(context.Background(), oapp)
|
|
require.Error(t, err)
|
|
CheckNotFoundStatus(t, resp)
|
|
|
|
th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableOAuthServiceProvider = false })
|
|
|
|
_, resp, err = adminClient.UpdateOAuthApp(context.Background(), oapp)
|
|
require.Error(t, err)
|
|
CheckNotImplementedStatus(t, resp)
|
|
|
|
_, err = client.Logout(context.Background())
|
|
require.NoError(t, err)
|
|
_, resp, err = client.UpdateOAuthApp(context.Background(), oapp)
|
|
require.Error(t, err)
|
|
CheckUnauthorizedStatus(t, resp)
|
|
|
|
oapp.Id = "junk"
|
|
_, resp, err = adminClient.UpdateOAuthApp(context.Background(), oapp)
|
|
require.Error(t, err)
|
|
CheckBadRequestStatus(t, resp)
|
|
|
|
th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableOAuthServiceProvider = true })
|
|
th.AddPermissionToRole(t, model.PermissionManageOAuth.Id, model.SystemUserRoleId)
|
|
th.LoginBasic(t)
|
|
|
|
userOapp := &model.OAuthApp{
|
|
Name: "useroapp",
|
|
IsTrusted: false,
|
|
IconURL: "https://nowhere.com/img",
|
|
Homepage: "https://nowhere.com",
|
|
Description: "test",
|
|
CallbackUrls: []string{"https://callback.com"},
|
|
}
|
|
|
|
userOapp, _, err = client.CreateOAuthApp(context.Background(), userOapp)
|
|
require.NoError(t, err)
|
|
|
|
userOapp.IsTrusted = true
|
|
userOapp, _, err = client.UpdateOAuthApp(context.Background(), userOapp)
|
|
require.NoError(t, err)
|
|
assert.False(t, userOapp.IsTrusted)
|
|
|
|
userOapp.IsTrusted = true
|
|
userOapp, _, err = adminClient.UpdateOAuthApp(context.Background(), userOapp)
|
|
require.NoError(t, err)
|
|
assert.True(t, userOapp.IsTrusted)
|
|
|
|
userOapp.IsTrusted = false
|
|
userOapp, _, err = client.UpdateOAuthApp(context.Background(), userOapp)
|
|
require.NoError(t, err)
|
|
assert.True(t, userOapp.IsTrusted)
|
|
}
|
|
|
|
func TestGetOAuthApps(t *testing.T) {
|
|
mainHelper.Parallel(t)
|
|
th := Setup(t)
|
|
client := th.Client
|
|
adminClient := th.SystemAdminClient
|
|
|
|
defaultRolePermissions := th.SaveDefaultRolePermissions(t)
|
|
enableOAuthServiceProvider := th.App.Config().ServiceSettings.EnableOAuthServiceProvider
|
|
defer func() {
|
|
th.RestoreDefaultRolePermissions(t, defaultRolePermissions)
|
|
th.App.UpdateConfig(func(cfg *model.Config) { cfg.ServiceSettings.EnableOAuthServiceProvider = enableOAuthServiceProvider })
|
|
}()
|
|
|
|
// Grant permission to regular users.
|
|
th.AddPermissionToRole(t, model.PermissionManageOAuth.Id, model.SystemUserRoleId)
|
|
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, _, err := adminClient.CreateOAuthApp(context.Background(), oapp)
|
|
require.NoError(t, err)
|
|
|
|
oapp.Name = GenerateTestAppName()
|
|
rapp2, _, err := client.CreateOAuthApp(context.Background(), oapp)
|
|
require.NoError(t, err)
|
|
|
|
apps, _, err := adminClient.GetOAuthApps(context.Background(), 0, 1000)
|
|
require.NoError(t, err)
|
|
|
|
found1 := false
|
|
found2 := false
|
|
for _, a := range apps {
|
|
if a.Id == rapp.Id {
|
|
found1 = true
|
|
}
|
|
if a.Id == rapp2.Id {
|
|
found2 = true
|
|
}
|
|
}
|
|
assert.Truef(t, found1, "missing oauth app %v", rapp.Id)
|
|
assert.Truef(t, found2, "missing oauth app %v", rapp2.Id)
|
|
|
|
apps, _, err = adminClient.GetOAuthApps(context.Background(), 1, 1)
|
|
require.NoError(t, err)
|
|
require.Equal(t, 1, len(apps), "paging failed")
|
|
|
|
apps, _, err = client.GetOAuthApps(context.Background(), 0, 1000)
|
|
require.NoError(t, err)
|
|
require.True(t, len(apps) == 1 || apps[0].Id == rapp2.Id, "wrong apps returned")
|
|
|
|
// Revoke permission from regular users.
|
|
th.RemovePermissionFromRole(t, model.PermissionManageOAuth.Id, model.SystemUserRoleId)
|
|
|
|
_, resp, err := client.GetOAuthApps(context.Background(), 0, 1000)
|
|
require.Error(t, err)
|
|
CheckForbiddenStatus(t, resp)
|
|
|
|
_, err = client.Logout(context.Background())
|
|
require.NoError(t, err)
|
|
|
|
_, resp, err = client.GetOAuthApps(context.Background(), 0, 1000)
|
|
require.Error(t, err)
|
|
CheckUnauthorizedStatus(t, resp)
|
|
|
|
th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableOAuthServiceProvider = false })
|
|
_, resp, err = adminClient.GetOAuthApps(context.Background(), 0, 1000)
|
|
require.Error(t, err)
|
|
CheckNotImplementedStatus(t, resp)
|
|
}
|
|
|
|
func TestGetOAuthApp(t *testing.T) {
|
|
mainHelper.Parallel(t)
|
|
th := Setup(t)
|
|
client := th.Client
|
|
adminClient := th.SystemAdminClient
|
|
|
|
defaultRolePermissions := th.SaveDefaultRolePermissions(t)
|
|
enableOAuthServiceProvider := th.App.Config().ServiceSettings.EnableOAuthServiceProvider
|
|
defer func() {
|
|
th.RestoreDefaultRolePermissions(t, defaultRolePermissions)
|
|
th.App.UpdateConfig(func(cfg *model.Config) { cfg.ServiceSettings.EnableOAuthServiceProvider = enableOAuthServiceProvider })
|
|
}()
|
|
|
|
// Grant permission to regular users.
|
|
th.AddPermissionToRole(t, model.PermissionManageOAuth.Id, model.SystemUserRoleId)
|
|
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, _, err := adminClient.CreateOAuthApp(context.Background(), oapp)
|
|
require.NoError(t, err)
|
|
|
|
oapp.Name = GenerateTestAppName()
|
|
rapp2, _, err := client.CreateOAuthApp(context.Background(), oapp)
|
|
require.NoError(t, err)
|
|
|
|
rrapp, _, err := adminClient.GetOAuthApp(context.Background(), rapp.Id)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, rapp.Id, rrapp.Id, "wrong app")
|
|
assert.NotEqual(t, "", rrapp.ClientSecret, "should not be sanitized")
|
|
|
|
rrapp2, _, err := adminClient.GetOAuthApp(context.Background(), rapp2.Id)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, rapp2.Id, rrapp2.Id, "wrong app")
|
|
assert.NotEqual(t, "", rrapp2.ClientSecret, "should not be sanitized")
|
|
|
|
_, _, err = client.GetOAuthApp(context.Background(), rapp2.Id)
|
|
require.NoError(t, err)
|
|
|
|
_, resp, err := client.GetOAuthApp(context.Background(), rapp.Id)
|
|
require.Error(t, err)
|
|
CheckForbiddenStatus(t, resp)
|
|
|
|
// Revoke permission from regular users.
|
|
th.RemovePermissionFromRole(t, model.PermissionManageOAuth.Id, model.SystemUserRoleId)
|
|
|
|
_, resp, err = client.GetOAuthApp(context.Background(), rapp2.Id)
|
|
require.Error(t, err)
|
|
CheckForbiddenStatus(t, resp)
|
|
|
|
_, err = client.Logout(context.Background())
|
|
require.NoError(t, err)
|
|
|
|
_, resp, err = client.GetOAuthApp(context.Background(), rapp2.Id)
|
|
require.Error(t, err)
|
|
CheckUnauthorizedStatus(t, resp)
|
|
|
|
_, resp, err = adminClient.GetOAuthApp(context.Background(), "junk")
|
|
require.Error(t, err)
|
|
CheckBadRequestStatus(t, resp)
|
|
|
|
_, resp, err = adminClient.GetOAuthApp(context.Background(), model.NewId())
|
|
require.Error(t, err)
|
|
CheckNotFoundStatus(t, resp)
|
|
|
|
th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableOAuthServiceProvider = false })
|
|
_, resp, err = adminClient.GetOAuthApp(context.Background(), rapp.Id)
|
|
require.Error(t, err)
|
|
CheckNotImplementedStatus(t, resp)
|
|
}
|
|
|
|
func TestGetOAuthAppInfo(t *testing.T) {
|
|
mainHelper.Parallel(t)
|
|
th := Setup(t)
|
|
client := th.Client
|
|
adminClient := th.SystemAdminClient
|
|
|
|
defaultRolePermissions := th.SaveDefaultRolePermissions(t)
|
|
enableOAuthServiceProvider := th.App.Config().ServiceSettings.EnableOAuthServiceProvider
|
|
defer func() {
|
|
th.RestoreDefaultRolePermissions(t, defaultRolePermissions)
|
|
th.App.UpdateConfig(func(cfg *model.Config) { cfg.ServiceSettings.EnableOAuthServiceProvider = enableOAuthServiceProvider })
|
|
}()
|
|
|
|
// Grant permission to regular users.
|
|
th.AddPermissionToRole(t, model.PermissionManageOAuth.Id, model.SystemUserRoleId)
|
|
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, _, err := adminClient.CreateOAuthApp(context.Background(), oapp)
|
|
require.NoError(t, err)
|
|
|
|
oapp.Name = GenerateTestAppName()
|
|
rapp2, _, err := client.CreateOAuthApp(context.Background(), oapp)
|
|
require.NoError(t, err)
|
|
|
|
rrapp, _, err := adminClient.GetOAuthAppInfo(context.Background(), rapp.Id)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, rapp.Id, rrapp.Id, "wrong app")
|
|
assert.Equal(t, "", rrapp.ClientSecret, "should be sanitized")
|
|
|
|
rrapp2, _, err := adminClient.GetOAuthAppInfo(context.Background(), rapp2.Id)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, rapp2.Id, rrapp2.Id, "wrong app")
|
|
assert.Equal(t, "", rrapp2.ClientSecret, "should be sanitized")
|
|
|
|
_, _, err = client.GetOAuthAppInfo(context.Background(), rapp2.Id)
|
|
require.NoError(t, err)
|
|
|
|
_, _, err = client.GetOAuthAppInfo(context.Background(), rapp.Id)
|
|
require.NoError(t, err)
|
|
|
|
// Revoke permission from regular users.
|
|
th.RemovePermissionFromRole(t, model.PermissionManageOAuth.Id, model.SystemUserRoleId)
|
|
|
|
_, _, err = client.GetOAuthAppInfo(context.Background(), rapp2.Id)
|
|
require.NoError(t, err)
|
|
|
|
_, err = client.Logout(context.Background())
|
|
require.NoError(t, err)
|
|
|
|
_, resp, err := client.GetOAuthAppInfo(context.Background(), rapp2.Id)
|
|
require.Error(t, err)
|
|
CheckUnauthorizedStatus(t, resp)
|
|
|
|
_, resp, err = adminClient.GetOAuthAppInfo(context.Background(), "junk")
|
|
require.Error(t, err)
|
|
CheckBadRequestStatus(t, resp)
|
|
|
|
_, resp, err = adminClient.GetOAuthAppInfo(context.Background(), model.NewId())
|
|
require.Error(t, err)
|
|
CheckNotFoundStatus(t, resp)
|
|
|
|
th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableOAuthServiceProvider = false })
|
|
_, resp, err = adminClient.GetOAuthAppInfo(context.Background(), rapp.Id)
|
|
require.Error(t, err)
|
|
CheckNotImplementedStatus(t, resp)
|
|
}
|
|
|
|
func TestDeleteOAuthApp(t *testing.T) {
|
|
mainHelper.Parallel(t)
|
|
th := Setup(t)
|
|
client := th.Client
|
|
adminClient := th.SystemAdminClient
|
|
|
|
defaultRolePermissions := th.SaveDefaultRolePermissions(t)
|
|
enableOAuthServiceProvider := th.App.Config().ServiceSettings.EnableOAuthServiceProvider
|
|
defer func() {
|
|
th.RestoreDefaultRolePermissions(t, defaultRolePermissions)
|
|
th.App.UpdateConfig(func(cfg *model.Config) { cfg.ServiceSettings.EnableOAuthServiceProvider = enableOAuthServiceProvider })
|
|
}()
|
|
|
|
// Grant permission to regular users.
|
|
th.AddPermissionToRole(t, model.PermissionManageOAuth.Id, model.SystemUserRoleId)
|
|
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, _, err := adminClient.CreateOAuthApp(context.Background(), oapp)
|
|
require.NoError(t, err)
|
|
|
|
oapp.Name = GenerateTestAppName()
|
|
rapp2, _, err := client.CreateOAuthApp(context.Background(), oapp)
|
|
require.NoError(t, err)
|
|
|
|
_, err = adminClient.DeleteOAuthApp(context.Background(), rapp.Id)
|
|
require.NoError(t, err)
|
|
|
|
_, err = adminClient.DeleteOAuthApp(context.Background(), rapp2.Id)
|
|
require.NoError(t, err)
|
|
|
|
rapp, _, err = adminClient.CreateOAuthApp(context.Background(), oapp)
|
|
require.NoError(t, err)
|
|
|
|
oapp.Name = GenerateTestAppName()
|
|
rapp2, _, err = client.CreateOAuthApp(context.Background(), oapp)
|
|
require.NoError(t, err)
|
|
|
|
resp, err := client.DeleteOAuthApp(context.Background(), rapp.Id)
|
|
require.Error(t, err)
|
|
CheckForbiddenStatus(t, resp)
|
|
|
|
_, err = client.DeleteOAuthApp(context.Background(), rapp2.Id)
|
|
require.NoError(t, err)
|
|
|
|
// Revoke permission from regular users.
|
|
th.RemovePermissionFromRole(t, model.PermissionManageOAuth.Id, model.SystemUserRoleId)
|
|
|
|
resp, err = client.DeleteOAuthApp(context.Background(), rapp.Id)
|
|
require.Error(t, err)
|
|
CheckForbiddenStatus(t, resp)
|
|
|
|
_, err = client.Logout(context.Background())
|
|
require.NoError(t, err)
|
|
resp, err = client.DeleteOAuthApp(context.Background(), rapp.Id)
|
|
require.Error(t, err)
|
|
CheckUnauthorizedStatus(t, resp)
|
|
|
|
resp, err = adminClient.DeleteOAuthApp(context.Background(), "junk")
|
|
require.Error(t, err)
|
|
CheckBadRequestStatus(t, resp)
|
|
|
|
resp, err = adminClient.DeleteOAuthApp(context.Background(), model.NewId())
|
|
require.Error(t, err)
|
|
CheckNotFoundStatus(t, resp)
|
|
|
|
th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableOAuthServiceProvider = false })
|
|
resp, err = adminClient.DeleteOAuthApp(context.Background(), rapp.Id)
|
|
require.Error(t, err)
|
|
CheckNotImplementedStatus(t, resp)
|
|
}
|
|
|
|
func TestRegenerateOAuthAppSecret(t *testing.T) {
|
|
mainHelper.Parallel(t)
|
|
th := Setup(t)
|
|
client := th.Client
|
|
adminClient := th.SystemAdminClient
|
|
|
|
defaultRolePermissions := th.SaveDefaultRolePermissions(t)
|
|
enableOAuthServiceProvider := th.App.Config().ServiceSettings.EnableOAuthServiceProvider
|
|
defer func() {
|
|
th.RestoreDefaultRolePermissions(t, defaultRolePermissions)
|
|
th.App.UpdateConfig(func(cfg *model.Config) { cfg.ServiceSettings.EnableOAuthServiceProvider = enableOAuthServiceProvider })
|
|
}()
|
|
|
|
// Grant permission to regular users.
|
|
th.AddPermissionToRole(t, model.PermissionManageOAuth.Id, model.SystemUserRoleId)
|
|
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, _, err := adminClient.CreateOAuthApp(context.Background(), oapp)
|
|
require.NoError(t, err)
|
|
|
|
oapp.Name = GenerateTestAppName()
|
|
rapp2, _, err := client.CreateOAuthApp(context.Background(), oapp)
|
|
require.NoError(t, err)
|
|
|
|
rrapp, _, err := adminClient.RegenerateOAuthAppSecret(context.Background(), rapp.Id)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, rrapp.Id, rapp.Id, "wrong app")
|
|
assert.NotEqual(t, rapp.ClientSecret, rrapp.ClientSecret, "secret didn't change")
|
|
|
|
_, _, err = adminClient.RegenerateOAuthAppSecret(context.Background(), rapp2.Id)
|
|
require.NoError(t, err)
|
|
|
|
rapp, _, err = adminClient.CreateOAuthApp(context.Background(), oapp)
|
|
require.NoError(t, err)
|
|
|
|
oapp.Name = GenerateTestAppName()
|
|
rapp2, _, err = client.CreateOAuthApp(context.Background(), oapp)
|
|
require.NoError(t, err)
|
|
|
|
_, resp, err := client.RegenerateOAuthAppSecret(context.Background(), rapp.Id)
|
|
require.Error(t, err)
|
|
CheckForbiddenStatus(t, resp)
|
|
|
|
_, _, err = client.RegenerateOAuthAppSecret(context.Background(), rapp2.Id)
|
|
require.NoError(t, err)
|
|
|
|
// Revoke permission from regular users.
|
|
th.RemovePermissionFromRole(t, model.PermissionManageOAuth.Id, model.SystemUserRoleId)
|
|
|
|
_, resp, err = client.RegenerateOAuthAppSecret(context.Background(), rapp.Id)
|
|
require.Error(t, err)
|
|
CheckForbiddenStatus(t, resp)
|
|
|
|
_, err = client.Logout(context.Background())
|
|
require.NoError(t, err)
|
|
_, resp, err = client.RegenerateOAuthAppSecret(context.Background(), rapp.Id)
|
|
require.Error(t, err)
|
|
CheckUnauthorizedStatus(t, resp)
|
|
|
|
_, resp, err = adminClient.RegenerateOAuthAppSecret(context.Background(), "junk")
|
|
require.Error(t, err)
|
|
CheckBadRequestStatus(t, resp)
|
|
|
|
_, resp, err = adminClient.RegenerateOAuthAppSecret(context.Background(), model.NewId())
|
|
require.Error(t, err)
|
|
CheckNotFoundStatus(t, resp)
|
|
|
|
th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableOAuthServiceProvider = false })
|
|
_, resp, err = adminClient.RegenerateOAuthAppSecret(context.Background(), rapp.Id)
|
|
require.Error(t, err)
|
|
CheckNotImplementedStatus(t, resp)
|
|
}
|
|
|
|
func TestGetAuthorizedOAuthAppsForUser(t *testing.T) {
|
|
mainHelper.Parallel(t)
|
|
th := Setup(t).InitBasic(t)
|
|
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, _, err := adminClient.CreateOAuthApp(context.Background(), oapp)
|
|
require.NoError(t, err)
|
|
|
|
authRequest := &model.AuthorizeRequest{
|
|
ResponseType: model.AuthCodeResponseType,
|
|
ClientId: rapp.Id,
|
|
RedirectURI: rapp.CallbackUrls[0],
|
|
Scope: "",
|
|
State: "123",
|
|
}
|
|
|
|
_, _, err = client.AuthorizeOAuthApp(context.Background(), authRequest)
|
|
require.NoError(t, err)
|
|
|
|
apps, _, err := client.GetAuthorizedOAuthAppsForUser(context.Background(), th.BasicUser.Id, 0, 1000)
|
|
require.NoError(t, err)
|
|
|
|
found := false
|
|
for _, a := range apps {
|
|
if a.Id == rapp.Id {
|
|
found = true
|
|
}
|
|
assert.Equal(t, "", a.ClientSecret, "not sanitized")
|
|
}
|
|
require.True(t, found, "missing app")
|
|
|
|
_, resp, err := client.GetAuthorizedOAuthAppsForUser(context.Background(), th.BasicUser2.Id, 0, 1000)
|
|
require.Error(t, err)
|
|
CheckForbiddenStatus(t, resp)
|
|
|
|
_, resp, err = client.GetAuthorizedOAuthAppsForUser(context.Background(), "junk", 0, 1000)
|
|
require.Error(t, err)
|
|
CheckBadRequestStatus(t, resp)
|
|
|
|
_, err = client.Logout(context.Background())
|
|
require.NoError(t, err)
|
|
_, resp, err = client.GetAuthorizedOAuthAppsForUser(context.Background(), th.BasicUser.Id, 0, 1000)
|
|
require.Error(t, err)
|
|
CheckUnauthorizedStatus(t, resp)
|
|
|
|
_, _, err = adminClient.GetAuthorizedOAuthAppsForUser(context.Background(), th.BasicUser.Id, 0, 1000)
|
|
require.NoError(t, err)
|
|
}
|
|
|
|
func TestNilAuthorizeOAuthApp(t *testing.T) {
|
|
mainHelper.Parallel(t)
|
|
th := Setup(t).InitBasic(t)
|
|
client := th.Client
|
|
|
|
_, _, err := client.AuthorizeOAuthApp(context.Background(), nil)
|
|
require.Error(t, err)
|
|
CheckErrorID(t, err, "api.context.invalid_body_param.app_error")
|
|
}
|
|
|
|
func TestRegisterOAuthClient(t *testing.T) {
|
|
mainHelper.Parallel(t)
|
|
th := Setup(t).InitBasic(t)
|
|
|
|
// Configure server for DCR
|
|
th.App.UpdateConfig(func(cfg *model.Config) {
|
|
cfg.ServiceSettings.EnableOAuthServiceProvider = model.NewPointer(true)
|
|
cfg.ServiceSettings.EnableDynamicClientRegistration = model.NewPointer(true)
|
|
})
|
|
|
|
t.Run("Valid DCR request", func(t *testing.T) {
|
|
request := &model.ClientRegistrationRequest{
|
|
RedirectURIs: []string{"https://example.com/callback"},
|
|
ClientName: model.NewPointer("Test Client"),
|
|
}
|
|
|
|
response, resp, err := th.SystemAdminClient.RegisterOAuthClient(context.Background(), request)
|
|
|
|
require.NoError(t, err)
|
|
require.NotNil(t, response)
|
|
CheckCreatedStatus(t, resp)
|
|
assert.Equal(t, request.RedirectURIs, response.RedirectURIs)
|
|
assert.NotEmpty(t, response.ClientID)
|
|
assert.NotNil(t, response.ClientSecret)
|
|
assert.NotEmpty(t, *response.ClientSecret)
|
|
})
|
|
|
|
t.Run("Missing redirect URIs", func(t *testing.T) {
|
|
request := &model.ClientRegistrationRequest{
|
|
ClientName: model.NewPointer("Test Client"),
|
|
}
|
|
|
|
_, resp, err := th.SystemAdminClient.RegisterOAuthClient(context.Background(), request)
|
|
|
|
require.Error(t, err)
|
|
CheckBadRequestStatus(t, resp)
|
|
})
|
|
|
|
t.Run("Works without authentication", func(t *testing.T) {
|
|
// Sleep to avoid rate limiting issues
|
|
time.Sleep(time.Second)
|
|
|
|
// Log out to demonstrate DCR works without session
|
|
_, err := th.Client.Logout(context.Background())
|
|
require.NoError(t, err)
|
|
|
|
request := &model.ClientRegistrationRequest{
|
|
RedirectURIs: []string{"https://example.com/callback"},
|
|
ClientName: model.NewPointer("Test Client No Auth"),
|
|
}
|
|
|
|
response, resp, err := th.Client.RegisterOAuthClient(context.Background(), request)
|
|
|
|
require.NoError(t, err)
|
|
require.NotNil(t, response)
|
|
CheckCreatedStatus(t, resp)
|
|
assert.Equal(t, request.RedirectURIs, response.RedirectURIs)
|
|
assert.NotEmpty(t, response.ClientID)
|
|
assert.NotNil(t, response.ClientSecret)
|
|
assert.NotEmpty(t, *response.ClientSecret)
|
|
})
|
|
|
|
t.Run("Works with client_uri", func(t *testing.T) {
|
|
// Sleep to avoid rate limiting issues
|
|
time.Sleep(time.Second)
|
|
|
|
request := &model.ClientRegistrationRequest{
|
|
RedirectURIs: []string{"https://example.com/callback"},
|
|
ClientName: model.NewPointer("Test Client with URI"),
|
|
ClientURI: model.NewPointer("https://example.com"),
|
|
}
|
|
|
|
response, resp, err := th.Client.RegisterOAuthClient(context.Background(), request)
|
|
|
|
require.NoError(t, err)
|
|
require.NotNil(t, response)
|
|
CheckCreatedStatus(t, resp)
|
|
assert.Equal(t, request.RedirectURIs, response.RedirectURIs)
|
|
assert.NotEmpty(t, response.ClientID)
|
|
assert.NotNil(t, response.ClientSecret)
|
|
assert.NotEmpty(t, *response.ClientSecret)
|
|
assert.Equal(t, request.ClientName, response.ClientName)
|
|
assert.Equal(t, request.ClientURI, response.ClientURI)
|
|
})
|
|
}
|
|
|
|
func TestRegisterOAuthClient_DisabledFeatures(t *testing.T) {
|
|
mainHelper.Parallel(t)
|
|
th := Setup(t)
|
|
adminClient := th.SystemAdminClient
|
|
|
|
defaultRolePermissions := th.SaveDefaultRolePermissions(t)
|
|
enableOAuthServiceProvider := th.App.Config().ServiceSettings.EnableOAuthServiceProvider
|
|
enableDCR := th.App.Config().ServiceSettings.EnableDynamicClientRegistration
|
|
defer func() {
|
|
th.RestoreDefaultRolePermissions(t, defaultRolePermissions)
|
|
th.App.UpdateConfig(func(cfg *model.Config) {
|
|
cfg.ServiceSettings.EnableOAuthServiceProvider = enableOAuthServiceProvider
|
|
cfg.ServiceSettings.EnableDynamicClientRegistration = enableDCR
|
|
})
|
|
}()
|
|
|
|
th.AddPermissionToRole(t, model.PermissionManageOAuth.Id, model.SystemUserRoleId)
|
|
|
|
request := &model.ClientRegistrationRequest{
|
|
RedirectURIs: []string{"https://example.com/callback"},
|
|
ClientName: model.NewPointer("Test Client"),
|
|
}
|
|
|
|
// Test with OAuth disabled
|
|
th.App.UpdateConfig(func(cfg *model.Config) {
|
|
cfg.ServiceSettings.EnableOAuthServiceProvider = model.NewPointer(false)
|
|
cfg.ServiceSettings.EnableDynamicClientRegistration = model.NewPointer(true)
|
|
})
|
|
|
|
_, resp, err := adminClient.RegisterOAuthClient(context.Background(), request)
|
|
require.Error(t, err)
|
|
CheckBadRequestStatus(t, resp)
|
|
|
|
// Sleep to avoid rate limiting issues
|
|
time.Sleep(time.Second)
|
|
|
|
// Test with DCR disabled
|
|
th.App.UpdateConfig(func(cfg *model.Config) {
|
|
cfg.ServiceSettings.EnableOAuthServiceProvider = model.NewPointer(true)
|
|
cfg.ServiceSettings.EnableDynamicClientRegistration = model.NewPointer(false)
|
|
})
|
|
|
|
_, resp, err = adminClient.RegisterOAuthClient(context.Background(), request)
|
|
require.Error(t, err)
|
|
CheckBadRequestStatus(t, resp)
|
|
|
|
// Sleep to avoid rate limiting issues
|
|
time.Sleep(time.Second)
|
|
|
|
// Test with nil config values (should be disabled by default)
|
|
th.App.UpdateConfig(func(cfg *model.Config) {
|
|
cfg.ServiceSettings.EnableOAuthServiceProvider = nil
|
|
cfg.ServiceSettings.EnableDynamicClientRegistration = nil
|
|
})
|
|
|
|
_, resp, err = adminClient.RegisterOAuthClient(context.Background(), request)
|
|
require.Error(t, err)
|
|
CheckBadRequestStatus(t, resp)
|
|
}
|
|
|
|
func TestRegisterOAuthClient_RedirectURIAllowlist(t *testing.T) {
|
|
mainHelper.Parallel(t)
|
|
th := Setup(t)
|
|
client := th.Client
|
|
|
|
th.App.UpdateConfig(func(cfg *model.Config) {
|
|
*cfg.ServiceSettings.EnableOAuthServiceProvider = true
|
|
cfg.ServiceSettings.EnableDynamicClientRegistration = model.NewPointer(true)
|
|
})
|
|
|
|
t.Run("allowlist empty registration succeeds", func(t *testing.T) {
|
|
cfg := th.App.Config()
|
|
cfg.ServiceSettings.DCRRedirectURIAllowlist = []string{}
|
|
th.App.UpdateConfig(func(c *model.Config) { *c = *cfg })
|
|
|
|
request := &model.ClientRegistrationRequest{
|
|
RedirectURIs: []string{"https://example.com/callback"},
|
|
ClientName: model.NewPointer("Test Client"),
|
|
}
|
|
response, resp, err := client.RegisterOAuthClient(context.Background(), request)
|
|
require.NoError(t, err)
|
|
CheckCreatedStatus(t, resp)
|
|
require.NotNil(t, response)
|
|
assert.NotEmpty(t, response.ClientID)
|
|
})
|
|
|
|
t.Run("wildcard allowed URI succeeds", func(t *testing.T) {
|
|
th.App.UpdateConfig(func(cfg *model.Config) {
|
|
cfg.ServiceSettings.DCRRedirectURIAllowlist = []string{"https://example.com/*", "https://*.test.com/**"}
|
|
})
|
|
|
|
request := &model.ClientRegistrationRequest{
|
|
RedirectURIs: []string{"https://example.com/callback"},
|
|
ClientName: model.NewPointer("Test Client"),
|
|
}
|
|
response, resp, err := client.RegisterOAuthClient(context.Background(), request)
|
|
require.NoError(t, err)
|
|
CheckCreatedStatus(t, resp)
|
|
require.NotNil(t, response)
|
|
|
|
time.Sleep(time.Second) // avoid rate limit
|
|
request2 := &model.ClientRegistrationRequest{
|
|
RedirectURIs: []string{"https://app.test.com/deep/path/cb"},
|
|
ClientName: model.NewPointer("Test Client 2"),
|
|
}
|
|
response2, resp2, err2 := client.RegisterOAuthClient(context.Background(), request2)
|
|
require.NoError(t, err2)
|
|
CheckCreatedStatus(t, resp2)
|
|
require.NotNil(t, response2)
|
|
})
|
|
|
|
t.Run("disallowed URI returns 400 invalid_redirect_uri", func(t *testing.T) {
|
|
th.App.UpdateConfig(func(cfg *model.Config) {
|
|
cfg.ServiceSettings.DCRRedirectURIAllowlist = []string{"https://allowed.com/**"}
|
|
})
|
|
|
|
body, _ := json.Marshal(&model.ClientRegistrationRequest{
|
|
RedirectURIs: []string{"https://disallowed.com/callback"},
|
|
ClientName: model.NewPointer("Test Client"),
|
|
})
|
|
req, err := http.NewRequest(http.MethodPost, client.APIURL+"/oauth/apps/register", bytes.NewReader(body))
|
|
require.NoError(t, err)
|
|
req.Header.Set("Content-Type", "application/json")
|
|
if client.AuthToken != "" {
|
|
req.Header.Set(model.HeaderAuth, model.HeaderBearer+" "+client.AuthToken)
|
|
}
|
|
httpResp, err := client.HTTPClient.Do(req)
|
|
require.NoError(t, err)
|
|
defer httpResp.Body.Close()
|
|
require.Equal(t, http.StatusBadRequest, httpResp.StatusCode)
|
|
var dcrErr model.DCRError
|
|
jsonErr := json.NewDecoder(httpResp.Body).Decode(&dcrErr)
|
|
require.NoError(t, jsonErr)
|
|
assert.Equal(t, model.DCRErrorInvalidRedirectURI, dcrErr.Error)
|
|
assert.NotEmpty(t, dcrErr.ErrorDescription)
|
|
})
|
|
|
|
t.Run("multi redirect partial mismatch rejects request", func(t *testing.T) {
|
|
th.App.UpdateConfig(func(cfg *model.Config) {
|
|
cfg.ServiceSettings.DCRRedirectURIAllowlist = []string{"https://allowed.com/**"}
|
|
})
|
|
|
|
time.Sleep(time.Second)
|
|
body, _ := json.Marshal(&model.ClientRegistrationRequest{
|
|
RedirectURIs: []string{"https://allowed.com/cb1", "https://disallowed.com/cb2"},
|
|
ClientName: model.NewPointer("Test Client"),
|
|
})
|
|
req, err := http.NewRequest(http.MethodPost, client.APIURL+"/oauth/apps/register", bytes.NewReader(body))
|
|
require.NoError(t, err)
|
|
req.Header.Set("Content-Type", "application/json")
|
|
if client.AuthToken != "" {
|
|
req.Header.Set(model.HeaderAuth, model.HeaderBearer+" "+client.AuthToken)
|
|
}
|
|
httpResp, err := client.HTTPClient.Do(req)
|
|
require.NoError(t, err)
|
|
defer httpResp.Body.Close()
|
|
require.Equal(t, http.StatusBadRequest, httpResp.StatusCode)
|
|
var dcrErr model.DCRError
|
|
jsonErr := json.NewDecoder(httpResp.Body).Decode(&dcrErr)
|
|
require.NoError(t, jsonErr)
|
|
assert.Equal(t, model.DCRErrorInvalidRedirectURI, dcrErr.Error)
|
|
assert.NotEmpty(t, dcrErr.ErrorDescription)
|
|
})
|
|
}
|
|
|
|
func TestRegisterOAuthClient_PublicClient_Success(t *testing.T) {
|
|
// Test successful public client DCR registration
|
|
mainHelper.Parallel(t)
|
|
th := Setup(t)
|
|
client := th.Client
|
|
|
|
th.App.UpdateConfig(func(cfg *model.Config) {
|
|
*cfg.ServiceSettings.EnableOAuthServiceProvider = true
|
|
cfg.ServiceSettings.EnableDynamicClientRegistration = model.NewPointer(true)
|
|
})
|
|
|
|
// DCR request for public client
|
|
request := &model.ClientRegistrationRequest{
|
|
RedirectURIs: []string{"https://example.com/callback"},
|
|
TokenEndpointAuthMethod: model.NewPointer(model.ClientAuthMethodNone),
|
|
ClientName: model.NewPointer("Test Public Client"),
|
|
ClientURI: model.NewPointer("https://example.com"),
|
|
}
|
|
|
|
// Register public client
|
|
response, resp, err := client.RegisterOAuthClient(context.Background(), request)
|
|
require.NoError(t, err)
|
|
CheckCreatedStatus(t, resp)
|
|
require.NotNil(t, response)
|
|
|
|
// Verify response properties for public client
|
|
assert.NotEmpty(t, response.ClientID)
|
|
assert.Nil(t, response.ClientSecret) // No client secret for public clients
|
|
assert.Equal(t, request.RedirectURIs, response.RedirectURIs)
|
|
assert.Equal(t, model.ClientAuthMethodNone, response.TokenEndpointAuthMethod)
|
|
assert.Equal(t, *request.ClientName, *response.ClientName)
|
|
assert.Equal(t, *request.ClientURI, *response.ClientURI)
|
|
assert.Equal(t, "user", response.Scope)
|
|
}
|
|
|
|
func TestRegisterOAuthClientAudit(t *testing.T) {
|
|
logFile, err := os.CreateTemp("", "dcr_audit.log")
|
|
require.NoError(t, err)
|
|
defer os.Remove(logFile.Name())
|
|
|
|
os.Setenv("MM_EXPERIMENTALAUDITSETTINGS_FILEENABLED", "true")
|
|
os.Setenv("MM_EXPERIMENTALAUDITSETTINGS_FILENAME", logFile.Name())
|
|
defer os.Unsetenv("MM_EXPERIMENTALAUDITSETTINGS_FILEENABLED")
|
|
defer os.Unsetenv("MM_EXPERIMENTALAUDITSETTINGS_FILENAME")
|
|
|
|
options := []app.Option{app.WithLicense(model.NewTestLicense("advanced_logging"))}
|
|
th := SetupWithServerOptions(t, options)
|
|
|
|
th.App.UpdateConfig(func(cfg *model.Config) {
|
|
*cfg.ServiceSettings.EnableOAuthServiceProvider = true
|
|
cfg.ServiceSettings.EnableDynamicClientRegistration = model.NewPointer(true)
|
|
})
|
|
|
|
t.Run("Successful DCR registration is audited", func(t *testing.T) {
|
|
clientName := "Test Audit Client"
|
|
request := &model.ClientRegistrationRequest{
|
|
RedirectURIs: []string{"https://example.com/callback"},
|
|
ClientName: model.NewPointer(clientName),
|
|
}
|
|
|
|
response, resp, err := th.Client.RegisterOAuthClient(context.Background(), request)
|
|
require.NoError(t, err)
|
|
CheckCreatedStatus(t, resp)
|
|
require.NotNil(t, response)
|
|
|
|
// Flush audit logs
|
|
err = th.Server.Audit.Flush()
|
|
require.NoError(t, err)
|
|
require.NoError(t, logFile.Sync())
|
|
|
|
// Read and verify audit log
|
|
data, err := io.ReadAll(logFile)
|
|
require.NoError(t, err)
|
|
require.NotEmpty(t, data)
|
|
|
|
entry := FindAuditEntry(string(data), "registerOAuthClient", "")
|
|
require.NotNil(t, entry, "should find a registerOAuthClient audit entry")
|
|
assert.Equal(t, "success", entry.Status)
|
|
// Verify client details are in the raw entry
|
|
assert.Contains(t, fmt.Sprintf("%v", entry.Raw), clientName)
|
|
assert.Contains(t, fmt.Sprintf("%v", entry.Raw), response.ClientID)
|
|
})
|
|
|
|
t.Run("Failed DCR registration is audited", func(t *testing.T) {
|
|
// Truncate log file for this test
|
|
require.NoError(t, logFile.Truncate(0))
|
|
_, err := logFile.Seek(0, 0)
|
|
require.NoError(t, err)
|
|
|
|
// Invalid request (missing redirect URIs)
|
|
request := &model.ClientRegistrationRequest{
|
|
ClientName: model.NewPointer("Invalid Client"),
|
|
}
|
|
|
|
_, resp, err := th.Client.RegisterOAuthClient(context.Background(), request)
|
|
require.Error(t, err)
|
|
CheckBadRequestStatus(t, resp)
|
|
|
|
// Flush audit logs
|
|
err = th.Server.Audit.Flush()
|
|
require.NoError(t, err)
|
|
require.NoError(t, logFile.Sync())
|
|
|
|
// Read and verify audit log
|
|
data, err := io.ReadAll(logFile)
|
|
require.NoError(t, err)
|
|
require.NotEmpty(t, data)
|
|
|
|
entry := FindAuditEntry(string(data), "registerOAuthClient", "")
|
|
require.NotNil(t, entry, "should find a registerOAuthClient audit entry")
|
|
assert.Equal(t, "fail", entry.Status)
|
|
})
|
|
}
|