-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
f77ec86
commit 91af115
Showing
9 changed files
with
603 additions
and
16 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,154 @@ | ||
using Xunit; | ||
|
||
namespace Descope.Test.Integration | ||
{ | ||
public class SsoTests | ||
{ | ||
private readonly DescopeClient _descopeClient = IntegrationTestSetup.InitDescopeClient(); | ||
|
||
[Fact] | ||
public async Task Sso_SamlSetAndDelete() | ||
{ | ||
string? tenantId = null; | ||
string? roleName = null; | ||
try | ||
{ | ||
// Create a tenant | ||
tenantId = await _descopeClient.Management.Tenant.Create(new TenantOptions(Guid.NewGuid().ToString())); | ||
roleName = Guid.NewGuid().ToString()[..20]; | ||
await _descopeClient.Management.Role.Create(roleName, tenantId: tenantId); | ||
|
||
// Update sso settings | ||
var settings = new SsoSamlSettings("https://sometestidp.com", "entityId", "cert") | ||
{ | ||
RoleMappings = new List<RoleMapping> { new RoleMapping(new List<string> { "group1", "group2" }, roleName) } | ||
}; | ||
await _descopeClient.Management.Sso.ConfigureSAMLSettings(tenantId, settings, "https://myredirect.com", new List<string> { "domain1.com" }); | ||
|
||
var loadedSetting = await _descopeClient.Management.Sso.LoadSettings(tenantId); | ||
|
||
// Make sure the settings match | ||
Assert.Equal(settings.IdpUrl, loadedSetting.Saml?.IdpSsoUrl); | ||
Assert.Equal(settings.IdpEntityId, loadedSetting.Saml?.IdpEntityId); | ||
Assert.Equal(settings.IdpCertificate, loadedSetting.Saml!.IdpCertificate); | ||
Assert.NotEmpty(loadedSetting.Saml.GroupsMapping!.First().Role!.Id); | ||
Assert.Equal("group1", loadedSetting.Saml.GroupsMapping!.First().Groups![0]); | ||
Assert.Equal("group2", loadedSetting.Saml.GroupsMapping!.First().Groups![1]); | ||
Assert.Equal("https://myredirect.com", loadedSetting.Saml?.RedirectUrl); | ||
Assert.Equal("domain1.com", loadedSetting.Tenant.Domains.First()); | ||
|
||
// Delete the settings | ||
await _descopeClient.Management.Sso.DeleteSettings(tenantId); | ||
loadedSetting = await _descopeClient.Management.Sso.LoadSettings(tenantId); | ||
Assert.Empty(loadedSetting.Saml.IdpSsoUrl ?? ""); | ||
} | ||
finally | ||
{ | ||
if (!string.IsNullOrEmpty(tenantId)) | ||
{ | ||
try { await _descopeClient.Management.Tenant.Delete(tenantId); } | ||
catch { } | ||
} | ||
if (!string.IsNullOrEmpty(roleName)) | ||
{ | ||
try { await _descopeClient.Management.Role.Delete(roleName); } | ||
catch { } | ||
} | ||
} | ||
} | ||
|
||
[Fact] | ||
public async Task Sso_SamlByMetadata() | ||
{ | ||
string? tenantId = null; | ||
string? roleName = null; | ||
try | ||
{ | ||
// Create a tenant | ||
tenantId = await _descopeClient.Management.Tenant.Create(new TenantOptions(Guid.NewGuid().ToString())); | ||
roleName = Guid.NewGuid().ToString()[..20]; | ||
await _descopeClient.Management.Role.Create(roleName, tenantId: tenantId); | ||
|
||
// update sso settings | ||
var settings = new SsoSamlSettingsByMetadata("https://sometestidpmd.com") | ||
{ | ||
RoleMappings = new List<RoleMapping> { new RoleMapping(new List<string> { "group1", "group2" }, roleName) } | ||
}; | ||
await _descopeClient.Management.Sso.ConfigureSamlSettingsByMetadata(tenantId, settings, "https://myredirect.com", new List<string> { "domain1.com" }); | ||
|
||
var loadedSetting = await _descopeClient.Management.Sso.LoadSettings(tenantId); | ||
|
||
// Make sure the settings match | ||
Assert.Equal(settings.IdpMetadataUrl, loadedSetting.Saml.IdpMetadataUrl); | ||
Assert.NotEmpty(loadedSetting.Saml.GroupsMapping?.First()?.Role?.Id ?? ""); | ||
Assert.Equal("group1", loadedSetting.Saml.GroupsMapping?.First()?.Groups?[0]); | ||
Assert.Equal("group2", loadedSetting.Saml.GroupsMapping?.First()?.Groups?[1]); | ||
Assert.Equal("https://myredirect.com", loadedSetting.Saml?.RedirectUrl); | ||
Assert.Equal("domain1.com", loadedSetting.Tenant.Domains.First()); | ||
} | ||
finally | ||
{ | ||
if (!string.IsNullOrEmpty(tenantId)) | ||
{ | ||
try { await _descopeClient.Management.Tenant.Delete(tenantId); } | ||
catch { } | ||
} | ||
if (!string.IsNullOrEmpty(roleName)) | ||
{ | ||
try { await _descopeClient.Management.Role.Delete(roleName); } | ||
catch { } | ||
} | ||
} | ||
} | ||
|
||
[Fact] | ||
public async Task Sso_Oidc() | ||
{ | ||
string? tenantId = null; | ||
string? roleName = null; | ||
try | ||
{ | ||
// Create a tenant | ||
tenantId = await _descopeClient.Management.Tenant.Create(new TenantOptions(Guid.NewGuid().ToString())); | ||
roleName = Guid.NewGuid().ToString()[..20]; | ||
await _descopeClient.Management.Role.Create(roleName, tenantId: tenantId); | ||
|
||
// Update sso settings | ||
var settings = new SsoOidcSettings | ||
{ | ||
Name = "Name", | ||
ClientId = "ClientId", | ||
ClientSecret = "ClientSecret", | ||
AuthUrl = "https://mytestauth.com", | ||
TokenUrl = "https://mytestauth.com", | ||
JwksUrl = "https://mytestauth.com", | ||
AttributeMapping = new OidcAttributeMapping { } | ||
}; | ||
await _descopeClient.Management.Sso.ConfigureOidcSettings(tenantId, settings, new List<string> { "domain1.com" }); | ||
|
||
var loadedSetting = await _descopeClient.Management.Sso.LoadSettings(tenantId); | ||
|
||
// Make sure the settings match | ||
Assert.Equal(settings.Name, loadedSetting.Oidc.Name); | ||
Assert.Equal(settings.ClientId, loadedSetting.Oidc.ClientId); | ||
Assert.Equal(settings.AuthUrl, loadedSetting.Oidc.AuthUrl); | ||
Assert.Equal(settings.TokenUrl, loadedSetting.Oidc.TokenUrl); | ||
Assert.Equal(settings.JwksUrl, loadedSetting.Oidc.JwksUrl); | ||
Assert.Equal("domain1.com", loadedSetting.Tenant.Domains.First()); | ||
} | ||
finally | ||
{ | ||
if (!string.IsNullOrEmpty(tenantId)) | ||
{ | ||
try { await _descopeClient.Management.Tenant.Delete(tenantId); } | ||
catch { } | ||
} | ||
if (!string.IsNullOrEmpty(roleName)) | ||
{ | ||
try { await _descopeClient.Management.Role.Delete(roleName); } | ||
catch { } | ||
} | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,91 @@ | ||
using System.Text.Json.Serialization; | ||
|
||
namespace Descope.Internal.Management | ||
{ | ||
internal class Sso : ISso | ||
{ | ||
private readonly IHttpClient _httpClient; | ||
private readonly string _managementKey; | ||
|
||
internal Sso(IHttpClient httpClient, string managementKey) | ||
{ | ||
_httpClient = httpClient; | ||
_managementKey = managementKey; | ||
} | ||
|
||
public async Task<SsoTenantSettings> LoadSettings(string tenantId) | ||
{ | ||
Utils.EnforceRequiredArgs(("tenantId", tenantId)); | ||
return await _httpClient.Get<SsoTenantSettings>(Routes.SsoLoadSettings, _managementKey, queryParams: new Dictionary<string, string?> { { "tenantId", tenantId } }); | ||
} | ||
|
||
public async Task ConfigureSAMLSettings(string tenantId, SsoSamlSettings settings, string? redirectUrl = null, List<string>? domains = null) | ||
{ | ||
Utils.EnforceRequiredArgs( | ||
("tenantId", tenantId), | ||
("IdpUrl", settings.IdpUrl), | ||
("IdpCertificate", settings.IdpCertificate), | ||
("IdpEntityId", settings.IdpEntityId)); | ||
|
||
var body = new | ||
{ | ||
tenantId, | ||
settings = new | ||
{ | ||
idpUrl = settings.IdpUrl, | ||
entityId = settings.IdpEntityId, | ||
idpCert = settings.IdpCertificate, | ||
roleMappings = ConvertRoleMapping(settings.RoleMappings), | ||
attributeMapping = settings.AttributeMapping, | ||
}, | ||
redirectUrl, | ||
domains, | ||
}; | ||
await _httpClient.Post<object>(Routes.SsoSetSaml, _managementKey, body: body); | ||
} | ||
|
||
public async Task ConfigureSamlSettingsByMetadata(string tenantId, SsoSamlSettingsByMetadata settings, string? redirectUrl = null, List<string>? domains = null) | ||
{ | ||
Utils.EnforceRequiredArgs(("tenantId", tenantId), ("IdpMetadataUrl", settings.IdpMetadataUrl)); | ||
var body = new | ||
{ | ||
tenantId, | ||
settings = new | ||
{ | ||
idpMetadataUrl = settings.IdpMetadataUrl, | ||
roleMappings = ConvertRoleMapping(settings.RoleMappings), | ||
attributeMapping = settings.AttributeMapping, | ||
}, | ||
redirectUrl, | ||
domains, | ||
}; | ||
await _httpClient.Post<object>(Routes.SsoSetSamlByMetadata, _managementKey, body: body); | ||
} | ||
|
||
public async Task ConfigureOidcSettings(string tenantId, SsoOidcSettings settings, List<string>? domains = null) | ||
{ | ||
Utils.EnforceRequiredArgs(("tenantId", tenantId)); | ||
var body = new | ||
{ | ||
tenantId, | ||
settings, | ||
domains, | ||
}; | ||
await _httpClient.Post<object>(Routes.SsoSetOidc, _managementKey, body: body); | ||
} | ||
|
||
public async Task DeleteSettings(string tenantId) | ||
{ | ||
Utils.EnforceRequiredArgs(("tenantId", tenantId)); | ||
await _httpClient.Delete<object>(Routes.SsoDeleteSettings, _managementKey, queryParams: new Dictionary<string, string?> { { "tenantId", tenantId } }); | ||
} | ||
|
||
private static List<Dictionary<string, object>> ConvertRoleMapping(List<RoleMapping>? roleMappings) | ||
{ | ||
var mappings = new List<Dictionary<string, object>>(); | ||
roleMappings?.ForEach(entry => mappings.Add(new Dictionary<string, object> { { "groups", entry.Groups }, { "roleName", entry.Role } })); | ||
return mappings; | ||
} | ||
|
||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
namespace Descope.Internal.Management | ||
{ | ||
internal class Utils | ||
{ | ||
internal static void EnforceRequiredArgs(params (string, object?)[] args) | ||
{ | ||
foreach (var arg in args) | ||
{ | ||
if (arg.Item2 == null || (arg.Item2 is string s && string.IsNullOrEmpty(s))) | ||
{ | ||
throw new DescopeException($"The {arg.Item1} argument is required"); | ||
} | ||
} | ||
} | ||
} | ||
} |
Oops, something went wrong.