Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add SSO application management #21

Merged
merged 1 commit into from
Apr 21, 2024
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
97 changes: 97 additions & 0 deletions Descope.Test/IntegrationTests/Management/SsoApplicationTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
using Xunit;

namespace Descope.Test.Integration
{
public class SsoApplicationTests
{
private readonly DescopeClient _descopeClient = IntegrationTestSetup.InitDescopeClient();

[Fact]
public async Task SsoApplication_Saml()
{
string? id = null;
try
{
var name = "saml_app";
var url = "https://sometestidp.com";
// Create
var options = new SamlApplicationOptions(name, url);
id = await _descopeClient.Management.SsoApplication.CreateSAMLApplication(options);

// Load
var loadedApp = await _descopeClient.Management.SsoApplication.Load(id);
Assert.Equal(name, loadedApp.Name);
Assert.Equal(url, loadedApp.SamlSettings!.LoginPageUrl);

// Update
name = "saml_app_updated";
url = "https://sometestidp.com/updated";
options = new SamlApplicationOptions(name, url) { Id = id };
await _descopeClient.Management.SsoApplication.UpdateSamlApplication(options);

// Load All
var apps = await _descopeClient.Management.SsoApplication.LoadAll();
loadedApp = apps.Find(a => a.Id == id);
Assert.Equal(name, loadedApp!.Name);
Assert.Equal(url, loadedApp.SamlSettings!.LoginPageUrl);

// Delete
await _descopeClient.Management.SsoApplication.Delete(id);
id = null;
}
finally
{
if (!string.IsNullOrEmpty(id))
{
try { await _descopeClient.Management.SsoApplication.Delete(id); }
catch { }
}
}
}

[Fact]
public async Task SsoApplication_Oidc()
{
string? id = null;
try
{
var name = "oidc_app";
var url = "https://sometestidp.com";
// Create
var options = new OidcApplicationOptions(name, url);
id = await _descopeClient.Management.SsoApplication.CreateOidcApplication(options);

// Load
var loadedApp = await _descopeClient.Management.SsoApplication.Load(id);
Assert.Equal(name, loadedApp.Name);
Assert.Equal(url, loadedApp.OidcSettings!.LoginPageUrl);

// Update
name = "oidc_app_updated";
url = "https://sometestidp.com/updated";
options = new OidcApplicationOptions(name, url) { Id = id };
await _descopeClient.Management.SsoApplication.UpdateOidcApplication(options);

// Load All
var apps = await _descopeClient.Management.SsoApplication.LoadAll();
loadedApp = apps.Find(a => a.Id == id);
Assert.Equal(name, loadedApp!.Name);
Assert.Equal(url, loadedApp.OidcSettings!.LoginPageUrl);

// Delete
await _descopeClient.Management.SsoApplication.Delete(id);
id = null;
}
finally
{
if (!string.IsNullOrEmpty(id))
{
try { await _descopeClient.Management.SsoApplication.Delete(id); }
catch { }
}
}
}

}

}
12 changes: 12 additions & 0 deletions Descope/Internal/Http/Routes.cs
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,18 @@ public static class Routes

#endregion SSO

#region SSO Application

public const string SsoApplicationOidcCreate = "/v1/mgmt/sso/idp/app/oidc/create";
public const string SsoApplicationSamlCreate = "/v1/mgmt/sso/idp/app/saml/create";
public const string SsoApplicationOidcUpdate = "/v1/mgmt/sso/idp/app/oidc/update";
public const string SsoApplicationSamlUpdate = "/v1/mgmt/sso/idp/app/saml/update";
public const string SsoApplicationDelete = "/v1/mgmt/sso/idp/app/delete";
public const string SsoApplicationLoad = "/v1/mgmt/sso/idp/app/load";
public const string SsoApplicationLoadAll = "/v1/mgmt/sso/idp/apps/load";

#endregion SSO Application

#region Permission

public const string PermissionCreate = "/v1/mgmt/permission/create";
Expand Down
3 changes: 3 additions & 0 deletions Descope/Internal/Management/Managment.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ internal class Management : IManagement
public IUser User => _user;
public IAccessKey AccessKey => _accessKey;
public ISso Sso => _sso;
public ISsoApplication SsoApplication => _ssoApplication;
public IPasswordSettings Password => _password;
public IJwt Jwt => _jwt;
public IPermission Permission => _permission;
Expand All @@ -16,6 +17,7 @@ internal class Management : IManagement
private readonly User _user;
private readonly AccessKey _accessKey;
private readonly Sso _sso;
private readonly SsoApplication _ssoApplication;
private readonly Password _password;
private readonly Jwt _jwt;
private readonly Permission _permission;
Expand All @@ -28,6 +30,7 @@ public Management(IHttpClient client, string managementKey)
_user = new User(client, managementKey);
_accessKey = new AccessKey(client, managementKey);
_sso = new Sso(client, managementKey);
_ssoApplication = new SsoApplication(client, managementKey);
_password = new Password(client, managementKey);
_jwt = new Jwt(client, managementKey);
_permission = new Permission(client, managementKey);
Expand Down
80 changes: 80 additions & 0 deletions Descope/Internal/Management/SsoApplication.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@

