Skip to content
31 changes: 31 additions & 0 deletions descope/api/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,11 @@ var (
outboundApplicationUploadTenantToken: "mgmt/outbound/app/tenant/oauthtoken/upload",
outboundApplicationBatchUploadUserTokens: "mgmt/outbound/app/user/oauthtoken/batch/upload",
outboundApplicationBatchUploadTenantTokens: "mgmt/outbound/app/tenant/oauthtoken/batch/upload",
outboundSCIMCreate: "mgmt/outbound/scim/create",
outboundSCIMUpdate: "mgmt/outbound/scim/update",
outboundSCIMDelete: "mgmt/outbound/scim/delete",
outboundSCIMLoad: "mgmt/outbound/scim",
outboundSCIMSetEnabled: "mgmt/outbound/scim/enabled/set",
thirdPartyApplicationCreate: "mgmt/thirdparty/app/create",
thirdPartyApplicationUpdate: "mgmt/thirdparty/app/update",
thirdPartyApplicationPatch: "mgmt/thirdparty/app/patch",
Expand Down Expand Up @@ -623,6 +628,12 @@ type mgmtEndpoints struct {
outboundApplicationBatchUploadUserTokens string
outboundApplicationBatchUploadTenantTokens string

outboundSCIMCreate string
outboundSCIMUpdate string
outboundSCIMDelete string
outboundSCIMLoad string
outboundSCIMSetEnabled string

thirdPartyApplicationCreate string
thirdPartyApplicationUpdate string
thirdPartyApplicationPatch string
Expand Down Expand Up @@ -1668,6 +1679,26 @@ func (e *endpoints) ManagementOutboundApplicationBatchUploadTenantTokens() strin
return path.Join(e.version, e.mgmt.outboundApplicationBatchUploadTenantTokens)
}

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

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

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

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

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

func (e *endpoints) ManagementThirdPartyApplicationCreate() string {
return path.Join(e.version, e.mgmt.thirdPartyApplicationCreate)
}
Expand Down
7 changes: 7 additions & 0 deletions descope/internal/mgmt/mgmt.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ type managementService struct {
fga sdk.FGA
thirdPartyApplication sdk.ThirdPartyApplication
outboundApplication sdk.OutboundApplication
outboundSCIM sdk.OutboundSCIM
managementKey sdk.ManagementKey
descoper sdk.Descoper
list sdk.List
Expand All @@ -54,6 +55,7 @@ func NewManagement(conf ManagementParams, provider *auth.Provider, c *api.Client
service.ssoApplication = &ssoApplication{managementBase: base}
service.thirdPartyApplication = &thirdPartyApplication{managementBase: base}
service.outboundApplication = &outboundApplication{managementBase: base}
service.outboundSCIM = &outboundSCIM{managementBase: base}
service.user = &user{managementBase: base}
service.accessKey = &accessKey{managementBase: base}
service.sso = &sso{managementBase: base}
Expand Down Expand Up @@ -167,6 +169,11 @@ func (mgmt *managementService) OutboundApplication() sdk.OutboundApplication {
return mgmt.outboundApplication
}

func (mgmt *managementService) OutboundSCIM() sdk.OutboundSCIM {
mgmt.ensureManagementKey()
return mgmt.outboundSCIM
}

func (mgmt *managementService) ManagementKey() sdk.ManagementKey {
mgmt.ensureManagementKey()
return mgmt.managementKey
Expand Down
96 changes: 96 additions & 0 deletions descope/internal/mgmt/outbound_scim.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
package mgmt

import (
"context"

"github.com/descope/go-sdk/descope"
"github.com/descope/go-sdk/descope/api"
"github.com/descope/go-sdk/descope/internal/utils"
"github.com/descope/go-sdk/descope/sdk"
)

type outboundSCIM struct {
managementBase
}

var _ sdk.OutboundSCIM = &outboundSCIM{}

func (s *outboundSCIM) CreateConfiguration(ctx context.Context, request *descope.CreateOutboundSCIMConfigurationRequest) (*descope.OutboundSCIMConfiguration, error) {
if request == nil {
return nil, utils.NewInvalidArgumentError("request")
}
if request.AppID == "" {
return nil, utils.NewInvalidArgumentError("request.AppID")
}

// Descope grpc-gateway rejects unknown JSON request fields — build the body from an explicit
// map so only the proto-declared fields are sent.
body := map[string]any{
"appId": request.AppID,
"configuration": request.Configuration,
}
httpRes, err := s.client.DoPostRequest(ctx, api.Routes.ManagementOutboundSCIMCreate(), body, nil, "")
if err != nil {
return nil, err
}
return s.unmarshalConfigurationResponse(httpRes)
}

func (s *outboundSCIM) UpdateConfiguration(ctx context.Context, request *descope.UpdateOutboundSCIMConfigurationRequest) (*descope.OutboundSCIMConfiguration, error) {
if request == nil {
return nil, utils.NewInvalidArgumentError("request")
}
if request.AppID == "" {
return nil, utils.NewInvalidArgumentError("request.AppID")
}

// Proto int64 Version must serialize as a JSON string — utils.Marshal honors the ",string"
// tag on the request struct, so send the struct directly rather than building a map.
httpRes, err := s.client.DoPostRequest(ctx, api.Routes.ManagementOutboundSCIMUpdate(), request, nil, "")
if err != nil {
return nil, err
}
return s.unmarshalConfigurationResponse(httpRes)
}

func (s *outboundSCIM) DeleteConfiguration(ctx context.Context, appID string) error {
if appID == "" {
return utils.NewInvalidArgumentError("appID")
}
req := map[string]any{"appId": appID}
_, err := s.client.DoPostRequest(ctx, api.Routes.ManagementOutboundSCIMDelete(), req, nil, "")
return err
}

func (s *outboundSCIM) LoadConfiguration(ctx context.Context, appID string) (*descope.OutboundSCIMConfiguration, error) {
if appID == "" {
return nil, utils.NewInvalidArgumentError("appID")
}
res, err := s.client.DoGetRequest(ctx, api.Routes.ManagementOutboundSCIMLoad()+"/"+appID, nil, "")
if err != nil {
return nil, err
}
return s.unmarshalConfigurationResponse(res)
}

func (s *outboundSCIM) SetEnabled(ctx context.Context, appID string, enabled bool) (*descope.OutboundSCIMConfiguration, error) {
if appID == "" {
return nil, utils.NewInvalidArgumentError("appID")
}
body := map[string]any{"appId": appID, "enabled": enabled}
httpRes, err := s.client.DoPostRequest(ctx, api.Routes.ManagementOutboundSCIMSetEnabled(), body, nil, "")
if err != nil {
return nil, err
}
return s.unmarshalConfigurationResponse(httpRes)
}

func (s *outboundSCIM) unmarshalConfigurationResponse(httpRes *api.HTTPResponse) (*descope.OutboundSCIMConfiguration, error) {
res := &struct {
Configuration *descope.OutboundSCIMConfiguration `json:"configuration"`
}{}
if err := utils.Unmarshal([]byte(httpRes.BodyStr), res); err != nil {
return nil, err
}
return res.Configuration, nil
}
Loading
Loading