Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -1289,6 +1289,13 @@ createdSSOSettings, err := descopeClient.Management.SSO().NewSettings(context.Ba
// To delete SSO settings, call the following method
// You can pass ssoID in case using multi SSO and you want to delete specific SSO configuration
err := descopeClient.Management.SSO().DeleteSettings(context.Background(), "tenant-id")

// To disable an SSO configuration without deleting it, set its auth type to none. Its settings,
// mappings and domains are kept, so re-enabling it needs no payload.
// You can pass ssoID in case using multi SSO and you want to disable a specific SSO configuration
err := descopeClient.Management.SSO().ConfigureAuthType(context.Background(), "tenant-id", descope.SSOAuthTypeNone, ssoID)
// Enable it again on the protocol it is configured for
err = descopeClient.Management.SSO().ConfigureAuthType(context.Background(), "tenant-id", descope.SSOAuthTypeSaml, ssoID)
```

Note: Certificates should have a similar structure to:
Expand Down
6 changes: 6 additions & 0 deletions descope/api/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,7 @@ var (
ssoLoadSettings: "mgmt/sso/settings", // v2 only
ssoLoadAllSettings: "mgmt/sso/settings/all", // v2 only
ssoSettingsNew: "mgmt/sso/settings/new",
ssoAuthType: "mgmt/sso/settings/authtype",
ssoSAMLSettings: "mgmt/sso/saml",
ssoSAMLSettingsByMetadata: "mgmt/sso/saml/metadata",
ssoRedirectURL: "mgmt/sso/redirect",
Expand Down Expand Up @@ -531,6 +532,7 @@ type mgmtEndpoints struct {
ssoLoadSettings string
ssoLoadAllSettings string
ssoSettingsNew string
ssoAuthType string
ssoSAMLSettings string
ssoSAMLSettingsByMetadata string
ssoRedirectURL string
Expand Down Expand Up @@ -1300,6 +1302,10 @@ func (e *endpoints) ManagementNewSSOSettings() string {
return path.Join(e.version, e.mgmt.ssoSettingsNew)
}

func (e *endpoints) ManagementSSOAuthType() string {
return path.Join(e.version, e.mgmt.ssoAuthType)
}

func (e *endpoints) ManagementSSOSAMLSettings() string {
return path.Join(e.version, e.mgmt.ssoSAMLSettings)
}
Expand Down
21 changes: 21 additions & 0 deletions descope/internal/mgmt/sso.go
Original file line number Diff line number Diff line change
Expand Up @@ -263,6 +263,27 @@ func (s *sso) DeleteSettings(ctx context.Context, tenantID string, ssoID string)
return nil
}

func (s *sso) ConfigureAuthType(ctx context.Context, tenantID string, authType descope.SSOAuthType, ssoID string) error {
if tenantID == "" {
return utils.NewInvalidArgumentError("tenantID")
}

if authType == "" {
return utils.NewInvalidArgumentError("authType")
}

req := map[string]any{
"tenantId": tenantID,
"authType": authType,
}
if len(ssoID) > 0 {
req["ssoId"] = ssoID
}

_, err := s.client.DoPostRequest(ctx, api.Routes.ManagementSSOAuthType(), req, nil, "")
return err
}

// * Deprecated (use ConfigureSAMLSettings() instead) *//
func (s *sso) ConfigureSettings(ctx context.Context, tenantID, idpURL, idpCert, entityID, redirectURL string, domains []string) error {
if tenantID == "" {
Expand Down
45 changes: 45 additions & 0 deletions descope/internal/mgmt/sso_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,51 @@ func TestDeleteSSOSettingsWithSSOIDSuccess(t *testing.T) {
assert.NoError(t, err)
}

func TestSSOConfigureAuthTypeDisableWithSSOIDSuccess(t *testing.T) {
mgmt := newTestMgmt(nil, helpers.DoOk(func(r *http.Request) {
require.Equal(t, r.Header.Get("Authorization"), "Bearer a:key")
req := map[string]any{}
require.NoError(t, helpers.ReadBody(r, &req))
require.Equal(t, "abc", req["tenantId"])
require.Equal(t, "none", req["authType"])
require.Equal(t, "somessoid", req["ssoId"])
}))
err := mgmt.SSO().ConfigureAuthType(context.Background(), "abc", descope.SSOAuthTypeNone, "somessoid")
require.NoError(t, err)
}

func TestSSOConfigureAuthTypeDefaultConfigSuccess(t *testing.T) {
mgmt := newTestMgmt(nil, helpers.DoOk(func(r *http.Request) {
req := map[string]any{}
require.NoError(t, helpers.ReadBody(r, &req))
require.Equal(t, "abc", req["tenantId"])
require.Equal(t, "saml", req["authType"])
require.Empty(t, req["ssoId"])
}))
err := mgmt.SSO().ConfigureAuthType(context.Background(), "abc", descope.SSOAuthTypeSaml, "")
require.NoError(t, err)
}

func TestSSOConfigureAuthTypeMissingTenantID(t *testing.T) {
called := false
mgmt := newTestMgmt(nil, helpers.DoOk(func(_ *http.Request) {
called = true
}))
err := mgmt.SSO().ConfigureAuthType(context.Background(), "", descope.SSOAuthTypeNone, "")
require.Error(t, err)
require.False(t, called)
}

func TestSSOConfigureAuthTypeMissingAuthType(t *testing.T) {
called := false
mgmt := newTestMgmt(nil, helpers.DoOk(func(_ *http.Request) {
called = true
}))
err := mgmt.SSO().ConfigureAuthType(context.Background(), "abc", "", "")
require.Error(t, err)
require.False(t, called)
}

func TestDeleteSSOSettingsError(t *testing.T) {
called := false
mgmt := newTestMgmt(nil, helpers.DoOkWithBody(func(_ *http.Request) {
Expand Down
11 changes: 11 additions & 0 deletions descope/sdk/mgmt.go
Original file line number Diff line number Diff line change
Expand Up @@ -724,6 +724,17 @@ type SSO interface {
// ssoID (optional) - you can pass ssoID in case using multi SSO and you want to delete specific SSO configuration
DeleteSettings(ctx context.Context, tenantID string, ssoID string) error

// Set the authentication type of a single SSO configuration, leaving its stored SAML/OIDC
// settings, mappings and domains untouched.
//
// tenantID and authType are required.
//
// authType - descope.SSOAuthTypeNone disables the configuration without deleting it,
// descope.SSOAuthTypeSaml / descope.SSOAuthTypeOidc enable it on that protocol with its stored
// settings, so re-enabling needs no payload.
// ssoID (optional) - pass ssoID when using multi SSO to change a specific SSO configuration.
ConfigureAuthType(ctx context.Context, tenantID string, authType descope.SSOAuthType, ssoID string) error

// *** Deprecated ***

//* Deprecated (use LoadSettings() instead) *//
Expand Down
10 changes: 10 additions & 0 deletions descope/tests/mocks/mgmt/managementmock.go
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,9 @@ type MockSSO struct {
DeleteSettingsAssert func(tenantID string, ssoID string)
DeleteSettingsError error

ConfigureAuthTypeAssert func(tenantID string, authType descope.SSOAuthType, ssoID string)
ConfigureAuthTypeError error

GetSettingsAssert func(tenantID string)
GetSettingsResponse *descope.SSOSettingsResponse
GetSettingsError error
Expand Down Expand Up @@ -324,6 +327,13 @@ func (m *MockSSO) ConfigureOIDCSettings(_ context.Context, tenantID string, sett
return m.ConfigureOIDCSettingsError
}

func (m *MockSSO) ConfigureAuthType(_ context.Context, tenantID string, authType descope.SSOAuthType, ssoID string) error {
if m.ConfigureAuthTypeAssert != nil {
m.ConfigureAuthTypeAssert(tenantID, authType, ssoID)
}
return m.ConfigureAuthTypeError
}

func (m *MockSSO) ConfigureXAASettings(_ context.Context, tenantID string, settings *descope.SSOXAASettings, ssoID string) error {
if m.ConfigureXAASettingsAssert != nil {
m.ConfigureXAASettingsAssert(tenantID, settings, ssoID)
Expand Down
9 changes: 9 additions & 0 deletions descope/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -773,6 +773,15 @@ const RoleInheritanceDefault RoleInheritance = ""
const RoleInheritanceNone RoleInheritance = "none"
const RoleInheritanceUserOnly RoleInheritance = "userOnly"

// SSOAuthType is the authentication type of an SSO configuration. None means the configuration is
// disabled: it keeps its stored settings, mappings and domains, and serves no logins until it is
// set back to Saml or Oidc.
type SSOAuthType string

const SSOAuthTypeNone SSOAuthType = "none"
const SSOAuthTypeSaml SSOAuthType = "saml"
const SSOAuthTypeOidc SSOAuthType = "oidc"

type Tenant struct {
ID string `json:"id"`
Name string `json:"name"`
Expand Down
Loading