using System.Text.Json.Serialization;

namespace Descope.Internal.Management
{
internal class SsoApplication : ISsoApplication
{
private readonly IHttpClient _httpClient;
private readonly string _managementKey;

internal SsoApplication(IHttpClient httpClient, string managementKey)
{
_httpClient = httpClient;
_managementKey = managementKey;
}

public async Task<string> CreateOidcApplication(OidcApplicationOptions options)
{
var resp = await _httpClient.Post<SsoApplicationCreateResponse>(Routes.SsoApplicationOidcCreate, _managementKey, body: options);
return resp.Id;
}

public async Task<string> CreateSAMLApplication(SamlApplicationOptions options)
{
var resp = await _httpClient.Post<SsoApplicationCreateResponse>(Routes.SsoApplicationSamlCreate, _managementKey, body: options);
return resp.Id;
}

public async Task UpdateOidcApplication(OidcApplicationOptions options)
{
await _httpClient.Post<object>(Routes.SsoApplicationOidcUpdate, _managementKey, body: options);
}

public async Task UpdateSamlApplication(SamlApplicationOptions options)
{
await _httpClient.Post<object>(Routes.SsoApplicationSamlUpdate, _managementKey, body: options);
}

public async Task Delete(string id)
{
var body = new { id };
await _httpClient.Post<object>(Routes.SsoApplicationDelete, _managementKey, body: body);
}

public async Task<SsoApplicationResponse> Load(string id)
{
return await _httpClient.Get<SsoApplicationResponse>(Routes.SsoApplicationLoad, _managementKey, queryParams: new Dictionary<string, string?> { { "id", id } });
}

public async Task<List<SsoApplicationResponse>> LoadAll()
{
var resp = await _httpClient.Get<SsoLoadAllResponse>(Routes.SsoApplicationLoadAll, _managementKey);
return resp.Apps;
}

}

internal class SsoApplicationCreateResponse
{
[JsonPropertyName("id")]
public string Id { get; set; }

public SsoApplicationCreateResponse(string id)
{
Id = id;
}
}

internal class SsoLoadAllResponse
{
[JsonPropertyName("apps")]
public List<SsoApplicationResponse> Apps { get; set; }

public SsoLoadAllResponse(List<SsoApplicationResponse> apps)
{
Apps = apps;
}
}

}
65 changes: 65 additions & 0 deletions Descope/Sdk/Managment.cs
Original file line number Diff line number Diff line change
Expand Up @@ -572,6 +572,66 @@ public interface ISso
Task DeleteSettings(string tenantId);
}

/// <summary>
/// Provides functions for managing SSO applications in a project.
/// </summary>
public interface ISsoApplication
{
/// <summary>
/// Create a new OIDC SSO application according to the given options.
/// </summary>
/// <param name="options">Options to define an OIDC application</param>
/// <returns>The created application ID</returns>
public Task<string> CreateOidcApplication(OidcApplicationOptions options);

/// <summary>
/// Create a new SAML SSO application according to the given options.
/// </summary>
/// <param name="options"></param>
/// <returns>The created application ID</returns>
public Task<string> CreateSAMLApplication(SamlApplicationOptions options);

/// <summary>
/// Update an existing OIDC SSO application.
/// <para>
/// <b>IMPORTANT:</b> All options are taken as-is and will override whatever value is currently set. Use carefully.
/// </para>
/// </summary>
/// <param name="options">The options to set for an existing SSO application</param>
public Task UpdateOidcApplication(OidcApplicationOptions options);

/// <summary>
/// Update an existing SAML SSO application.
/// <para>
/// <b>IMPORTANT:</b> All options are taken as-is and will override whatever value is currently set. Use carefully.
/// </para>
/// </summary>
/// <param name="options">The options to set for an existing SSO application</param>
public Task UpdateSamlApplication(SamlApplicationOptions options);

/// <summary>
/// Delete an existing SSO application.
/// <para>
/// <b>IMPORTANT:</b> This action is irreversible. Use carefully.
/// </para>
/// </summary>
/// <param name="id">The ID of application to delete</param>
public Task Delete(string id);

/// <summary>
/// Load an SSO application
/// </summary>
/// <param name="id">The ID of the application to load</param>
/// <returns>The loaded SSO application</returns>
public Task<SsoApplicationResponse> Load(string id);

/// <summary>
/// Load all project SSO applications.
/// </summary>
/// <returns>A list of all SSO applications.</returns>
public Task<List<SsoApplicationResponse>> LoadAll();
}

/// <summary>
/// Provides functions for managing permissions in a project.
/// </summary>
Expand Down Expand Up @@ -788,6 +848,11 @@ public interface IManagement
/// </summary>
public ISso Sso { get; }

/// <summary>
/// Provides functions for configuring SSO Applications in a project.
/// </summary>
public ISsoApplication SsoApplication { get; }

/// <summary>
/// Provides functions for managing password policy for a project or a tenant.
/// </summary>
Expand Down
Loading