diff --git a/notes.txt b/notes.txt index 59bc186..a96bf2b 100644 --- a/notes.txt +++ b/notes.txt @@ -4,6 +4,20 @@ TODO: - https://github.com/openiddict/openiddict-samples/tree/dev/samples/Contruum/Contruum.Server +- migrate to .net Program.cs file + - refactor DB-migrations in sample server + + +- load options.Permissions from database instead of configuring it + + +- client refactoring + - split identity, openiddict => create libs + - better Client deployment + - introduce deploy.js + - check server stylings not removed + + - organize APIs a bit more by feature - i.e. identity -> AccountController - AccountController @@ -36,14 +50,6 @@ TODO: - PolicyClient -- load options.Permissions from database instead of configuring it - - -- better Client deployment - - introduce deploy.js - - check server stylings not removed - - - better ux for applications.permissions - sth. like the approach of OrchardCore ID UI diff --git a/src/identity/OpenIddict.UI.Identity.Api/Account/AccountController.cs b/src/identity/OpenIddict.UI.Identity.Api/Account/AccountController.cs index 458ef73..f6f0b00 100644 --- a/src/identity/OpenIddict.UI.Identity.Api/Account/AccountController.cs +++ b/src/identity/OpenIddict.UI.Identity.Api/Account/AccountController.cs @@ -3,13 +3,11 @@ using Microsoft.AspNetCore.Mvc; using System.Collections.Generic; using System.Threading.Tasks; -using tomware.OpenIddict.UI.Suite.Api; namespace tomware.OpenIddict.UI.Identity.Api { [Route("accounts")] - [ApiExplorerSettings(GroupName = "openiddict-ui-identity")] - public class AccountController : ApiControllerBase + public class AccountController : IdentityApiController { private readonly IAccountApiService _service; @@ -41,7 +39,7 @@ public async Task Register([FromBody] RegisterUserViewModel model [HttpPost("changepassword")] [ProducesResponseType(typeof(IdentityResult), StatusCodes.Status200OK)] - public async Task ChangePassword([FromBody]ChangePasswordViewModel model) + public async Task ChangePassword([FromBody] ChangePasswordViewModel model) { if (model == null) return BadRequest(); if (ModelState.IsValid) diff --git a/src/identity/OpenIddict.UI.Identity.Api/ClaimType/ClaimTypeController.cs b/src/identity/OpenIddict.UI.Identity.Api/ClaimType/ClaimTypeController.cs index ff2c4ff..2572094 100644 --- a/src/identity/OpenIddict.UI.Identity.Api/ClaimType/ClaimTypeController.cs +++ b/src/identity/OpenIddict.UI.Identity.Api/ClaimType/ClaimTypeController.cs @@ -3,13 +3,11 @@ using System; using System.Collections.Generic; using System.Threading.Tasks; -using tomware.OpenIddict.UI.Suite.Api; namespace tomware.OpenIddict.UI.Identity.Api { [Route("claimtypes")] - [ApiExplorerSettings(GroupName = "openiddict-ui-identity")] - public class ClaimTypeController : ApiControllerBase + public class ClaimTypeController : IdentityApiController { private readonly IClaimTypeApiService _service; diff --git a/src/identity/OpenIddict.UI.Identity.Api/Common/Constants.cs b/src/identity/OpenIddict.UI.Identity.Api/Common/Constants.cs new file mode 100644 index 0000000..fc13f5f --- /dev/null +++ b/src/identity/OpenIddict.UI.Identity.Api/Common/Constants.cs @@ -0,0 +1,12 @@ +namespace tomware.OpenIddict.UI.Identity.Api +{ + public static class Policies + { + public const string OPENIDDICT_UI_IDENTITY_API_POLICY = "OpenIddictUiIdentityApiPolicy"; + } + + public static class ApiGroups + { + public const string OPENIDDICT_UI_IDENTITY_GROUP = "openiddict-ui-identity"; + } +} \ No newline at end of file diff --git a/src/identity/OpenIddict.UI.Identity.Api/Common/IdentityApiController.cs b/src/identity/OpenIddict.UI.Identity.Api/Common/IdentityApiController.cs new file mode 100644 index 0000000..eb139b7 --- /dev/null +++ b/src/identity/OpenIddict.UI.Identity.Api/Common/IdentityApiController.cs @@ -0,0 +1,16 @@ +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Mvc; +using OpenIddict.Validation.AspNetCore; +using tomware.OpenIddict.UI.Suite.Api; + +namespace tomware.OpenIddict.UI.Identity.Api +{ + [ApiExplorerSettings(GroupName = ApiGroups.OPENIDDICT_UI_IDENTITY_GROUP)] + [Authorize( + Policies.OPENIDDICT_UI_IDENTITY_API_POLICY, + AuthenticationSchemes = OpenIddictValidationAspNetCoreDefaults.AuthenticationScheme + )] + public class IdentityApiController : ApiControllerBase + { + } +} \ No newline at end of file diff --git a/src/identity/OpenIddict.UI.Identity.Api/DependencyInjection.cs b/src/identity/OpenIddict.UI.Identity.Api/DependencyInjection.cs index 0be3eea..81f1927 100644 --- a/src/identity/OpenIddict.UI.Identity.Api/DependencyInjection.cs +++ b/src/identity/OpenIddict.UI.Identity.Api/DependencyInjection.cs @@ -3,8 +3,7 @@ using System.Diagnostics.CodeAnalysis; using Microsoft.AspNetCore.Identity; using Microsoft.Extensions.DependencyInjection; - -using tomware.OpenIddict.UI.Suite.Core; +using Microsoft.AspNetCore.Authorization; using tomware.OpenIddict.UI.Suite.Api; namespace tomware.OpenIddict.UI.Identity.Api @@ -23,6 +22,8 @@ public static OpenIddictBuilder AddUIIdentityApis( builder.Services.AddApiServices(); + builder.Services.AddAuthorizationServices(options.Policy); + return builder; } @@ -48,22 +49,19 @@ this IServiceCollection services services.AddTransient(); services.AddTransient(); - services.AddAuthorizationServices(); - return services; } private static IServiceCollection AddAuthorizationServices( - this IServiceCollection services + this IServiceCollection services, + Action policy ) { services.AddAuthorization(options => { options.AddPolicy( - Policies.ADMIN_POLICY, - policy => policy - .RequireAuthenticatedUser() - .RequireRole(Roles.ADMINISTRATOR_ROLE) + Policies.OPENIDDICT_UI_IDENTITY_API_POLICY, + policy ); }); diff --git a/src/identity/OpenIddict.UI.Identity.Api/Options/OpenIddictUIIdentityApiOptions.cs b/src/identity/OpenIddict.UI.Identity.Api/Options/OpenIddictUIIdentityApiOptions.cs index a108f11..a737cd2 100644 --- a/src/identity/OpenIddict.UI.Identity.Api/Options/OpenIddictUIIdentityApiOptions.cs +++ b/src/identity/OpenIddict.UI.Identity.Api/Options/OpenIddictUIIdentityApiOptions.cs @@ -1,3 +1,7 @@ +using System; +using Microsoft.AspNetCore.Authorization; +using tomware.OpenIddict.UI.Suite.Core; + namespace tomware.OpenIddict.UI.Identity.Api { public class OpenIddictUIIdentityApiOptions @@ -6,5 +10,20 @@ public class OpenIddictUIIdentityApiOptions /// Registers a conventional route prefix for the API controllers. Defaults to "api/". /// public string RoutePrefix { get; set; } = "api/"; + + /// + /// Allows to register custom authorization policies for accessing OpenIddict-UI Identity API's. + /// Defaults to: + /// + /// policy + /// .RequireAuthenticatedUser() + /// .RequireRole(Roles.ADMINISTRATOR_ROLE); + /// + /// + /// + public Action Policy { get; set; } = policy => + policy + .RequireAuthenticatedUser() + .RequireRole(Roles.ADMINISTRATOR_ROLE); } } \ No newline at end of file diff --git a/src/identity/OpenIddict.UI.Identity.Api/Role/RoleController.cs b/src/identity/OpenIddict.UI.Identity.Api/Role/RoleController.cs index 8169ec6..9731602 100644 --- a/src/identity/OpenIddict.UI.Identity.Api/Role/RoleController.cs +++ b/src/identity/OpenIddict.UI.Identity.Api/Role/RoleController.cs @@ -2,13 +2,11 @@ using Microsoft.AspNetCore.Mvc; using System.Collections.Generic; using System.Threading.Tasks; -using tomware.OpenIddict.UI.Suite.Api; namespace tomware.OpenIddict.UI.Identity.Api { [Route("roles")] - [ApiExplorerSettings(GroupName = "openiddict-ui-identity")] - public class RoleController : ApiControllerBase + public class RoleController : IdentityApiController { private readonly IRoleService _service; diff --git a/src/openiddict/OpenIddict.UI.Api/Application/ApplicationController.cs b/src/openiddict/OpenIddict.UI.Api/Application/ApplicationController.cs index b87fc67..8c9df44 100644 --- a/src/openiddict/OpenIddict.UI.Api/Application/ApplicationController.cs +++ b/src/openiddict/OpenIddict.UI.Api/Application/ApplicationController.cs @@ -3,13 +3,11 @@ using Microsoft.AspNetCore.Mvc; using System.Collections.Generic; using System.Threading.Tasks; -using tomware.OpenIddict.UI.Suite.Api; namespace tomware.OpenIddict.UI.Api { [Route("application")] - [ApiExplorerSettings(GroupName = "openiddict-ui-api")] - public class ApplicationController : ApiControllerBase + public class ApplicationController : OpenIddictApiController { private readonly IApplicationApiService _service; diff --git a/src/openiddict/OpenIddict.UI.Api/Common/Constants.cs b/src/openiddict/OpenIddict.UI.Api/Common/Constants.cs new file mode 100644 index 0000000..69bdc97 --- /dev/null +++ b/src/openiddict/OpenIddict.UI.Api/Common/Constants.cs @@ -0,0 +1,12 @@ +namespace tomware.OpenIddict.UI.Api +{ + public static class Policies + { + public const string OPENIDDICT_UI_API_POLICY = "OpenIddictUiApiPolicy"; + } + + public static class ApiGroups + { + public const string OPENIDDICT_UI_GROUP = "openiddict-ui-api"; + } +} \ No newline at end of file diff --git a/src/openiddict/OpenIddict.UI.Api/Common/OpenIddictApiController.cs b/src/openiddict/OpenIddict.UI.Api/Common/OpenIddictApiController.cs new file mode 100644 index 0000000..51d2744 --- /dev/null +++ b/src/openiddict/OpenIddict.UI.Api/Common/OpenIddictApiController.cs @@ -0,0 +1,16 @@ +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Mvc; +using OpenIddict.Validation.AspNetCore; +using tomware.OpenIddict.UI.Suite.Api; + +namespace tomware.OpenIddict.UI.Api +{ + [ApiExplorerSettings(GroupName = ApiGroups.OPENIDDICT_UI_GROUP)] + [Authorize( + Policies.OPENIDDICT_UI_API_POLICY, + AuthenticationSchemes = OpenIddictValidationAspNetCoreDefaults.AuthenticationScheme + )] + public class OpenIddictApiController : ApiControllerBase + { + } +} \ No newline at end of file diff --git a/src/openiddict/OpenIddict.UI.Api/DependencyInjection.cs b/src/openiddict/OpenIddict.UI.Api/DependencyInjection.cs index 735aebe..2d024cd 100644 --- a/src/openiddict/OpenIddict.UI.Api/DependencyInjection.cs +++ b/src/openiddict/OpenIddict.UI.Api/DependencyInjection.cs @@ -1,80 +1,78 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics.CodeAnalysis; -using Microsoft.Extensions.DependencyInjection; - -using tomware.OpenIddict.UI.Suite.Core; -using tomware.OpenIddict.UI.Suite.Api; - -namespace tomware.OpenIddict.UI.Api -{ - [ExcludeFromCodeCoverage] - public static class OpenIddictUIServicesExtensions - { - /// - /// Register the Api for the EF based UI Store. - /// - public static OpenIddictBuilder AddUIApis( - this OpenIddictBuilder builder, - Action uiApiOptions = null - ) - { - var options = new OpenIddictUIApiOptions(); - uiApiOptions?.Invoke(options); - builder.AddRoutePrefix(options.RoutePrefix); - - builder.Services.AddApiServices(uiApiOptions); - - return builder; - } - - private static IServiceCollection AddApiServices( - this IServiceCollection services, - Action options = null - ) - { - services.Configure(options); - - services.AddTransient(); - services.AddTransient(); - - services.AddAuthorizationServices(); - - return services; - } - - private static IServiceCollection AddAuthorizationServices( - this IServiceCollection services - ) - { - services.AddAuthorization(options => - { - options.AddPolicy( - Policies.ADMIN_POLICY, - policy => policy - .RequireAuthenticatedUser() - .RequireRole(Roles.ADMINISTRATOR_ROLE) - ); - }); - - return services; - } - - private static OpenIddictBuilder AddRoutePrefix( - this OpenIddictBuilder builder, - string routePrefix - ) - { - builder.Services.AddControllers(options => - { - options.UseOpenIddictUIRoutePrefix(routePrefix, new List - { - typeof(ApplicationController), - typeof(ScopeController) - }); - }); - - return builder; - } - } +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using Microsoft.AspNetCore.Authorization; +using Microsoft.Extensions.DependencyInjection; +using tomware.OpenIddict.UI.Suite.Api; + +namespace tomware.OpenIddict.UI.Api +{ + [ExcludeFromCodeCoverage] + public static class OpenIddictUIServicesExtensions + { + /// + /// Register the Api for the EF based UI Store. + /// + public static OpenIddictBuilder AddUIApis( + this OpenIddictBuilder builder, + Action uiApiOptions = null + ) + { + var options = new OpenIddictUIApiOptions(); + uiApiOptions?.Invoke(options); + builder.AddRoutePrefix(options.RoutePrefix); + + builder.Services.AddApiServices(uiApiOptions); + + builder.Services.AddAuthorizationServices(options.Policy); + + return builder; + } + + private static IServiceCollection AddApiServices( + this IServiceCollection services, + Action options = null + ) + { + services.Configure(options); + + services.AddTransient(); + services.AddTransient(); + + return services; + } + + private static IServiceCollection AddAuthorizationServices( + this IServiceCollection services, + Action policy + ) + { + services.AddAuthorization(options => + { + options.AddPolicy( + Policies.OPENIDDICT_UI_API_POLICY, + policy + ); + }); + + return services; + } + + private static OpenIddictBuilder AddRoutePrefix( + this OpenIddictBuilder builder, + string routePrefix + ) + { + builder.Services.AddControllers(options => + { + options.UseOpenIddictUIRoutePrefix(routePrefix, new List + { + typeof(ApplicationController), + typeof(ScopeController) + }); + }); + + return builder; + } + } } \ No newline at end of file diff --git a/src/openiddict/OpenIddict.UI.Api/Options/OpenIddictUIApiOptions.cs b/src/openiddict/OpenIddict.UI.Api/Options/OpenIddictUIApiOptions.cs index 9d2bd7f..0bd63ae 100644 --- a/src/openiddict/OpenIddict.UI.Api/Options/OpenIddictUIApiOptions.cs +++ b/src/openiddict/OpenIddict.UI.Api/Options/OpenIddictUIApiOptions.cs @@ -1,4 +1,7 @@ +using System; using System.Collections.Generic; +using Microsoft.AspNetCore.Authorization; +using tomware.OpenIddict.UI.Suite.Core; namespace tomware.OpenIddict.UI.Api { @@ -13,5 +16,21 @@ public class OpenIddictUIApiOptions /// Registers a conventional route prefix for the API controllers. Defaults to "api/". /// public string RoutePrefix { get; set; } = "api/"; + + /// + /// Allows to register custom authorization policies for accessing OpenIddict-UI API's. + /// Defaults to: + /// + /// policy + /// .RequireAuthenticatedUser() + /// .RequireRole(Roles.ADMINISTRATOR_ROLE); + /// + /// + /// + /// + public Action Policy { get; set; } = policy => + policy + .RequireAuthenticatedUser() + .RequireRole(Roles.ADMINISTRATOR_ROLE); } } \ No newline at end of file diff --git a/src/openiddict/OpenIddict.UI.Api/Scope/ScopeController.cs b/src/openiddict/OpenIddict.UI.Api/Scope/ScopeController.cs index d31e286..fd8e575 100644 --- a/src/openiddict/OpenIddict.UI.Api/Scope/ScopeController.cs +++ b/src/openiddict/OpenIddict.UI.Api/Scope/ScopeController.cs @@ -2,13 +2,11 @@ using Microsoft.AspNetCore.Mvc; using System.Collections.Generic; using System.Threading.Tasks; -using tomware.OpenIddict.UI.Suite.Api; namespace tomware.OpenIddict.UI.Api { [Route("scopes")] - [ApiExplorerSettings(GroupName = "openiddict-ui-api")] - public class ScopeController : ApiControllerBase + public class ScopeController : OpenIddictApiController { private readonly IScopeApiService _service; diff --git a/src/suite/OpenIddict.UI.Suite.Api/Controllers/ApiControllerBase.cs b/src/suite/OpenIddict.UI.Suite.Api/Controllers/ApiControllerBase.cs index f1bd8a6..aeebe65 100644 --- a/src/suite/OpenIddict.UI.Suite.Api/Controllers/ApiControllerBase.cs +++ b/src/suite/OpenIddict.UI.Suite.Api/Controllers/ApiControllerBase.cs @@ -1,15 +1,8 @@ -using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; -using OpenIddict.Validation.AspNetCore; using System.Net.Mime; -using tomware.OpenIddict.UI.Suite.Core; namespace tomware.OpenIddict.UI.Suite.Api { - [Authorize( - Policies.ADMIN_POLICY, - AuthenticationSchemes = OpenIddictValidationAspNetCoreDefaults.AuthenticationScheme - )] [Produces(MediaTypeNames.Application.Json)] public class ApiControllerBase : ControllerBase { diff --git a/src/suite/OpenIddict.UI.Suite.Core/Common/Constants.cs b/src/suite/OpenIddict.UI.Suite.Core/Common/Constants.cs index efdef72..2344960 100644 --- a/src/suite/OpenIddict.UI.Suite.Core/Common/Constants.cs +++ b/src/suite/OpenIddict.UI.Suite.Core/Common/Constants.cs @@ -1,10 +1,5 @@ namespace tomware.OpenIddict.UI.Suite.Core { - public static class Policies - { - public const string ADMIN_POLICY = "AdministratorPolicy"; - } - public static class Roles { public const string ADMINISTRATOR_ROLE = "Administrator";