From 829d549aef822cbb05fe30d9f04a9d8510eac18b Mon Sep 17 00:00:00 2001 From: kailash-b Date: Mon, 16 Sep 2024 12:50:05 +0530 Subject: [PATCH 1/3] Add support for managing SCIM configuration --- .../Clients/ConnectionsClient.cs | 45 ++++++++ .../Clients/IConnectionsClient.cs | 33 ++++++ .../Models/ScimConfiguration.cs | 60 +++++++++++ .../Models/ScimConfigurationCreateRequest.cs | 20 ++++ .../Models/ScimConfigurationUpdateRequest.cs | 20 ++++ src/Auth0.ManagementApi/Models/ScimMapping.cs | 22 ++++ .../ConnectionTests.cs | 102 ++++++++++++++++++ 7 files changed, 302 insertions(+) create mode 100644 src/Auth0.ManagementApi/Models/ScimConfiguration.cs create mode 100644 src/Auth0.ManagementApi/Models/ScimConfigurationCreateRequest.cs create mode 100644 src/Auth0.ManagementApi/Models/ScimConfigurationUpdateRequest.cs create mode 100644 src/Auth0.ManagementApi/Models/ScimMapping.cs diff --git a/src/Auth0.ManagementApi/Clients/ConnectionsClient.cs b/src/Auth0.ManagementApi/Clients/ConnectionsClient.cs index 07a16bb2b..bdb3cc242 100644 --- a/src/Auth0.ManagementApi/Clients/ConnectionsClient.cs +++ b/src/Auth0.ManagementApi/Clients/ConnectionsClient.cs @@ -143,5 +143,50 @@ public Task CheckStatusAsync(string id, CancellationToken cancellationToken = de { return Connection.GetAsync(BuildUri($"connections/{EncodePath(id)}/status"), DefaultHeaders, cancellationToken: cancellationToken); } + + /// + /// Retrieves an SCIM configuration. + /// + /// The id of the connection to retrieve its SCIM configuration + /// containing information required for creating an + /// The cancellation token to cancel operation. + /// A . + public Task CreateScimConfigurationAsync(string id, ScimConfigurationCreateRequest request, CancellationToken cancellationToken = default) + { + return Connection.SendAsync(HttpMethod.Post, BuildUri($"connections/{EncodePath(id)}/scim-configuration"), request, DefaultHeaders, cancellationToken: cancellationToken); + } + + /// + /// Retrieves an SCIM configuration. + /// + /// The id of the connection to retrieve its SCIM configuration + /// The cancellation token to cancel operation. + /// A . + public Task GetScimConfigurationAsync(string id, CancellationToken cancellationToken = default) + { + return Connection.GetAsync(BuildUri($"connections/{EncodePath(id)}/scim-configuration"), DefaultHeaders, cancellationToken: cancellationToken); + } + + /// + /// Updates an SCIM configuration. + /// + /// The id of the connection to update its SCIM configuration + /// containing information required for updating an + /// The cancellation token to cancel operation. + /// A . + public Task UpdateScimConfigurationAsync(string id, ScimConfigurationUpdateRequest request, CancellationToken cancellationToken = default) + { + return Connection.SendAsync(new HttpMethod("PATCH"), BuildUri($"connections/{EncodePath(id)}/scim-configuration"), request, DefaultHeaders, cancellationToken: cancellationToken); + } + + /// + /// Deletes an SCIM configuration. + /// + /// The id of the connection to delete its SCIM configuration + /// The cancellation token to cancel operation. + public Task DeleteScimConfigurationAsync(string id, CancellationToken cancellationToken = default) + { + return Connection.SendAsync(HttpMethod.Delete, BuildUri($"connections/{EncodePath(id)}/scim-configuration"), null, DefaultHeaders, cancellationToken: cancellationToken); + } } } diff --git a/src/Auth0.ManagementApi/Clients/IConnectionsClient.cs b/src/Auth0.ManagementApi/Clients/IConnectionsClient.cs index 70699bc4c..aa6674696 100644 --- a/src/Auth0.ManagementApi/Clients/IConnectionsClient.cs +++ b/src/Auth0.ManagementApi/Clients/IConnectionsClient.cs @@ -70,5 +70,38 @@ public interface IConnectionsClient /// The cancellation token to cancel operation. /// A that represents the asynchronous check operation. Will throw if the status check fails. Task CheckStatusAsync(string id, CancellationToken cancellationToken = default); + + /// + /// Creates an SCIM configuration. + /// + /// The id of the connection to create an + /// containing information required for creating an + /// The cancellation token to cancel operation. + /// A . + Task CreateScimConfigurationAsync(string id, ScimConfigurationCreateRequest request, CancellationToken cancellationToken = default); + + /// + /// Retrieves an SCIM configuration. + /// + /// The id of the connection to retrieve its + /// The cancellation token to cancel operation. + /// A . + Task GetScimConfigurationAsync(string id, CancellationToken cancellationToken = default); + + /// + /// Updates an SCIM configuration. + /// + /// The id of the connection to be update its + /// containing information required for updating an + /// The cancellation token to cancel operation. + /// A . + Task UpdateScimConfigurationAsync(string id, ScimConfigurationUpdateRequest request, CancellationToken cancellationToken = default); + + /// + /// Deletes an SCIM configuration. + /// + /// The id of the connection to be update its + /// The cancellation token to cancel operation. + Task DeleteScimConfigurationAsync(string id, CancellationToken cancellationToken = default); } } diff --git a/src/Auth0.ManagementApi/Models/ScimConfiguration.cs b/src/Auth0.ManagementApi/Models/ScimConfiguration.cs new file mode 100644 index 000000000..21ab40900 --- /dev/null +++ b/src/Auth0.ManagementApi/Models/ScimConfiguration.cs @@ -0,0 +1,60 @@ +using System.Collections.Generic; +using Newtonsoft.Json; +using Newtonsoft.Json.Serialization; + +namespace Auth0.ManagementApi.Models +{ + /// + /// Represents an SCIM Configuration + /// + public class ScimConfiguration + { + /// + /// The connection's identifier + /// + [JsonProperty("connection_id")] + public string ConnectionId { get; set; } + + /// + /// The connection's identifier + /// + [JsonProperty("connection_name")] + public string ConnectionName { get; set; } + + /// + /// The connection's strategy + /// + [JsonProperty("strategy")] + public string Strategy { get; set; } + + /// + /// The tenant's name + /// + [JsonProperty("tenant_name")] + public string TenantName { get; set; } + + /// + /// User ID attribute for generating unique user ids + /// + [JsonProperty("user_id_attribute")] + public string UserIdAttribute { get; set; } + + /// + /// The mapping between auth0 and SCIM + /// + [JsonProperty("mapping")] + public List Mapping { get; set; } + + /// + /// The Date Time SCIM Configuration was created + /// + [JsonProperty("created_at")] + public string CreatedAt { get; set; } + + /// + /// The Date Time SCIM Configuration was last updated + /// + [JsonProperty("updated_on")] + public string UpdatedOn { get; set; } + } +} \ No newline at end of file diff --git a/src/Auth0.ManagementApi/Models/ScimConfigurationCreateRequest.cs b/src/Auth0.ManagementApi/Models/ScimConfigurationCreateRequest.cs new file mode 100644 index 000000000..8e25c6a3a --- /dev/null +++ b/src/Auth0.ManagementApi/Models/ScimConfigurationCreateRequest.cs @@ -0,0 +1,20 @@ +using System.Collections.Generic; +using Newtonsoft.Json; + +namespace Auth0.ManagementApi.Models +{ + public class ScimConfigurationCreateRequest + { + /// + /// User ID attribute for generating unique user ids + /// + [JsonProperty("user_id_attribute")] + public string UserIdAttribute { get; set; } + + /// + /// The mapping between auth0 and SCIM + /// + [JsonProperty("mapping")] + public List Mapping { get; set; } + } +} \ No newline at end of file diff --git a/src/Auth0.ManagementApi/Models/ScimConfigurationUpdateRequest.cs b/src/Auth0.ManagementApi/Models/ScimConfigurationUpdateRequest.cs new file mode 100644 index 000000000..1a0397e76 --- /dev/null +++ b/src/Auth0.ManagementApi/Models/ScimConfigurationUpdateRequest.cs @@ -0,0 +1,20 @@ +using System.Collections.Generic; +using Newtonsoft.Json; + +namespace Auth0.ManagementApi.Models +{ + public class ScimConfigurationUpdateRequest + { + /// + /// User ID attribute for generating unique user ids + /// + [JsonProperty("user_id_attribute")] + public string UserIdAttribute { get; set; } + + /// + /// The mapping between auth0 and SCIM + /// + [JsonProperty("mapping")] + public List Mapping { get; set; } + } +} \ No newline at end of file diff --git a/src/Auth0.ManagementApi/Models/ScimMapping.cs b/src/Auth0.ManagementApi/Models/ScimMapping.cs new file mode 100644 index 000000000..aa44d268a --- /dev/null +++ b/src/Auth0.ManagementApi/Models/ScimMapping.cs @@ -0,0 +1,22 @@ +using Newtonsoft.Json; + +namespace Auth0.ManagementApi.Models +{ + /// + /// Represents the mapping between SCIM and Auth0 + /// + public class ScimMapping + { + /// + /// The field location in the auth0 schema + /// + [JsonProperty("auth0")] + public string Auth0 { get; set; } + + /// + /// The field location in the SCIM schema + /// + [JsonProperty("scim")] + public string Scim { get; set; } + } +} \ No newline at end of file diff --git a/tests/Auth0.ManagementApi.IntegrationTests/ConnectionTests.cs b/tests/Auth0.ManagementApi.IntegrationTests/ConnectionTests.cs index 2d2708296..bd703a21e 100644 --- a/tests/Auth0.ManagementApi.IntegrationTests/ConnectionTests.cs +++ b/tests/Auth0.ManagementApi.IntegrationTests/ConnectionTests.cs @@ -9,6 +9,8 @@ using Auth0.Tests.Shared; using Auth0.ManagementApi.Paging; using System.Collections.Generic; +using Auth0.AuthenticationApi.Models; +using Auth0.Tests.Shared; namespace Auth0.ManagementApi.IntegrationTests { @@ -215,5 +217,105 @@ public async Task Test_multiple_strategies() // Assert Assert.NotNull(connections); } + + [Fact] + public async Task Test_scim_configuration_crud_sequence() + { + var expectedScimConfiguration = new ScimConfiguration() + { + Strategy = "samlp", + ConnectionId = "con_wP6Ya7Fbp98JQXuY", + ConnectionName = "fake-saml", + TenantName = "brucke", + UserIdAttribute = "string", + Mapping = new List() + { + new() + { + Auth0 = "string", + Scim = "string" + } + } + }; + + var token = await GenerateBruckeManagementApiToken(); + var apiClient = new ManagementApiClient(token, TestBaseUtils.GetVariable("BRUCKE_MANAGEMENT_API_URL"), + new HttpClientManagementConnection(options: new HttpClientManagementConnectionOptions + { NumberOfHttpRetries = 9 })); + try + { + // Create an SCIM configuration + await apiClient.Connections.CreateScimConfigurationAsync( + expectedScimConfiguration.ConnectionId, new ScimConfigurationCreateRequest() + { + UserIdAttribute = expectedScimConfiguration.UserIdAttribute, + Mapping = expectedScimConfiguration.Mapping + }); + + // Get SCIM configuration and verify + var scimConfiguration = + await apiClient.Connections.GetScimConfigurationAsync(expectedScimConfiguration.ConnectionId); + + AssertScimConfiguration(expectedScimConfiguration, scimConfiguration); + + // Update SCIM Configuration and Validate + var updateRequest = new ScimConfigurationUpdateRequest() + { + UserIdAttribute = "string", + Mapping = new List() + { + new() + { + Auth0 = "string", + Scim = "string" + }, + new() + { + Auth0 = "int", + Scim = "int" + } + } + + }; + expectedScimConfiguration.UserIdAttribute = updateRequest.UserIdAttribute; + scimConfiguration = + await apiClient.Connections.UpdateScimConfigurationAsync( + expectedScimConfiguration.ConnectionId, updateRequest); + AssertScimConfiguration(expectedScimConfiguration, scimConfiguration); + } + finally + { + // Delete SCIM Configuration and Validate + await apiClient.Connections.DeleteScimConfigurationAsync(expectedScimConfiguration.ConnectionId); + } + } + + private async Task GenerateBruckeManagementApiToken() + { + using var authenticationApiClient = + new TestAuthenticationApiClient(TestBaseUtils.GetVariable("BRUCKE_AUTHENTICATION_API_URL")); + // Get the access token + var token = await authenticationApiClient.GetTokenAsync(new ClientCredentialsTokenRequest + { + ClientId = TestBaseUtils.GetVariable("BRUCKE_MANAGEMENT_API_CLIENT_ID"), + ClientSecret = TestBaseUtils.GetVariable("BRUCKE_MANAGEMENT_API_CLIENT_SECRET"), + Audience = TestBaseUtils.GetVariable("BRUCKE_MANAGEMENT_API_AUDIENCE") + }); + + return token.AccessToken; + } + + private void AssertScimConfiguration(ScimConfiguration expectedScimConfiguration, + ScimConfiguration actualScimConfiguration) + { + actualScimConfiguration.Should().NotBeNull(); + Assert.Equal(expectedScimConfiguration.ConnectionId, actualScimConfiguration.ConnectionId); + Assert.Equal(expectedScimConfiguration.ConnectionName, actualScimConfiguration.ConnectionName); + Assert.Equal(expectedScimConfiguration.TenantName, actualScimConfiguration.TenantName); + Assert.Equal(expectedScimConfiguration.UserIdAttribute, actualScimConfiguration.UserIdAttribute); + Assert.Equal(expectedScimConfiguration.Strategy, actualScimConfiguration.Strategy); + Assert.NotNull(actualScimConfiguration.UpdatedOn); + Assert.NotNull(actualScimConfiguration.CreatedAt); + } } } From 63598253c1b20d378e91484cbc3bc5ad4a9f8a5e Mon Sep 17 00:00:00 2001 From: kailash-b Date: Mon, 16 Sep 2024 17:28:35 +0530 Subject: [PATCH 2/3] Add support for managing SCIM tokens --- .../Clients/ConnectionsClient.cs | 50 ++++++- .../Clients/IConnectionsClient.cs | 40 +++++- src/Auth0.ManagementApi/Models/ScimToken.cs | 13 ++ .../Models/ScimTokenBase.cs | 35 +++++ .../Models/ScimTokenCreateRequest.cs | 23 +++ .../Models/ScimTokenCreateResponse.cs | 13 ++ .../ConnectionTests.cs | 131 ++++++++++++++++++ 7 files changed, 301 insertions(+), 4 deletions(-) create mode 100644 src/Auth0.ManagementApi/Models/ScimToken.cs create mode 100644 src/Auth0.ManagementApi/Models/ScimTokenBase.cs create mode 100644 src/Auth0.ManagementApi/Models/ScimTokenCreateRequest.cs create mode 100644 src/Auth0.ManagementApi/Models/ScimTokenCreateResponse.cs diff --git a/src/Auth0.ManagementApi/Clients/ConnectionsClient.cs b/src/Auth0.ManagementApi/Clients/ConnectionsClient.cs index bdb3cc242..b3d6acb73 100644 --- a/src/Auth0.ManagementApi/Clients/ConnectionsClient.cs +++ b/src/Auth0.ManagementApi/Clients/ConnectionsClient.cs @@ -14,7 +14,8 @@ namespace Auth0.ManagementApi.Clients /// public class ConnectionsClient : BaseClient, IConnectionsClient { - readonly JsonConverter[] converters = new JsonConverter[] { new PagedListConverter("connections") }; + private readonly JsonConverter[] _converters = { new PagedListConverter("connections") }; + private readonly JsonConverter[] _defaultMappingsConverter = { new ListConverter("mapping") }; /// /// Initializes a new instance of the . @@ -118,7 +119,7 @@ public Task> GetAllAsync(GetConnectionsRequest request, P } } - return Connection.GetAsync>(BuildUri("connections", queryStrings), DefaultHeaders, converters, cancellationToken); + return Connection.GetAsync>(BuildUri("connections", queryStrings), DefaultHeaders, _converters, cancellationToken); } /// @@ -188,5 +189,50 @@ public Task DeleteScimConfigurationAsync(string id, CancellationToken cancellati { return Connection.SendAsync(HttpMethod.Delete, BuildUri($"connections/{EncodePath(id)}/scim-configuration"), null, DefaultHeaders, cancellationToken: cancellationToken); } + + /// + /// Retrieves the default . + /// + /// The id of the connection to retrieve its default + /// The cancellation token to cancel operation. + /// An IList of . + public Task> GetDefaultScimMappingAsync(string id, CancellationToken cancellationToken = default) + { + return Connection.GetAsync>(BuildUri($"connections/{EncodePath(id)}/scim-configuration/default-mapping"), DefaultHeaders, _defaultMappingsConverter, cancellationToken: cancellationToken); + } + + /// + /// Creates an SCIM token. + /// + /// The id of the connection to create an + /// containing information required for creating an + /// The cancellation token to cancel operation. + /// An . + public Task CreateScimTokenAsync(string id, ScimTokenCreateRequest request, CancellationToken cancellationToken = default) + { + return Connection.SendAsync(HttpMethod.Post, BuildUri($"connections/{EncodePath(id)}/scim-configuration/tokens"), request, DefaultHeaders, cancellationToken: cancellationToken); + } + + /// + /// Retrieves all for the given connection. + /// + /// The id of the connection to retrieve its + /// The cancellation token to cancel operation. + /// An . + public Task> GetScimTokenAsync(string id, CancellationToken cancellationToken = default) + { + return Connection.GetAsync>(BuildUri($"connections/{EncodePath(id)}/scim-configuration/tokens"), DefaultHeaders, cancellationToken: cancellationToken); + } + + /// + /// Deletes an SCIM token. + /// + /// The ID of the connection that owns the to be deleted + /// The ID of the to delete + /// The cancellation token to cancel operation. + public Task DeleteScimTokenAsync(string id, string tokenId, CancellationToken cancellationToken = default) + { + return Connection.SendAsync(HttpMethod.Delete, BuildUri($"connections/{EncodePath(id)}/scim-configuration/tokens/{EncodePath(tokenId)}"), null, DefaultHeaders, cancellationToken: cancellationToken); + } } } diff --git a/src/Auth0.ManagementApi/Clients/IConnectionsClient.cs b/src/Auth0.ManagementApi/Clients/IConnectionsClient.cs index aa6674696..45034f16b 100644 --- a/src/Auth0.ManagementApi/Clients/IConnectionsClient.cs +++ b/src/Auth0.ManagementApi/Clients/IConnectionsClient.cs @@ -1,7 +1,10 @@ + + namespace Auth0.ManagementApi.Clients { using System.Threading; using System.Threading.Tasks; + using System.Collections.Generic; using Models; using Paging; @@ -91,7 +94,7 @@ public interface IConnectionsClient /// /// Updates an SCIM configuration. /// - /// The id of the connection to be update its + /// The id of the connection to update /// containing information required for updating an /// The cancellation token to cancel operation. /// A . @@ -100,8 +103,41 @@ public interface IConnectionsClient /// /// Deletes an SCIM configuration. /// - /// The id of the connection to be update its + /// The id of the connection to delete /// The cancellation token to cancel operation. Task DeleteScimConfigurationAsync(string id, CancellationToken cancellationToken = default); + + /// + /// Retrieves the default . + /// + /// The id of the connection to retrieve its default + /// The cancellation token to cancel operation. + /// An IList of . + Task> GetDefaultScimMappingAsync(string id, CancellationToken cancellationToken = default); + + /// + /// Creates an SCIM token. + /// + /// The id of the connection to create an + /// containing information required for creating an + /// The cancellation token to cancel operation. + /// An . + Task CreateScimTokenAsync(string id, ScimTokenCreateRequest request, CancellationToken cancellationToken = default); + + /// + /// Retrieves all for the given connection. + /// + /// The id of the connection to retrieve its + /// The cancellation token to cancel operation. + /// An . + Task> GetScimTokenAsync(string id, CancellationToken cancellationToken = default); + + /// + /// Deletes an SCIM token. + /// + /// The ID of the connection that owns the to be deleted + /// The ID of the to delete + /// The cancellation token to cancel operation. + Task DeleteScimTokenAsync(string id, string tokenId, CancellationToken cancellationToken = default); } } diff --git a/src/Auth0.ManagementApi/Models/ScimToken.cs b/src/Auth0.ManagementApi/Models/ScimToken.cs new file mode 100644 index 000000000..424c0bb45 --- /dev/null +++ b/src/Auth0.ManagementApi/Models/ScimToken.cs @@ -0,0 +1,13 @@ +using Newtonsoft.Json; + +namespace Auth0.ManagementApi.Models +{ + public class ScimToken : ScimTokenBase + { + /// + /// The token's last used at timestamp + /// + [JsonProperty("last_used_at")] + public string LastUsedAt { get; set; } + } +} \ No newline at end of file diff --git a/src/Auth0.ManagementApi/Models/ScimTokenBase.cs b/src/Auth0.ManagementApi/Models/ScimTokenBase.cs new file mode 100644 index 000000000..87f20ab87 --- /dev/null +++ b/src/Auth0.ManagementApi/Models/ScimTokenBase.cs @@ -0,0 +1,35 @@ +using Newtonsoft.Json; +using Newtonsoft.Json.Serialization; + +namespace Auth0.ManagementApi.Models +{ + /// + /// Represents an SCIM token for an SCIM client. + /// + public class ScimTokenBase + { + /// + /// The token's identifier + /// + [JsonProperty("token_id")] + public string TokenId { get; set; } + + /// + /// The scopes of the scim token + /// + [JsonProperty("scopes")] + public string[] Scopes { get; set; } + + /// + /// The token's created at timestamp + /// + [JsonProperty("created_at")] + public string CreatedAt { get; set; } + + /// + /// The token's valid until at timestamp + /// + [JsonProperty("valid_until")] + public string ValidUntil { get; set; } + } +} \ No newline at end of file diff --git a/src/Auth0.ManagementApi/Models/ScimTokenCreateRequest.cs b/src/Auth0.ManagementApi/Models/ScimTokenCreateRequest.cs new file mode 100644 index 000000000..fdb8f3a1f --- /dev/null +++ b/src/Auth0.ManagementApi/Models/ScimTokenCreateRequest.cs @@ -0,0 +1,23 @@ +using Newtonsoft.Json; +using Newtonsoft.Json.Serialization; + +namespace Auth0.ManagementApi.Models +{ + /// + /// Represents the client request to Create + /// + public class ScimTokenCreateRequest + { + /// + /// The scopes of the scim token + /// + [JsonProperty("scopes")] + public string[] Scopes { get; set; } + + /// + /// Lifetime of the token in seconds. Must be greater than 900 + /// + [JsonProperty("token_lifetime")] + public int TokenLifetime { get; set; } + } +} \ No newline at end of file diff --git a/src/Auth0.ManagementApi/Models/ScimTokenCreateResponse.cs b/src/Auth0.ManagementApi/Models/ScimTokenCreateResponse.cs new file mode 100644 index 000000000..f235b247c --- /dev/null +++ b/src/Auth0.ManagementApi/Models/ScimTokenCreateResponse.cs @@ -0,0 +1,13 @@ +using Newtonsoft.Json; + +namespace Auth0.ManagementApi.Models +{ + public class ScimTokenCreateResponse : ScimTokenBase + { + /// + /// The SCIM client's token + /// + [JsonProperty("token")] + public string Token { get; set; } + } +} \ No newline at end of file diff --git a/tests/Auth0.ManagementApi.IntegrationTests/ConnectionTests.cs b/tests/Auth0.ManagementApi.IntegrationTests/ConnectionTests.cs index bd703a21e..0e44b9c3a 100644 --- a/tests/Auth0.ManagementApi.IntegrationTests/ConnectionTests.cs +++ b/tests/Auth0.ManagementApi.IntegrationTests/ConnectionTests.cs @@ -290,6 +290,137 @@ await apiClient.Connections.UpdateScimConfigurationAsync( } } + [Fact] + public async Task Test_get_default_scim_configuration() + { + var expectedScimConfiguration = new ScimConfiguration() + { + Strategy = "samlp", + ConnectionId = "con_wP6Ya7Fbp98JQXuY", + ConnectionName = "fake-saml", + TenantName = "brucke", + UserIdAttribute = "string", + Mapping = new List() + { + new() + { + Auth0 = "random", + Scim = "random" + } + } + }; + + var token = await GenerateBruckeManagementApiToken(); + var apiClient = new ManagementApiClient(token, TestBaseUtils.GetVariable("BRUCKE_MANAGEMENT_API_URL"), + new HttpClientManagementConnection(options: new HttpClientManagementConnectionOptions + { NumberOfHttpRetries = 9 })); + try + { + // Create an SCIM configuration + await apiClient.Connections.CreateScimConfigurationAsync( + expectedScimConfiguration.ConnectionId, new ScimConfigurationCreateRequest() + { + UserIdAttribute = expectedScimConfiguration.UserIdAttribute, + Mapping = expectedScimConfiguration.Mapping + }); + + var defaultScimMapping = await apiClient.Connections.GetDefaultScimMappingAsync(expectedScimConfiguration.ConnectionId); + Assert.NotNull(defaultScimMapping); + } + finally + { + // Clean-up + await apiClient.Connections.DeleteScimConfigurationAsync(expectedScimConfiguration.ConnectionId); + } + } + + [Fact] + public async Task Test_scim_token_crud_sequence() + { + var expectedScimConfiguration = new ScimConfiguration() + { + Strategy = "samlp", + ConnectionId = "con_wP6Ya7Fbp98JQXuY", + ConnectionName = "fake-saml", + TenantName = "brucke", + UserIdAttribute = "string", + Mapping = new List() + { + new() + { + Auth0 = "random", + Scim = "random" + } + } + }; + + var token = await GenerateBruckeManagementApiToken(); + var apiClient = new ManagementApiClient(token, TestBaseUtils.GetVariable("BRUCKE_MANAGEMENT_API_URL"), + new HttpClientManagementConnection(options: new HttpClientManagementConnectionOptions + { NumberOfHttpRetries = 9 })); + try + { + // Create an SCIM configuration + await apiClient.Connections.CreateScimConfigurationAsync( + expectedScimConfiguration.ConnectionId, new ScimConfigurationCreateRequest() + { + UserIdAttribute = expectedScimConfiguration.UserIdAttribute, + Mapping = expectedScimConfiguration.Mapping + }); + + var createTokenRequest = new ScimTokenCreateRequest() + { + Scopes = new string[] { "openid", "offline_access" }, + TokenLifetime = 1000 + }; + + // Create two SCIM tokens and Validate + var scimTokenOne = await CreateScimTokenAndValidate(createTokenRequest); + var scimTokenTwo = await CreateScimTokenAndValidate(createTokenRequest); + + // Retrieve the token and validate + var retrievedScimTokens = + await apiClient.Connections.GetScimTokenAsync(expectedScimConfiguration.ConnectionId); + Assert.Equal(scimTokenOne.Scopes, retrievedScimTokens[0].Scopes); + Assert.Equal(scimTokenOne.TokenId, retrievedScimTokens[0].TokenId); + Assert.Equal(scimTokenOne.CreatedAt, retrievedScimTokens[0].CreatedAt); + Assert.Equal(scimTokenOne.ValidUntil, retrievedScimTokens[0].ValidUntil); + + Assert.Equal(scimTokenTwo.Scopes, retrievedScimTokens[1].Scopes); + Assert.Equal(scimTokenTwo.TokenId, retrievedScimTokens[1].TokenId); + Assert.Equal(scimTokenTwo.CreatedAt, retrievedScimTokens[1].CreatedAt); + Assert.Equal(scimTokenTwo.ValidUntil, retrievedScimTokens[1].ValidUntil); + + // Delete SCIM Token and validate + await apiClient.Connections.DeleteScimTokenAsync(expectedScimConfiguration.ConnectionId, scimTokenOne.TokenId); + await apiClient.Connections.DeleteScimTokenAsync(expectedScimConfiguration.ConnectionId, scimTokenTwo.TokenId); + var retrievedScimTokensAfterDelete = + await apiClient.Connections.GetScimTokenAsync(expectedScimConfiguration.ConnectionId); + Assert.Empty(retrievedScimTokensAfterDelete); + } + finally + { + // Clean-up + await apiClient.Connections.DeleteScimConfigurationAsync(expectedScimConfiguration.ConnectionId); + } + + async Task CreateScimTokenAndValidate(ScimTokenCreateRequest createTokenRequest) + { + var scimToken = + await apiClient.Connections.CreateScimTokenAsync(expectedScimConfiguration.ConnectionId, createTokenRequest); + Assert.NotNull(scimToken); + Assert.NotNull(scimToken.Scopes); + Assert.NotNull(scimToken.TokenId); + Assert.NotNull(scimToken.Token); + Assert.NotNull(scimToken.CreatedAt); + Assert.NotNull(scimToken.ValidUntil); + scimToken.Scopes.Should().HaveCount(2); + Assert.Equal(createTokenRequest.Scopes, scimToken.Scopes); + return scimToken; + } + } + + private async Task GenerateBruckeManagementApiToken() { using var authenticationApiClient = From dccacb55d50c54699b1ca369b138847d573583bf Mon Sep 17 00:00:00 2001 From: kailash-b Date: Mon, 16 Sep 2024 17:44:14 +0530 Subject: [PATCH 3/3] Refactor models folder structure --- .../Clients/ConnectionsClient.cs | 14 +++++++------- .../Clients/IConnectionsClient.cs | 10 +++++----- .../Models/{ => Scim}/ScimConfiguration.cs | 0 .../{ => Scim}/ScimConfigurationCreateRequest.cs | 0 .../{ => Scim}/ScimConfigurationUpdateRequest.cs | 0 .../Models/{ => Scim}/ScimMapping.cs | 0 .../Models/{ => Scim}/ScimToken.cs | 0 .../Models/{ => Scim}/ScimTokenBase.cs | 0 .../Models/{ => Scim}/ScimTokenCreateRequest.cs | 0 .../Models/{ => Scim}/ScimTokenCreateResponse.cs | 0 10 files changed, 12 insertions(+), 12 deletions(-) rename src/Auth0.ManagementApi/Models/{ => Scim}/ScimConfiguration.cs (100%) rename src/Auth0.ManagementApi/Models/{ => Scim}/ScimConfigurationCreateRequest.cs (100%) rename src/Auth0.ManagementApi/Models/{ => Scim}/ScimConfigurationUpdateRequest.cs (100%) rename src/Auth0.ManagementApi/Models/{ => Scim}/ScimMapping.cs (100%) rename src/Auth0.ManagementApi/Models/{ => Scim}/ScimToken.cs (100%) rename src/Auth0.ManagementApi/Models/{ => Scim}/ScimTokenBase.cs (100%) rename src/Auth0.ManagementApi/Models/{ => Scim}/ScimTokenCreateRequest.cs (100%) rename src/Auth0.ManagementApi/Models/{ => Scim}/ScimTokenCreateResponse.cs (100%) diff --git a/src/Auth0.ManagementApi/Clients/ConnectionsClient.cs b/src/Auth0.ManagementApi/Clients/ConnectionsClient.cs index b3d6acb73..092cd5db6 100644 --- a/src/Auth0.ManagementApi/Clients/ConnectionsClient.cs +++ b/src/Auth0.ManagementApi/Clients/ConnectionsClient.cs @@ -146,9 +146,9 @@ public Task CheckStatusAsync(string id, CancellationToken cancellationToken = de } /// - /// Retrieves an SCIM configuration. + /// Creates an . /// - /// The id of the connection to retrieve its SCIM configuration + /// The id of the connection to create an /// containing information required for creating an /// The cancellation token to cancel operation. /// A . @@ -158,9 +158,9 @@ public Task CreateScimConfigurationAsync(string id, ScimConfi } /// - /// Retrieves an SCIM configuration. + /// Retrieves an . /// - /// The id of the connection to retrieve its SCIM configuration + /// The id of the connection to retrieve its /// The cancellation token to cancel operation. /// A . public Task GetScimConfigurationAsync(string id, CancellationToken cancellationToken = default) @@ -169,7 +169,7 @@ public Task GetScimConfigurationAsync(string id, Cancellation } /// - /// Updates an SCIM configuration. + /// Updates an n. /// /// The id of the connection to update its SCIM configuration /// containing information required for updating an @@ -181,7 +181,7 @@ public Task UpdateScimConfigurationAsync(string id, ScimConfi } /// - /// Deletes an SCIM configuration. + /// Deletes an . /// /// The id of the connection to delete its SCIM configuration /// The cancellation token to cancel operation. @@ -202,7 +202,7 @@ public Task> GetDefaultScimMappingAsync(string id, Cancellati } /// - /// Creates an SCIM token. + /// Creates an . /// /// The id of the connection to create an /// containing information required for creating an diff --git a/src/Auth0.ManagementApi/Clients/IConnectionsClient.cs b/src/Auth0.ManagementApi/Clients/IConnectionsClient.cs index 45034f16b..815c32c34 100644 --- a/src/Auth0.ManagementApi/Clients/IConnectionsClient.cs +++ b/src/Auth0.ManagementApi/Clients/IConnectionsClient.cs @@ -75,7 +75,7 @@ public interface IConnectionsClient Task CheckStatusAsync(string id, CancellationToken cancellationToken = default); /// - /// Creates an SCIM configuration. + /// Creates an . /// /// The id of the connection to create an /// containing information required for creating an @@ -84,7 +84,7 @@ public interface IConnectionsClient Task CreateScimConfigurationAsync(string id, ScimConfigurationCreateRequest request, CancellationToken cancellationToken = default); /// - /// Retrieves an SCIM configuration. + /// Retrieves an . /// /// The id of the connection to retrieve its /// The cancellation token to cancel operation. @@ -92,7 +92,7 @@ public interface IConnectionsClient Task GetScimConfigurationAsync(string id, CancellationToken cancellationToken = default); /// - /// Updates an SCIM configuration. + /// Updates an . /// /// The id of the connection to update /// containing information required for updating an @@ -101,7 +101,7 @@ public interface IConnectionsClient Task UpdateScimConfigurationAsync(string id, ScimConfigurationUpdateRequest request, CancellationToken cancellationToken = default); /// - /// Deletes an SCIM configuration. + /// Deletes an . /// /// The id of the connection to delete /// The cancellation token to cancel operation. @@ -116,7 +116,7 @@ public interface IConnectionsClient Task> GetDefaultScimMappingAsync(string id, CancellationToken cancellationToken = default); /// - /// Creates an SCIM token. + /// Creates an . /// /// The id of the connection to create an /// containing information required for creating an diff --git a/src/Auth0.ManagementApi/Models/ScimConfiguration.cs b/src/Auth0.ManagementApi/Models/Scim/ScimConfiguration.cs similarity index 100% rename from src/Auth0.ManagementApi/Models/ScimConfiguration.cs rename to src/Auth0.ManagementApi/Models/Scim/ScimConfiguration.cs diff --git a/src/Auth0.ManagementApi/Models/ScimConfigurationCreateRequest.cs b/src/Auth0.ManagementApi/Models/Scim/ScimConfigurationCreateRequest.cs similarity index 100% rename from src/Auth0.ManagementApi/Models/ScimConfigurationCreateRequest.cs rename to src/Auth0.ManagementApi/Models/Scim/ScimConfigurationCreateRequest.cs diff --git a/src/Auth0.ManagementApi/Models/ScimConfigurationUpdateRequest.cs b/src/Auth0.ManagementApi/Models/Scim/ScimConfigurationUpdateRequest.cs similarity index 100% rename from src/Auth0.ManagementApi/Models/ScimConfigurationUpdateRequest.cs rename to src/Auth0.ManagementApi/Models/Scim/ScimConfigurationUpdateRequest.cs diff --git a/src/Auth0.ManagementApi/Models/ScimMapping.cs b/src/Auth0.ManagementApi/Models/Scim/ScimMapping.cs similarity index 100% rename from src/Auth0.ManagementApi/Models/ScimMapping.cs rename to src/Auth0.ManagementApi/Models/Scim/ScimMapping.cs diff --git a/src/Auth0.ManagementApi/Models/ScimToken.cs b/src/Auth0.ManagementApi/Models/Scim/ScimToken.cs similarity index 100% rename from src/Auth0.ManagementApi/Models/ScimToken.cs rename to src/Auth0.ManagementApi/Models/Scim/ScimToken.cs diff --git a/src/Auth0.ManagementApi/Models/ScimTokenBase.cs b/src/Auth0.ManagementApi/Models/Scim/ScimTokenBase.cs similarity index 100% rename from src/Auth0.ManagementApi/Models/ScimTokenBase.cs rename to src/Auth0.ManagementApi/Models/Scim/ScimTokenBase.cs diff --git a/src/Auth0.ManagementApi/Models/ScimTokenCreateRequest.cs b/src/Auth0.ManagementApi/Models/Scim/ScimTokenCreateRequest.cs similarity index 100% rename from src/Auth0.ManagementApi/Models/ScimTokenCreateRequest.cs rename to src/Auth0.ManagementApi/Models/Scim/ScimTokenCreateRequest.cs diff --git a/src/Auth0.ManagementApi/Models/ScimTokenCreateResponse.cs b/src/Auth0.ManagementApi/Models/Scim/ScimTokenCreateResponse.cs similarity index 100% rename from src/Auth0.ManagementApi/Models/ScimTokenCreateResponse.cs rename to src/Auth0.ManagementApi/Models/Scim/ScimTokenCreateResponse.cs