From 63346f0b7d33c175121f7da3eed0c31a077c7d14 Mon Sep 17 00:00:00 2001 From: Stuart Ferguson Date: Wed, 9 Jun 2021 22:50:37 +0100 Subject: [PATCH 01/49] Upgrade to Identity Server v5 --- .dockerignore | 34 +- README.md | 19 - .../Exceptions/IdentityResultException.cs | 2 +- .../Extensions.cs | 2 +- .../ISecurityServiceManager.cs | 550 +- .../SecurityService.BusinessLogic.csproj | 24 + .../Requests/CreateClientRequest.cs | 4 - .../Requests/CreateRoleRequest.cs | 2 - .../Requests/CreateUserRequest.cs | 6 - ...SecurityService.DataTransferObjects.csproj | 11 +- .../DbContexts/AuthenticationDbContext.cs | 45 +- ...210607111618_InitialMigration.Designer.cs} | 172 +- .../20210607111618_InitialMigration.cs} | 84 +- .../AuthenticationDbContextModelSnapshot.cs | 162 +- ...210607105411_InitialMigration.Designer.cs} | 223 +- .../20210607105411_InitialMigration.cs | 678 + .../ConfigurationDbContextModelSnapshot.cs | 216 +- ...91105215403_InitialDbMigration.Designer.cs | 837 -- .../20191105215403_InitialDbMigration.cs | 607 - .../20210118212226_Identityv4.cs | 502 - ...210607105327_InitialMigration.Designer.cs} | 68 +- .../20210607105327_InitialMigration.cs | 116 + .../PersistedGrantDbContextModelSnapshot.cs | 62 +- ...91105215225_InitialDbMigration.Designer.cs | 110 - .../20191105215225_InitialDbMigration.cs | 75 - .../20210118212333_Identityv4.cs | 77 - .../SecurityService.Database.csproj | 33 +- .../Seeding/DatabaseSeeding.cs | 134 - .../Seeding/SeedingType.cs | 11 - .../Clients/Clients.feature.cs | 10 +- .../Common/DockerHelper.cs | 8 +- .../ISecurityServiceManager.cs | 247 - .../SecurityService.Manager.csproj | 37 - SecurityService.Models/AccountOptions.cs | 3 - SecurityService.Models/ConsentOptions.cs | 3 - SecurityService.Models/RoleDetails.cs | 9 +- .../SecurityService.Models.csproj | 2 +- SecurityService.Models/UserDetails.cs | 8 +- .../Common/DockerHelper.cs | 33 +- .../Common/Hooks.cs | 18 +- .../Common/SharedSteps.cs | 4 +- .../UserLogin/UserLogin.feature | 2 +- .../UserLogin/UserLogin.feature.cs | 4 +- .../UserLogin/UserLoginSteps.cs | 6 +- .../BootstrapperTests.cs | 4 +- .../ModelFactoryTests.cs | 2 +- .../SecurityService.UnitTests.csproj | 2 +- .../SecurityServiceManagerTestSetup.cs | 8 +- .../SecurityServiceManagerTests.cs | 24 +- SecurityService.sln | 128 +- SecurityService/Common/StartupExtensions.cs | 2 +- SecurityService/Config.cs | 116 + .../Controllers/Account/AccountController.cs | 461 +- .../Controllers/Account/ExternalController.cs | 345 +- .../Controllers/ApiResourceController.cs | 4 +- .../Controllers/ApiScopeController.cs | 4 +- .../Controllers/ClientController.cs | 4 +- .../Controllers/Consent/ConsentController.cs | 396 +- .../Controllers/Device/DeviceController.cs | 407 +- .../Diagnostics/DiagnosticsController.cs | 61 +- SecurityService/Controllers/Extensions.cs | 6 +- .../Controllers/Grants/GrantsController.cs | 158 +- .../Controllers/Home/HomeController.cs | 59 +- .../Controllers/IdentityResourceController.cs | 4 +- SecurityService/Controllers/RoleController.cs | 2 +- SecurityService/Controllers/UserController.cs | 2 +- SecurityService/Dockerfile | 2 +- SecurityService/DockerfileWindows | 2 +- SecurityService/Extensions.cs | 31 + SecurityService/Extensions/Extensions.cs | 28 - SecurityService/Factories/IModelFactory.cs | 2 +- SecurityService/Factories/ModelFactory.cs | 2 +- SecurityService/Program.cs | 54 +- SecurityService/SecurityHeadersAttribute.cs | 56 + SecurityService/SecurityService.csproj | 92 +- SecurityService/SecurityService.xml | 1672 --- SecurityService/Startup.cs | 341 +- SecurityService/UpdateUI.ps1 | 40 + .../ViewModels/Account/AccountOptions.cs | 20 + .../ViewModels/Account/ExternalProvider.cs | 12 + .../{ => Account}/LoggedOutViewModel.cs | 11 +- .../ViewModels/Account/LoginInputModel.cs | 18 + .../ViewModels/Account/LoginViewModel.cs | 22 + .../ViewModels/Account/LogoutInputModel.cs | 11 + .../ViewModels/Account/LogoutViewModel.cs | 11 + .../ViewModels/Account/RedirectViewModel.cs | 12 + .../ViewModels/Consent/ConsentInputModel.cs | 17 + .../ViewModels/Consent/ConsentOptions.cs | 16 + .../{ => Consent}/ConsentViewModel.cs | 13 +- .../{ => Consent}/ProcessConsentResult.cs | 12 +- .../ViewModels/Consent/ResourceViewModel.cs | 12 + .../{ => Consent}/ScopeViewModel.cs | 13 +- .../ViewModels/ConsentInputModel.cs | 18 - .../Device/DeviceAuthorizationInputModel.cs | 11 + .../Device/DeviceAuthorizationViewModel.cs | 12 + .../DeviceAuthorizationInputModel.cs | 14 - .../DeviceAuthorizationViewModel.cs | 15 - .../Diagnostics/DiagnosticsViewModel.cs | 32 + .../ViewModels/DiagnosticsViewModel.cs | 34 - SecurityService/ViewModels/ErrorViewModel.cs | 23 - .../ViewModels/ExternalProvider.cs | 15 - .../GrantsViewModel.cs} | 17 +- SecurityService/ViewModels/GrantsViewModel.cs | 14 - .../ViewModels/Home/ErrorViewModel.cs | 22 + SecurityService/ViewModels/LoginInputModel.cs | 19 - SecurityService/ViewModels/LoginViewModel.cs | 23 - .../ViewModels/LogoutInputModel.cs | 14 - SecurityService/ViewModels/LogoutViewModel.cs | 14 - .../ViewModels/RedirectViewModel.cs | 15 - .../Views/Account/LoggedOut.cshtml | 2 +- SecurityService/Views/Account/Login.cshtml | 2 +- SecurityService/Views/Account/Logout.cshtml | 4 +- SecurityService/Views/Consent/Index.cshtml | 6 +- .../Views/Device/UserCodeConfirmation.cshtml | 2 +- .../Views/Diagnostics/Index.cshtml | 2 +- SecurityService/Views/Grants/Index.cshtml | 2 +- SecurityService/Views/Home/Index.cshtml | 12 +- SecurityService/Views/Shared/Error.cshtml | 2 +- SecurityService/Views/Shared/Redirect.cshtml | 2 +- SecurityService/Views/Shared/_Layout.cshtml | 3 +- SecurityService/Views/Shared/_Nav.cshtml | 7 +- .../Views/Shared/_ScopeListItem.cshtml | 14 +- SecurityService/Views/_ViewImports.cshtml | 3 +- SecurityService/appsettings.json | 40 +- SecurityService/bundleconfig.json | 14 - SecurityService/ca.tf | 27 - SecurityService/hosting.json | 4 +- ...-key-7B5CA49B919774AC72B8177C782E2F1F.json | 1 + SecurityService/tempkey.jwk | 1 - SecurityService/tempkey.rsa | 1 - SecurityService/wwwroot/css/site.css | 106 +- SecurityService/wwwroot/css/site.less | 116 - SecurityService/wwwroot/css/site.min.css | 2 +- SecurityService/wwwroot/css/site.scss | 51 + SecurityService/wwwroot/duende-logo.svg | 1 + SecurityService/wwwroot/favicon.ico | Bin 1150 -> 15406 bytes SecurityService/wwwroot/icon.jpg | Bin 19482 -> 0 bytes SecurityService/wwwroot/icon.png | Bin 20796 -> 0 bytes SecurityService/wwwroot/lib/bootstrap/LICENSE | 22 + .../wwwroot/lib/bootstrap/README.md | 209 + .../wwwroot/lib/bootstrap/css/bootstrap.css | 6800 ---------- .../lib/bootstrap/css/bootstrap.css.map | 1 - .../lib/bootstrap/css/bootstrap.min.css | 5 - .../lib/bootstrap/dist/css/bootstrap-grid.css | 3872 ++++++ .../bootstrap/dist/css/bootstrap-grid.css.map | 1 + .../bootstrap/dist/css/bootstrap-grid.min.css | 7 + .../dist/css/bootstrap-grid.min.css.map | 1 + .../bootstrap/dist/css/bootstrap-reboot.css | 326 + .../dist/css/bootstrap-reboot.css.map | 1 + .../dist/css/bootstrap-reboot.min.css | 8 + .../dist/css/bootstrap-reboot.min.css.map | 1 + .../lib/bootstrap/dist/css/bootstrap.css | 10263 +++++++++++++++ .../lib/bootstrap/dist/css/bootstrap.css.map | 1 + .../lib/bootstrap/dist/css/bootstrap.min.css | 7 + .../bootstrap/dist/css/bootstrap.min.css.map | 1 + .../lib/bootstrap/dist/js/bootstrap.bundle.js | 7031 ++++++++++ .../bootstrap/dist/js/bootstrap.bundle.js.map | 1 + .../bootstrap/dist/js/bootstrap.bundle.min.js | 7 + .../dist/js/bootstrap.bundle.min.js.map | 1 + .../lib/bootstrap/dist/js/bootstrap.js | 4418 +++++++ .../lib/bootstrap/dist/js/bootstrap.js.map | 1 + .../lib/bootstrap/dist/js/bootstrap.min.js | 7 + .../bootstrap/dist/js/bootstrap.min.js.map | 1 + .../wwwroot/lib/bootstrap/js/bootstrap.js | 2363 ---- .../wwwroot/lib/bootstrap/js/bootstrap.min.js | 7 - .../wwwroot/lib/bootstrap4-glyphicons/LICENSE | 201 + .../css/bootstrap-glyphicons.css | 809 ++ .../css/bootstrap-glyphicons.min.css | 6 + .../glyphicons-halflings-regular.eot | Bin .../glyphicons-halflings-regular.svg | 0 .../glyphicons-halflings-regular.ttf | Bin .../glyphicons-halflings-regular.woff | Bin .../glyphicons-halflings-regular.woff2 | Bin .../maps/glyphicons-fontawesome.css | 2947 +++++ .../maps/glyphicons-fontawesome.less | 3891 ++++++ .../maps/glyphicons-fontawesome.min.css | 1 + .../wwwroot/lib/jquery/LICENSE.txt | 20 + SecurityService/wwwroot/lib/jquery/README.md | 62 + .../wwwroot/lib/jquery/dist/jquery.js | 1792 ++- .../wwwroot/lib/jquery/dist/jquery.min.js | 2 + .../wwwroot/lib/jquery/dist/jquery.min.map | 1 + .../wwwroot/lib/jquery/dist/jquery.slim.js | 8777 +++++++++++++ .../lib/jquery/dist/jquery.slim.min.js | 2 + .../lib/jquery/dist/jquery.slim.min.map | 1 + .../wwwroot/lib/jquery/jquery.min.js | 5 - .../wwwroot/lib/jquery/jquery.min.map | 1 - .../Controllers/HomeController.cs | 10 +- SecurityServiceTestUI/Dockerfile | 26 + .../DockerfileWindows | 0 .../Models/ErrorViewModel.cs | 2 +- .../Program.cs | 25 +- .../SecurityServiceTestUI.csproj | 20 + SecurityServiceTestUI/Startup.cs | 113 + SecurityServiceTestUI/Views/Home/Index.cshtml | 26 + .../Views/Home/Privacy.cshtml | 0 .../Views/Shared/Error.cshtml | 0 .../Views/Shared/_Layout.cshtml | 10 +- .../Shared/_ValidationScriptsPartial.cshtml | 0 .../Views/_ViewImports.cshtml | 3 + .../Views/_ViewStart.cshtml | 0 .../appsettings.json | 6 +- SecurityServiceTestUI/aspnetapp-root-cert.cer | Bin 0 -> 820 bytes SecurityServiceTestUI/hosting.json | 3 + .../wwwroot/css/site.css | 0 SecurityServiceTestUI/wwwroot/favicon.ico | Bin 0 -> 5430 bytes .../wwwroot/js/site.js | 0 .../wwwroot/lib/bootstrap/LICENSE | 0 .../lib/bootstrap/dist/css/bootstrap-grid.css | 0 .../bootstrap/dist/css/bootstrap-grid.css.map | 0 .../bootstrap/dist/css/bootstrap-grid.min.css | 0 .../dist/css/bootstrap-grid.min.css.map | 0 .../bootstrap/dist/css/bootstrap-reboot.css | 0 .../dist/css/bootstrap-reboot.css.map | 0 .../dist/css/bootstrap-reboot.min.css | 0 .../dist/css/bootstrap-reboot.min.css.map | 0 .../lib/bootstrap/dist/css/bootstrap.css | 0 .../lib/bootstrap/dist/css/bootstrap.css.map | 0 .../lib/bootstrap/dist/css/bootstrap.min.css | 0 .../bootstrap/dist/css/bootstrap.min.css.map | 0 .../lib/bootstrap/dist/js/bootstrap.bundle.js | 0 .../bootstrap/dist/js/bootstrap.bundle.js.map | 0 .../bootstrap/dist/js/bootstrap.bundle.min.js | 0 .../dist/js/bootstrap.bundle.min.js.map | 0 .../lib/bootstrap/dist/js/bootstrap.js | 0 .../lib/bootstrap/dist/js/bootstrap.js.map | 0 .../lib/bootstrap/dist/js/bootstrap.min.js | 0 .../bootstrap/dist/js/bootstrap.min.js.map | 0 .../jquery-validation-unobtrusive/LICENSE.txt | 0 .../jquery.validate.unobtrusive.js | 0 .../jquery.validate.unobtrusive.min.js | 0 .../wwwroot/lib/jquery-validation/LICENSE.md | 0 .../dist/additional-methods.js | 0 .../dist/additional-methods.min.js | 0 .../jquery-validation/dist/jquery.validate.js | 0 .../dist/jquery.validate.min.js | 0 .../wwwroot/lib/jquery/LICENSE.txt | 0 .../wwwroot/lib/jquery/dist}/jquery.js | 10682 +++++++++------- .../wwwroot/lib/jquery/dist/jquery.min.js | 2 + .../wwwroot/lib/jquery/dist/jquery.min.map | 1 + SecurityServiceTestWebClient/Dockerfile | 20 - .../SecurityServiceTestWebClient.csproj | 30 - SecurityServiceTestWebClient/Startup.cs | 120 - .../TokenManagement/Extensions.cs | 254 - .../Views/Home/Index.cshtml | 8 - .../Views/_ViewImports.cshtml | 3 - SecurityServiceTestWebClient/hosting.json | 3 - .../wwwroot/favicon.ico | Bin 32038 -> 0 bytes .../wwwroot/lib/jquery/dist/jquery.min.js | 2 - .../wwwroot/lib/jquery/dist/jquery.min.map | 1 - lcov1.info | 523 - 250 files changed, 53904 insertions(+), 22590 deletions(-) delete mode 100644 README.md rename {SecurityService.Manager => SecurityService.BusinessLogic}/Exceptions/IdentityResultException.cs (96%) rename {SecurityService.Manager/Extensions => SecurityService.BusinessLogic}/Extensions.cs (96%) rename SecurityService.Manager/SecurityServiceManager.cs => SecurityService.BusinessLogic/ISecurityServiceManager.cs (78%) create mode 100644 SecurityService.BusinessLogic/SecurityService.BusinessLogic.csproj rename SecurityService.Database/Migrations/{AuthenticationDbContext/20191105215459_InitialDbMigration.Designer.cs => AuthenticationDb/20210607111618_InitialMigration.Designer.cs} (83%) rename SecurityService.Database/Migrations/{AuthenticationDbContext/20191105215459_InitialDbMigration.cs => AuthenticationDb/20210607111618_InitialMigration.cs} (63%) rename SecurityService.Database/Migrations/{AuthenticationDbContext => AuthenticationDb}/AuthenticationDbContextModelSnapshot.cs (89%) rename SecurityService.Database/Migrations/{ConfigurationDbContext/20210118212226_Identityv4.Designer.cs => ConfigurationDb/20210607105411_InitialMigration.Designer.cs} (72%) create mode 100644 SecurityService.Database/Migrations/ConfigurationDb/20210607105411_InitialMigration.cs rename SecurityService.Database/Migrations/{ConfigurationDbContext => ConfigurationDb}/ConfigurationDbContextModelSnapshot.cs (73%) delete mode 100644 SecurityService.Database/Migrations/ConfigurationDbContext/20191105215403_InitialDbMigration.Designer.cs delete mode 100644 SecurityService.Database/Migrations/ConfigurationDbContext/20191105215403_InitialDbMigration.cs delete mode 100644 SecurityService.Database/Migrations/ConfigurationDbContext/20210118212226_Identityv4.cs rename SecurityService.Database/Migrations/{PersistedGrantDbContext/20210118212333_Identityv4.Designer.cs => PersistedGrantDb/20210607105327_InitialMigration.Designer.cs} (65%) create mode 100644 SecurityService.Database/Migrations/PersistedGrantDb/20210607105327_InitialMigration.cs rename SecurityService.Database/Migrations/{PersistedGrantDbContext => PersistedGrantDb}/PersistedGrantDbContextModelSnapshot.cs (67%) delete mode 100644 SecurityService.Database/Migrations/PersistedGrantDbContext/20191105215225_InitialDbMigration.Designer.cs delete mode 100644 SecurityService.Database/Migrations/PersistedGrantDbContext/20191105215225_InitialDbMigration.cs delete mode 100644 SecurityService.Database/Migrations/PersistedGrantDbContext/20210118212333_Identityv4.cs delete mode 100644 SecurityService.Database/Seeding/DatabaseSeeding.cs delete mode 100644 SecurityService.Database/Seeding/SeedingType.cs delete mode 100644 SecurityService.Manager/ISecurityServiceManager.cs delete mode 100644 SecurityService.Manager/SecurityService.Manager.csproj create mode 100644 SecurityService/Config.cs create mode 100644 SecurityService/Extensions.cs delete mode 100644 SecurityService/Extensions/Extensions.cs create mode 100644 SecurityService/SecurityHeadersAttribute.cs delete mode 100644 SecurityService/SecurityService.xml create mode 100644 SecurityService/UpdateUI.ps1 create mode 100644 SecurityService/ViewModels/Account/AccountOptions.cs create mode 100644 SecurityService/ViewModels/Account/ExternalProvider.cs rename SecurityService/ViewModels/{ => Account}/LoggedOutViewModel.cs (50%) create mode 100644 SecurityService/ViewModels/Account/LoginInputModel.cs create mode 100644 SecurityService/ViewModels/Account/LoginViewModel.cs create mode 100644 SecurityService/ViewModels/Account/LogoutInputModel.cs create mode 100644 SecurityService/ViewModels/Account/LogoutViewModel.cs create mode 100644 SecurityService/ViewModels/Account/RedirectViewModel.cs create mode 100644 SecurityService/ViewModels/Consent/ConsentInputModel.cs create mode 100644 SecurityService/ViewModels/Consent/ConsentOptions.cs rename SecurityService/ViewModels/{ => Consent}/ConsentViewModel.cs (55%) rename SecurityService/ViewModels/{ => Consent}/ProcessConsentResult.cs (57%) create mode 100644 SecurityService/ViewModels/Consent/ResourceViewModel.cs rename SecurityService/ViewModels/{ => Consent}/ScopeViewModel.cs (51%) delete mode 100644 SecurityService/ViewModels/ConsentInputModel.cs create mode 100644 SecurityService/ViewModels/Device/DeviceAuthorizationInputModel.cs create mode 100644 SecurityService/ViewModels/Device/DeviceAuthorizationViewModel.cs delete mode 100644 SecurityService/ViewModels/DeviceAuthorizationInputModel.cs delete mode 100644 SecurityService/ViewModels/DeviceAuthorizationViewModel.cs create mode 100644 SecurityService/ViewModels/Diagnostics/DiagnosticsViewModel.cs delete mode 100644 SecurityService/ViewModels/DiagnosticsViewModel.cs delete mode 100644 SecurityService/ViewModels/ErrorViewModel.cs delete mode 100644 SecurityService/ViewModels/ExternalProvider.cs rename SecurityService/ViewModels/{GrantViewModel.cs => Grants/GrantsViewModel.cs} (61%) delete mode 100644 SecurityService/ViewModels/GrantsViewModel.cs create mode 100644 SecurityService/ViewModels/Home/ErrorViewModel.cs delete mode 100644 SecurityService/ViewModels/LoginInputModel.cs delete mode 100644 SecurityService/ViewModels/LoginViewModel.cs delete mode 100644 SecurityService/ViewModels/LogoutInputModel.cs delete mode 100644 SecurityService/ViewModels/LogoutViewModel.cs delete mode 100644 SecurityService/ViewModels/RedirectViewModel.cs delete mode 100644 SecurityService/bundleconfig.json delete mode 100644 SecurityService/ca.tf create mode 100644 SecurityService/keys/is-signing-key-7B5CA49B919774AC72B8177C782E2F1F.json delete mode 100644 SecurityService/tempkey.jwk delete mode 100644 SecurityService/tempkey.rsa delete mode 100644 SecurityService/wwwroot/css/site.less create mode 100644 SecurityService/wwwroot/css/site.scss create mode 100644 SecurityService/wwwroot/duende-logo.svg delete mode 100644 SecurityService/wwwroot/icon.jpg delete mode 100644 SecurityService/wwwroot/icon.png create mode 100644 SecurityService/wwwroot/lib/bootstrap/LICENSE create mode 100644 SecurityService/wwwroot/lib/bootstrap/README.md delete mode 100644 SecurityService/wwwroot/lib/bootstrap/css/bootstrap.css delete mode 100644 SecurityService/wwwroot/lib/bootstrap/css/bootstrap.css.map delete mode 100644 SecurityService/wwwroot/lib/bootstrap/css/bootstrap.min.css create mode 100644 SecurityService/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.css create mode 100644 SecurityService/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.css.map create mode 100644 SecurityService/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.min.css create mode 100644 SecurityService/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.min.css.map create mode 100644 SecurityService/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.css create mode 100644 SecurityService/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.css.map create mode 100644 SecurityService/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.min.css create mode 100644 SecurityService/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.min.css.map create mode 100644 SecurityService/wwwroot/lib/bootstrap/dist/css/bootstrap.css create mode 100644 SecurityService/wwwroot/lib/bootstrap/dist/css/bootstrap.css.map create mode 100644 SecurityService/wwwroot/lib/bootstrap/dist/css/bootstrap.min.css create mode 100644 SecurityService/wwwroot/lib/bootstrap/dist/css/bootstrap.min.css.map create mode 100644 SecurityService/wwwroot/lib/bootstrap/dist/js/bootstrap.bundle.js create mode 100644 SecurityService/wwwroot/lib/bootstrap/dist/js/bootstrap.bundle.js.map create mode 100644 SecurityService/wwwroot/lib/bootstrap/dist/js/bootstrap.bundle.min.js create mode 100644 SecurityService/wwwroot/lib/bootstrap/dist/js/bootstrap.bundle.min.js.map create mode 100644 SecurityService/wwwroot/lib/bootstrap/dist/js/bootstrap.js create mode 100644 SecurityService/wwwroot/lib/bootstrap/dist/js/bootstrap.js.map create mode 100644 SecurityService/wwwroot/lib/bootstrap/dist/js/bootstrap.min.js create mode 100644 SecurityService/wwwroot/lib/bootstrap/dist/js/bootstrap.min.js.map delete mode 100644 SecurityService/wwwroot/lib/bootstrap/js/bootstrap.js delete mode 100644 SecurityService/wwwroot/lib/bootstrap/js/bootstrap.min.js create mode 100644 SecurityService/wwwroot/lib/bootstrap4-glyphicons/LICENSE create mode 100644 SecurityService/wwwroot/lib/bootstrap4-glyphicons/css/bootstrap-glyphicons.css create mode 100644 SecurityService/wwwroot/lib/bootstrap4-glyphicons/css/bootstrap-glyphicons.min.css rename SecurityService/wwwroot/lib/{bootstrap/fonts => bootstrap4-glyphicons/fonts/glyphicons}/glyphicons-halflings-regular.eot (100%) rename SecurityService/wwwroot/lib/{bootstrap/fonts => bootstrap4-glyphicons/fonts/glyphicons}/glyphicons-halflings-regular.svg (100%) rename SecurityService/wwwroot/lib/{bootstrap/fonts => bootstrap4-glyphicons/fonts/glyphicons}/glyphicons-halflings-regular.ttf (100%) rename SecurityService/wwwroot/lib/{bootstrap/fonts => bootstrap4-glyphicons/fonts/glyphicons}/glyphicons-halflings-regular.woff (100%) rename SecurityService/wwwroot/lib/{bootstrap/fonts => bootstrap4-glyphicons/fonts/glyphicons}/glyphicons-halflings-regular.woff2 (100%) create mode 100644 SecurityService/wwwroot/lib/bootstrap4-glyphicons/maps/glyphicons-fontawesome.css create mode 100644 SecurityService/wwwroot/lib/bootstrap4-glyphicons/maps/glyphicons-fontawesome.less create mode 100644 SecurityService/wwwroot/lib/bootstrap4-glyphicons/maps/glyphicons-fontawesome.min.css create mode 100644 SecurityService/wwwroot/lib/jquery/LICENSE.txt create mode 100644 SecurityService/wwwroot/lib/jquery/README.md rename {SecurityServiceTestWebClient => SecurityService}/wwwroot/lib/jquery/dist/jquery.js (86%) create mode 100644 SecurityService/wwwroot/lib/jquery/dist/jquery.min.js create mode 100644 SecurityService/wwwroot/lib/jquery/dist/jquery.min.map create mode 100644 SecurityService/wwwroot/lib/jquery/dist/jquery.slim.js create mode 100644 SecurityService/wwwroot/lib/jquery/dist/jquery.slim.min.js create mode 100644 SecurityService/wwwroot/lib/jquery/dist/jquery.slim.min.map delete mode 100644 SecurityService/wwwroot/lib/jquery/jquery.min.js delete mode 100644 SecurityService/wwwroot/lib/jquery/jquery.min.map rename {SecurityServiceTestWebClient => SecurityServiceTestUI}/Controllers/HomeController.cs (86%) create mode 100644 SecurityServiceTestUI/Dockerfile rename {SecurityServiceTestWebClient => SecurityServiceTestUI}/DockerfileWindows (100%) rename {SecurityServiceTestWebClient => SecurityServiceTestUI}/Models/ErrorViewModel.cs (79%) rename {SecurityServiceTestWebClient => SecurityServiceTestUI}/Program.cs (69%) create mode 100644 SecurityServiceTestUI/SecurityServiceTestUI.csproj create mode 100644 SecurityServiceTestUI/Startup.cs create mode 100644 SecurityServiceTestUI/Views/Home/Index.cshtml rename {SecurityServiceTestWebClient => SecurityServiceTestUI}/Views/Home/Privacy.cshtml (100%) rename {SecurityServiceTestWebClient => SecurityServiceTestUI}/Views/Shared/Error.cshtml (100%) rename {SecurityServiceTestWebClient => SecurityServiceTestUI}/Views/Shared/_Layout.cshtml (85%) rename {SecurityServiceTestWebClient => SecurityServiceTestUI}/Views/Shared/_ValidationScriptsPartial.cshtml (100%) create mode 100644 SecurityServiceTestUI/Views/_ViewImports.cshtml rename {SecurityServiceTestWebClient => SecurityServiceTestUI}/Views/_ViewStart.cshtml (100%) rename {SecurityServiceTestWebClient => SecurityServiceTestUI}/appsettings.json (51%) create mode 100644 SecurityServiceTestUI/aspnetapp-root-cert.cer create mode 100644 SecurityServiceTestUI/hosting.json rename {SecurityServiceTestWebClient => SecurityServiceTestUI}/wwwroot/css/site.css (100%) create mode 100644 SecurityServiceTestUI/wwwroot/favicon.ico rename {SecurityServiceTestWebClient => SecurityServiceTestUI}/wwwroot/js/site.js (100%) rename {SecurityServiceTestWebClient => SecurityServiceTestUI}/wwwroot/lib/bootstrap/LICENSE (100%) rename {SecurityServiceTestWebClient => SecurityServiceTestUI}/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.css (100%) rename {SecurityServiceTestWebClient => SecurityServiceTestUI}/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.css.map (100%) rename {SecurityServiceTestWebClient => SecurityServiceTestUI}/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.min.css (100%) rename {SecurityServiceTestWebClient => SecurityServiceTestUI}/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.min.css.map (100%) rename {SecurityServiceTestWebClient => SecurityServiceTestUI}/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.css (100%) rename {SecurityServiceTestWebClient => SecurityServiceTestUI}/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.css.map (100%) rename {SecurityServiceTestWebClient => SecurityServiceTestUI}/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.min.css (100%) rename {SecurityServiceTestWebClient => SecurityServiceTestUI}/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.min.css.map (100%) rename {SecurityServiceTestWebClient => SecurityServiceTestUI}/wwwroot/lib/bootstrap/dist/css/bootstrap.css (100%) rename {SecurityServiceTestWebClient => SecurityServiceTestUI}/wwwroot/lib/bootstrap/dist/css/bootstrap.css.map (100%) rename {SecurityServiceTestWebClient => SecurityServiceTestUI}/wwwroot/lib/bootstrap/dist/css/bootstrap.min.css (100%) rename {SecurityServiceTestWebClient => SecurityServiceTestUI}/wwwroot/lib/bootstrap/dist/css/bootstrap.min.css.map (100%) rename {SecurityServiceTestWebClient => SecurityServiceTestUI}/wwwroot/lib/bootstrap/dist/js/bootstrap.bundle.js (100%) rename {SecurityServiceTestWebClient => SecurityServiceTestUI}/wwwroot/lib/bootstrap/dist/js/bootstrap.bundle.js.map (100%) rename {SecurityServiceTestWebClient => SecurityServiceTestUI}/wwwroot/lib/bootstrap/dist/js/bootstrap.bundle.min.js (100%) rename {SecurityServiceTestWebClient => SecurityServiceTestUI}/wwwroot/lib/bootstrap/dist/js/bootstrap.bundle.min.js.map (100%) rename {SecurityServiceTestWebClient => SecurityServiceTestUI}/wwwroot/lib/bootstrap/dist/js/bootstrap.js (100%) rename {SecurityServiceTestWebClient => SecurityServiceTestUI}/wwwroot/lib/bootstrap/dist/js/bootstrap.js.map (100%) rename {SecurityServiceTestWebClient => SecurityServiceTestUI}/wwwroot/lib/bootstrap/dist/js/bootstrap.min.js (100%) rename {SecurityServiceTestWebClient => SecurityServiceTestUI}/wwwroot/lib/bootstrap/dist/js/bootstrap.min.js.map (100%) rename {SecurityServiceTestWebClient => SecurityServiceTestUI}/wwwroot/lib/jquery-validation-unobtrusive/LICENSE.txt (100%) rename {SecurityServiceTestWebClient => SecurityServiceTestUI}/wwwroot/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.js (100%) rename {SecurityServiceTestWebClient => SecurityServiceTestUI}/wwwroot/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.min.js (100%) rename {SecurityServiceTestWebClient => SecurityServiceTestUI}/wwwroot/lib/jquery-validation/LICENSE.md (100%) rename {SecurityServiceTestWebClient => SecurityServiceTestUI}/wwwroot/lib/jquery-validation/dist/additional-methods.js (100%) rename {SecurityServiceTestWebClient => SecurityServiceTestUI}/wwwroot/lib/jquery-validation/dist/additional-methods.min.js (100%) rename {SecurityServiceTestWebClient => SecurityServiceTestUI}/wwwroot/lib/jquery-validation/dist/jquery.validate.js (100%) rename {SecurityServiceTestWebClient => SecurityServiceTestUI}/wwwroot/lib/jquery-validation/dist/jquery.validate.min.js (100%) rename {SecurityServiceTestWebClient => SecurityServiceTestUI}/wwwroot/lib/jquery/LICENSE.txt (100%) rename {SecurityService/wwwroot/lib/jquery => SecurityServiceTestUI/wwwroot/lib/jquery/dist}/jquery.js (51%) create mode 100644 SecurityServiceTestUI/wwwroot/lib/jquery/dist/jquery.min.js create mode 100644 SecurityServiceTestUI/wwwroot/lib/jquery/dist/jquery.min.map delete mode 100644 SecurityServiceTestWebClient/Dockerfile delete mode 100644 SecurityServiceTestWebClient/SecurityServiceTestWebClient.csproj delete mode 100644 SecurityServiceTestWebClient/Startup.cs delete mode 100644 SecurityServiceTestWebClient/TokenManagement/Extensions.cs delete mode 100644 SecurityServiceTestWebClient/Views/Home/Index.cshtml delete mode 100644 SecurityServiceTestWebClient/Views/_ViewImports.cshtml delete mode 100644 SecurityServiceTestWebClient/hosting.json delete mode 100644 SecurityServiceTestWebClient/wwwroot/favicon.ico delete mode 100644 SecurityServiceTestWebClient/wwwroot/lib/jquery/dist/jquery.min.js delete mode 100644 SecurityServiceTestWebClient/wwwroot/lib/jquery/dist/jquery.min.map delete mode 100644 lcov1.info diff --git a/.dockerignore b/.dockerignore index df2e0fe5..3729ff0c 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,9 +1,25 @@ -.dockerignore -.env -.git -.gitignore -.vs -.vscode -*/bin -*/obj -**/.toolstarget \ No newline at end of file +**/.classpath +**/.dockerignore +**/.env +**/.git +**/.gitignore +**/.project +**/.settings +**/.toolstarget +**/.vs +**/.vscode +**/*.*proj.user +**/*.dbmdl +**/*.jfm +**/azds.yaml +**/bin +**/charts +**/docker-compose* +**/Dockerfile* +**/node_modules +**/npm-debug.log +**/obj +**/secrets.dev.yaml +**/values.dev.yaml +LICENSE +README.md \ No newline at end of file diff --git a/README.md b/README.md deleted file mode 100644 index 1bdcd8b4..00000000 --- a/README.md +++ /dev/null @@ -1,19 +0,0 @@ -# SecurityService - -## Build Status - -[![Last Nightly Build Status Badge](https://github.com/TransactionProcessing/SecurityService/workflows/Nightly%20Build/badge.svg)](https://github.com/TransactionProcessing/SecurityService/workflows/Nightly%20Build/badge.svg) -[![Last Release Build Status Badge](https://github.com/StuartFerguson/TransactionProcessing/workflows/Release/badge.svg)](https://github.com/TransactionProcessing/SecurityService/workflows/Release/badge.svg) - -## Nuget Versions -||| -| --- | --- | -| **SecurityService.Client** | [![Security Service Client MyGet Badge](https://buildstats.info/myget/transactionprocessing/SecurityService.Client)](https://buildstats.info/myget/transactionprocessing/SecurityService.Client) | - -## Code Coverage Results - -[![Coverage Status](https://coveralls.io/repos/github/StuartFerguson/SecurityService/badge.svg?branch=master)](https://coveralls.io/github/StuartFerguson/SecurityService?branch=master) - -## Code Quality Results - -[![Codacy Badge](https://api.codacy.com/project/badge/Grade/98b769692f924c4e86923b2e924a065f)](https://www.codacy.com/manual/stuart_ferguson1/SecurityService?utm_source=github.com&utm_medium=referral&utm_content=TransactionProcessing/SecurityService&utm_campaign=Badge_Grade) diff --git a/SecurityService.Manager/Exceptions/IdentityResultException.cs b/SecurityService.BusinessLogic/Exceptions/IdentityResultException.cs similarity index 96% rename from SecurityService.Manager/Exceptions/IdentityResultException.cs rename to SecurityService.BusinessLogic/Exceptions/IdentityResultException.cs index 91c5b9dd..10ffdd07 100644 --- a/SecurityService.Manager/Exceptions/IdentityResultException.cs +++ b/SecurityService.BusinessLogic/Exceptions/IdentityResultException.cs @@ -1,4 +1,4 @@ -namespace SecurityService.Manager.Exceptions +namespace SecurityService.BusinessLogic.Exceptions { using System; using System.Diagnostics.CodeAnalysis; diff --git a/SecurityService.Manager/Extensions/Extensions.cs b/SecurityService.BusinessLogic/Extensions.cs similarity index 96% rename from SecurityService.Manager/Extensions/Extensions.cs rename to SecurityService.BusinessLogic/Extensions.cs index bc83d03f..b4c28264 100644 --- a/SecurityService.Manager/Extensions/Extensions.cs +++ b/SecurityService.BusinessLogic/Extensions.cs @@ -1,4 +1,4 @@ -namespace SecurityService.Manager.Extensions +namespace SecurityService.BusinessLogic { using System; using System.Collections.Generic; diff --git a/SecurityService.Manager/SecurityServiceManager.cs b/SecurityService.BusinessLogic/ISecurityServiceManager.cs similarity index 78% rename from SecurityService.Manager/SecurityServiceManager.cs rename to SecurityService.BusinessLogic/ISecurityServiceManager.cs index 0675f06e..4e3d6535 100644 --- a/SecurityService.Manager/SecurityServiceManager.cs +++ b/SecurityService.BusinessLogic/ISecurityServiceManager.cs @@ -1,29 +1,260 @@ -namespace SecurityService.Manager +using System; + +namespace SecurityService.BusinessLogic { - using System; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using System.Linq; + using System.Net.Mime; using System.Security.Claims; using System.Threading; using System.Threading.Tasks; + using Duende.IdentityServer.EntityFramework.DbContexts; + using Duende.IdentityServer.EntityFramework.Mappers; + using Duende.IdentityServer.Models; using Exceptions; - using Extensions; using IdentityModel; - using IdentityServer4.EntityFramework.DbContexts; - using IdentityServer4.EntityFramework.Mappers; - using IdentityServer4.Models; using Microsoft.AspNetCore.Identity; using Microsoft.EntityFrameworkCore; - using Models; + using SecurityService.Models; using Shared.Exceptions; using Shared.General; - /// - /// - /// - /// - /// + public class ApplicationUser : IdentityUser + { + } + + public interface ISecurityServiceManager + { + /// + /// Creates the API scope. + /// + /// The name. + /// The display name. + /// The description. + /// The cancellation token. + /// + Task CreateApiScope(String name, + String displayName, + String description, + CancellationToken cancellationToken); + + /// + /// Gets the API scope. + /// + /// Name of the API scope. + /// The cancellation token. + /// + Task GetApiScope(String apiScopeName, CancellationToken cancellationToken); + + /// + /// Gets the API scopes. + /// + /// The cancellation token. + /// + Task> GetApiScopes(CancellationToken cancellationToken); + + /// + /// Creates the API resource. + /// + /// The name. + /// The display name. + /// The description. + /// The secret. + /// The scopes. + /// The user claims. + /// The cancellation token. + /// + Task CreateApiResource(String name, + String displayName, + String description, + String secret, + List scopes, + List userClaims, + CancellationToken cancellationToken); + + /// + /// Creates the client. + /// + /// The client identifier. + /// The secret. + /// Name of the client. + /// The client description. + /// The allowed scopes. + /// The allowed grant types. + /// The client redirect uris. + /// The client post logout redirect uris. + /// if set to true [require consent]. + /// if set to true [allow offline access]. + /// The cancellation token. + /// + Task CreateClient(String clientId, + String secret, + String clientName, + String clientDescription, + List allowedScopes, + List allowedGrantTypes, + List clientRedirectUris, + List clientPostLogoutRedirectUris, + Boolean requireConsent, + Boolean allowOfflineAccess, + CancellationToken cancellationToken); + + /// + /// Creates the identity resource. + /// + /// The name. + /// The display name. + /// The description. + /// if set to true [required]. + /// if set to true [emphasize]. + /// if set to true [show in discovery document]. + /// The claims. + /// The cancellation token. + /// + Task CreateIdentityResource(String name, + String displayName, + String description, + Boolean required, + Boolean emphasize, + Boolean showInDiscoveryDocument, + List claims, + CancellationToken cancellationToken); + + /// + /// Creates the role. + /// + /// Name of the role. + /// The cancellation token. + /// + Task CreateRole(String roleName, + CancellationToken cancellationToken); + + /// + /// Registers the user. + /// + /// Name of the given. + /// Name of the middle. + /// Name of the family. + /// Name of the user. + /// The password. + /// The email address. + /// The phone number. + /// The claims. + /// The roles. + /// The cancellation token. + /// + Task CreateUser(String givenName, + String middleName, + String familyName, + String userName, + String password, + String emailAddress, + String phoneNumber, + Dictionary claims, + List roles, + CancellationToken cancellationToken); + + /// + /// Gets the API resource. + /// + /// Name of the API resource. + /// The cancellation token. + /// + Task GetApiResource(String apiResourceName, + CancellationToken cancellationToken); + + /// + /// Gets the API resources. + /// + /// The cancellation token. + /// + Task> GetApiResources(CancellationToken cancellationToken); + + /// + /// Gets the client. + /// + /// The client identifier. + /// The cancellation token. + /// + Task GetClient(String clientId, + CancellationToken cancellationToken); + + /// + /// Gets the clients. + /// + /// The cancellation token. + /// + Task> GetClients(CancellationToken cancellationToken); + + /// + /// Gets the identity resource. + /// + /// Name of the identity resource. + /// The cancellation token. + /// + Task GetIdentityResource(String identityResourceName, + CancellationToken cancellationToken); + + /// + /// Gets the API resources. + /// + /// The cancellation token. + /// + Task> GetIdentityResources(CancellationToken cancellationToken); + + /// + /// Gets the role. + /// + /// The role identifier. + /// The cancellation token. + /// + Task GetRole(Guid roleId, + CancellationToken cancellationToken); + + /// + /// Gets the roles. + /// + /// The cancellation token. + /// + Task> GetRoles(CancellationToken cancellationToken); + + /// + /// Gets the user by user identifier. + /// + /// The user identifier. + /// The cancellation token. + /// + Task GetUser(Guid userId, + CancellationToken cancellationToken); + + /// + /// Gets the users. + /// + /// Name of the user. + /// The cancellation token. + /// + Task> GetUsers(String userName, + CancellationToken cancellationToken); + + /// + /// Signouts this instance. + /// + /// + Task Signout(); + + /// + /// Validates the credentials. + /// + /// Name of the user. + /// The password. + /// The cancellation token. + /// + Task ValidateCredentials(String userName, + String password, + CancellationToken cancellationToken); + } + public class SecurityServiceManager : ISecurityServiceManager { #region Fields @@ -55,8 +286,6 @@ public class SecurityServiceManager : ISecurityServiceManager #endregion - #region Constructors - /// /// Initializes a new instance of the class. /// @@ -78,33 +307,21 @@ public SecurityServiceManager(IPasswordHasher passwordHasher, this.ConfigurationDbContext = configurationDbContext; } - #endregion - - #region Methods - - /// - /// Creates the API scope. - /// - /// The name. - /// The display name. - /// The description. - /// The cancellation token. - /// public async Task CreateApiScope(String name, String displayName, String description, CancellationToken cancellationToken) { ApiScope apiScope = new ApiScope - { - Description = description, - DisplayName = displayName, - Name = name, - Emphasize = false, - Enabled = true, - Required = false, - ShowInDiscoveryDocument = true - }; + { + Description = description, + DisplayName = displayName, + Name = name, + Emphasize = false, + Enabled = true, + Required = false, + ShowInDiscoveryDocument = true + }; // Now translate the model to the entity await this.ConfigurationDbContext.ApiScopes.AddAsync(apiScope.ToEntity(), cancellationToken); @@ -115,21 +332,14 @@ public async Task CreateApiScope(String name, return name; } - /// - /// Gets the API scope. - /// - /// Name of the API scope. - /// The cancellation token. - /// - /// No Api Scope found with Name [{apiScopeName}] public async Task GetApiScope(String apiScopeName, CancellationToken cancellationToken) { ApiScope apiScopeModel = null; - IdentityServer4.EntityFramework.Entities.ApiScope apiScopeEntity = await this.ConfigurationDbContext.ApiScopes.Where(a => a.Name == apiScopeName) - .Include(a => a.Properties).Include(a => a.UserClaims) - .SingleOrDefaultAsync(cancellationToken: cancellationToken); + Duende.IdentityServer.EntityFramework.Entities.ApiScope apiScopeEntity = await this.ConfigurationDbContext.ApiScopes.Where(a => a.Name == apiScopeName) + .Include(a => a.Properties).Include(a => a.UserClaims) + .SingleOrDefaultAsync(cancellationToken: cancellationToken); if (apiScopeEntity == null) { @@ -141,21 +351,16 @@ public async Task GetApiScope(String apiScopeName, return apiScopeModel; } - /// - /// Gets the API scopes. - /// - /// The cancellation token. - /// public async Task> GetApiScopes(CancellationToken cancellationToken) { List apiScopeModels = new List(); - List apiScopeEntities = + List apiScopeEntities = await this.ConfigurationDbContext.ApiScopes.Include(a => a.Properties).Include(a => a.UserClaims).ToListAsync(cancellationToken: cancellationToken); if (apiScopeEntities.Any()) { - foreach (IdentityServer4.EntityFramework.Entities.ApiScope apiScopeEntity in apiScopeEntities) + foreach (Duende.IdentityServer.EntityFramework.Entities.ApiScope apiScopeEntity in apiScopeEntities) { apiScopeModels.Add(apiScopeEntity.ToModel()); } @@ -164,17 +369,6 @@ public async Task> GetApiScopes(CancellationToken cancellationTok return apiScopeModels; } - /// - /// Creates the API resource. - /// - /// The name. - /// The display name. - /// The description. - /// The secret. - /// The scopes. - /// The user claims. - /// The cancellation token. - /// public async Task CreateApiResource(String name, String displayName, String description, @@ -212,21 +406,6 @@ public async Task CreateApiResource(String name, return name; } - /// - /// Creates the client. - /// - /// The client identifier. - /// The secret. - /// Name of the client. - /// The client description. - /// The allowed scopes. - /// The allowed grant types. - /// The client redirect uris. - /// The client post logout redirect uris. - /// if set to true [require consent]. - /// if set to true [allow offline access]. - /// The cancellation token. - /// public async Task CreateClient(String clientId, String secret, String clientName, @@ -244,19 +423,19 @@ public async Task CreateClient(String clientId, // Create the model from the request Client client = new Client - { - ClientId = clientId, - ClientName = clientName, - Description = clientDescription, - ClientSecrets = + { + ClientId = clientId, + ClientName = clientName, + Description = clientDescription, + ClientSecrets = { new Secret(secret.ToSha256()) }, - AllowedGrantTypes = allowedGrantTypes, - AllowedScopes = allowedScopes, - RequireConsent = requireConsent, - AllowOfflineAccess = allowOfflineAccess, - }; + AllowedGrantTypes = allowedGrantTypes, + AllowedScopes = allowedScopes, + RequireConsent = requireConsent, + AllowOfflineAccess = allowOfflineAccess, + }; if (allowedGrantTypes.Contains("hybrid")) { @@ -290,18 +469,6 @@ public async Task CreateClient(String clientId, return clientId; } - /// - /// Creates the identity resource. - /// - /// The name. - /// The display name. - /// The description. - /// if set to true [required]. - /// if set to true [emphasize]. - /// if set to true [show in discovery document]. - /// The claims. - /// The cancellation token. - /// public async Task CreateIdentityResource(String name, String displayName, String description, @@ -326,15 +493,6 @@ public async Task CreateIdentityResource(String name, return name; } - /// - /// Creates the role. - /// - /// Name of the role. - /// The cancellation token. - /// - /// Role {newIdentityRole.Name} already exists - /// or - /// Error creating role {newIdentityRole.Name} public async Task CreateRole(String roleName, CancellationToken cancellationToken) { @@ -366,29 +524,6 @@ public async Task CreateRole(String roleName, return roleId; } - /// - /// Registers the user. - /// - /// Name of the given. - /// Name of the middle. - /// Name of the family. - /// Name of the user. - /// The password. - /// The email address. - /// The phone number. - /// The claims. - /// The roles. - /// The cancellation token. - /// - /// Error generating password hash value, hash was null or empty - /// Error creating user {newIdentityUser.UserName} - /// or - /// Error adding roles [{string.Join(",", request.Roles)}] to user {newIdentityUser.UserName} - /// or - /// Error adding claims [{string.Join(",", claims)}] to user {newIdentityUser.UserName} - /// or - /// Error deleting user {newIdentityUser.UserName} as part of cleanup - /// Error generating password hash value, hash was null or empty public async Task CreateUser(String givenName, String middleName, String familyName, @@ -404,16 +539,16 @@ public async Task CreateUser(String givenName, // request is valid now add the user IdentityUser newIdentityUser = new IdentityUser - { - Id = userId.ToString(), - Email = emailAddress, - EmailConfirmed = true, - UserName = userName, - NormalizedEmail = emailAddress.ToUpper(), - NormalizedUserName = userName.ToUpper(), - SecurityStamp = Guid.NewGuid().ToString("D"), - PhoneNumber = phoneNumber - }; + { + Id = userId.ToString(), + Email = emailAddress, + EmailConfirmed = true, + UserName = userName, + NormalizedEmail = emailAddress.ToUpper(), + NormalizedUserName = userName.ToUpper(), + SecurityStamp = Guid.NewGuid().ToString("D"), + PhoneNumber = phoneNumber + }; // Set the password //String password = String.IsNullOrEmpty(request.Password) ? GenerateRandomPassword() : request.Password; @@ -511,21 +646,14 @@ public async Task CreateUser(String givenName, return userId; } - /// - /// Gets the API resource. - /// - /// Name of the API resource. - /// The cancellation token. - /// - /// No Api Resource found with Name [{apiResourceName}] public async Task GetApiResource(String apiResourceName, CancellationToken cancellationToken) { ApiResource apiResourceModel = null; - IdentityServer4.EntityFramework.Entities.ApiResource apiResourceEntity = await this.ConfigurationDbContext.ApiResources.Where(a => a.Name == apiResourceName) - .Include(a => a.Scopes).Include(a => a.UserClaims) - .SingleOrDefaultAsync(cancellationToken:cancellationToken); + Duende.IdentityServer.EntityFramework.Entities.ApiResource apiResourceEntity = await this.ConfigurationDbContext.ApiResources.Where(a => a.Name == apiResourceName) + .Include(a => a.Scopes).Include(a => a.UserClaims) + .SingleOrDefaultAsync(cancellationToken: cancellationToken); if (apiResourceEntity == null) { @@ -537,21 +665,16 @@ public async Task GetApiResource(String apiResourceName, return apiResourceModel; } - /// - /// Gets the API resources. - /// - /// The cancellation token. - /// public async Task> GetApiResources(CancellationToken cancellationToken) { List apiResourceModels = new List(); - List apiResourceEntities = - await this.ConfigurationDbContext.ApiResources.Include(a => a.Scopes).Include(a => a.UserClaims).ToListAsync(cancellationToken:cancellationToken); + List apiResourceEntities = + await this.ConfigurationDbContext.ApiResources.Include(a => a.Scopes).Include(a => a.UserClaims).ToListAsync(cancellationToken: cancellationToken); if (apiResourceEntities.Any()) { - foreach (IdentityServer4.EntityFramework.Entities.ApiResource apiResourceEntity in apiResourceEntities) + foreach (Duende.IdentityServer.EntityFramework.Entities.ApiResource apiResourceEntity in apiResourceEntities) { apiResourceModels.Add(apiResourceEntity.ToModel()); } @@ -560,22 +683,15 @@ public async Task> GetApiResources(CancellationToken cancellat return apiResourceModels; } - /// - /// Gets the client. - /// - /// The client identifier. - /// The cancellation token. - /// - /// No client found with Client Id [{clientId}] public async Task GetClient(String clientId, CancellationToken cancellationToken) { Client clientModel = null; - IdentityServer4.EntityFramework.Entities.Client clientEntity = await this.ConfigurationDbContext - .Clients.Include(c => c.AllowedGrantTypes).Include(c => c.AllowedScopes) - .Where(c => c.ClientId == clientId) - .SingleOrDefaultAsync(cancellationToken:cancellationToken); + Duende.IdentityServer.EntityFramework.Entities.Client clientEntity = await this.ConfigurationDbContext + .Clients.Include(c => c.AllowedGrantTypes).Include(c => c.AllowedScopes) + .Where(c => c.ClientId == clientId) + .SingleOrDefaultAsync(cancellationToken: cancellationToken); if (clientEntity == null) { @@ -587,22 +703,17 @@ public async Task GetClient(String clientId, return clientModel; } - /// - /// Gets the clients. - /// - /// The cancellation token. - /// public async Task> GetClients(CancellationToken cancellationToken) { List clientModels = new List(); - List clientEntities = await this - .ConfigurationDbContext.Clients.Include(c => c.AllowedGrantTypes) - .Include(c => c.AllowedScopes).ToListAsync(cancellationToken:cancellationToken); + List clientEntities = await this + .ConfigurationDbContext.Clients.Include(c => c.AllowedGrantTypes) + .Include(c => c.AllowedScopes).ToListAsync(cancellationToken: cancellationToken); if (clientEntities.Any()) { - foreach (IdentityServer4.EntityFramework.Entities.Client clientEntity in clientEntities) + foreach (Duende.IdentityServer.EntityFramework.Entities.Client clientEntity in clientEntities) { clientModels.Add(clientEntity.ToModel()); } @@ -611,23 +722,16 @@ public async Task> GetClients(CancellationToken cancellationToken) return clientModels; } - /// - /// Gets the identity resource. - /// - /// Name of the identity resource. - /// The cancellation token. - /// - /// No Identity Resource found with Name [{identityResourceName}] public async Task GetIdentityResource(String identityResourceName, CancellationToken cancellationToken) { IdentityResource identityResourceModel = null; - IdentityServer4.EntityFramework.Entities.IdentityResource identityResourceEntity = await this - .ConfigurationDbContext.IdentityResources - .Where(a => a.Name == identityResourceName) - .Include(a => a.UserClaims) - .SingleOrDefaultAsync(cancellationToken:cancellationToken); + Duende.IdentityServer.EntityFramework.Entities.IdentityResource identityResourceEntity = await this + .ConfigurationDbContext.IdentityResources + .Where(a => a.Name == identityResourceName) + .Include(a => a.UserClaims) + .SingleOrDefaultAsync(cancellationToken: cancellationToken); if (identityResourceEntity == null) { @@ -639,21 +743,16 @@ public async Task GetIdentityResource(String identityResourceN return identityResourceModel; } - /// - /// Gets the API resources. - /// - /// The cancellation token. - /// public async Task> GetIdentityResources(CancellationToken cancellationToken) { List identityResourceModels = new List(); - List identityResourceEntities = - await this.ConfigurationDbContext.IdentityResources.Include(a => a.UserClaims).ToListAsync(cancellationToken:cancellationToken); + List identityResourceEntities = + await this.ConfigurationDbContext.IdentityResources.Include(a => a.UserClaims).ToListAsync(cancellationToken: cancellationToken); if (identityResourceEntities.Any()) { - foreach (IdentityServer4.EntityFramework.Entities.IdentityResource identityResourceEntity in identityResourceEntities) + foreach (Duende.IdentityServer.EntityFramework.Entities.IdentityResource identityResourceEntity in identityResourceEntities) { identityResourceModels.Add(identityResourceEntity.ToModel()); } @@ -662,13 +761,6 @@ public async Task> GetIdentityResources(CancellationToken return identityResourceModels; } - /// - /// Gets the role. - /// - /// The role identifier. - /// The cancellation token. - /// - /// No role found with Id {roleId} public async Task GetRole(Guid roleId, CancellationToken cancellationToken) { @@ -689,11 +781,6 @@ public async Task GetRole(Guid roleId, return response; } - /// - /// Gets the roles. - /// - /// The cancellation token. - /// public async Task> GetRoles(CancellationToken cancellationToken) { List response = new List(); @@ -714,13 +801,6 @@ public async Task> GetRoles(CancellationToken cancellationToke return response; } - /// - /// Gets the user by user identifier. - /// - /// The user identifier. - /// The cancellation token. - /// - /// No user found with user Id {userId} public async Task GetUser(Guid userId, CancellationToken cancellationToken) { @@ -749,12 +829,6 @@ public async Task GetUser(Guid userId, return response; } - /// - /// Gets the users. - /// - /// Name of the user. - /// The cancellation token. - /// public async Task> GetUsers(String userName, CancellationToken cancellationToken) { @@ -789,22 +863,12 @@ public async Task> GetUsers(String userName, return response; } - /// - /// Signouts this instance. - /// [ExcludeFromCodeCoverage] public async Task Signout() { await this.SignInManager.SignOutAsync(); } - /// - /// Validates the credentials. - /// - /// Name of the user. - /// The password. - /// The cancellation token. - /// public async Task ValidateCredentials(String userName, String password, CancellationToken cancellationToken) @@ -857,12 +921,12 @@ private void ValidateGrantTypes(List allowedGrantTypes) // Get a list of valid grant types List validTypesList = new List(); - validTypesList.AddRange(GrantTypes.ClientCredentials); - validTypesList.AddRange(GrantTypes.Code); - validTypesList.AddRange(GrantTypes.DeviceFlow); - validTypesList.AddRange(GrantTypes.Hybrid); - validTypesList.AddRange(GrantTypes.Implicit); - validTypesList.AddRange(GrantTypes.ResourceOwnerPassword); + validTypesList.Add(Duende.IdentityServer.Models.GrantType.AuthorizationCode); + validTypesList.Add(Duende.IdentityServer.Models.GrantType.ClientCredentials); + validTypesList.Add(Duende.IdentityServer.Models.GrantType.DeviceFlow); + validTypesList.Add(Duende.IdentityServer.Models.GrantType.Hybrid); + validTypesList.Add(Duende.IdentityServer.Models.GrantType.Implicit); + validTypesList.Add(Duende.IdentityServer.Models.GrantType.ResourceOwnerPassword); List invalidGrantTypes = allowedGrantTypes.Where(a => validTypesList.All(v => v != a)).ToList(); @@ -871,7 +935,5 @@ private void ValidateGrantTypes(List allowedGrantTypes) throw new ArgumentException(nameof(allowedGrantTypes), $"The grant types [{string.Join(", ", invalidGrantTypes)}] are not valid to create a new client"); } } - - #endregion } -} \ No newline at end of file +} diff --git a/SecurityService.BusinessLogic/SecurityService.BusinessLogic.csproj b/SecurityService.BusinessLogic/SecurityService.BusinessLogic.csproj new file mode 100644 index 00000000..a25c80f3 --- /dev/null +++ b/SecurityService.BusinessLogic/SecurityService.BusinessLogic.csproj @@ -0,0 +1,24 @@ + + + + net5.0 + + + + + + + + + + + + + + + + + + + + diff --git a/SecurityService.DataTransferObjects/Requests/CreateClientRequest.cs b/SecurityService.DataTransferObjects/Requests/CreateClientRequest.cs index ec4e20ac..aabd2545 100644 --- a/SecurityService.DataTransferObjects/Requests/CreateClientRequest.cs +++ b/SecurityService.DataTransferObjects/Requests/CreateClientRequest.cs @@ -2,7 +2,6 @@ { using System; using System.Collections.Generic; - using System.ComponentModel.DataAnnotations; using System.Diagnostics.CodeAnalysis; using Newtonsoft.Json; @@ -56,7 +55,6 @@ public class CreateClientRequest /// /// The client identifier. /// - [Required] [JsonProperty("client_id")] public String ClientId { get; set; } @@ -66,7 +64,6 @@ public class CreateClientRequest /// /// The name of the client. /// - [Required] [JsonProperty("client_name")] public String ClientName { get; set; } @@ -103,7 +100,6 @@ public class CreateClientRequest /// /// The secret. /// - [Required] [JsonProperty("secret")] public String Secret { get; set; } diff --git a/SecurityService.DataTransferObjects/Requests/CreateRoleRequest.cs b/SecurityService.DataTransferObjects/Requests/CreateRoleRequest.cs index 94778d30..c331e623 100644 --- a/SecurityService.DataTransferObjects/Requests/CreateRoleRequest.cs +++ b/SecurityService.DataTransferObjects/Requests/CreateRoleRequest.cs @@ -4,7 +4,6 @@ namespace SecurityService.DataTransferObjects.Requests { - using System.ComponentModel.DataAnnotations; using System.Diagnostics.CodeAnalysis; using Newtonsoft.Json; @@ -17,7 +16,6 @@ public class CreateRoleRequest /// /// The name of the role. /// - [Required] [JsonProperty("role_name")] public String RoleName { get; set; } } diff --git a/SecurityService.DataTransferObjects/Requests/CreateUserRequest.cs b/SecurityService.DataTransferObjects/Requests/CreateUserRequest.cs index fbdbca61..c4ea9bf6 100644 --- a/SecurityService.DataTransferObjects/Requests/CreateUserRequest.cs +++ b/SecurityService.DataTransferObjects/Requests/CreateUserRequest.cs @@ -2,7 +2,6 @@ { using System; using System.Collections.Generic; - using System.ComponentModel.DataAnnotations; using System.Diagnostics.CodeAnalysis; using System.Runtime.CompilerServices; using Newtonsoft.Json; @@ -16,7 +15,6 @@ public class CreateUserRequest /// /// The email address. /// - [Required] [JsonProperty("email_address")] public String EmailAddress { get; set; } @@ -26,7 +24,6 @@ public class CreateUserRequest /// /// The phone number. /// - [Required] [JsonProperty("phone_number")] public String PhoneNumber { get; set; } @@ -36,7 +33,6 @@ public class CreateUserRequest /// /// The password. /// - [Required] [JsonProperty("password")] public String Password { get; set; } @@ -64,7 +60,6 @@ public class CreateUserRequest /// /// The name of the given. /// - [Required] [JsonProperty("given_name")] public String GivenName { get; set; } @@ -83,7 +78,6 @@ public class CreateUserRequest /// /// The name of the family. /// - [Required] [JsonProperty("family_name")] public String FamilyName { get; set; } } diff --git a/SecurityService.DataTransferObjects/SecurityService.DataTransferObjects.csproj b/SecurityService.DataTransferObjects/SecurityService.DataTransferObjects.csproj index 282ca1a2..b4b47128 100644 --- a/SecurityService.DataTransferObjects/SecurityService.DataTransferObjects.csproj +++ b/SecurityService.DataTransferObjects/SecurityService.DataTransferObjects.csproj @@ -1,17 +1,16 @@ - + net5.0;netstandard2.0 - - D:\Projects\StuartFerguson\SecurityService\SecurityService.DataTransferObjects\SecurityService.DataTransferObjects.xml + + D:\Projects\StuartFerguson\NewSecurity\SecurityService\SecurityService.DataTransferObjects\SecurityService.DataTransferObjects.xml - - - + + diff --git a/SecurityService.Database/DbContexts/AuthenticationDbContext.cs b/SecurityService.Database/DbContexts/AuthenticationDbContext.cs index 301d7ab9..728a7794 100644 --- a/SecurityService.Database/DbContexts/AuthenticationDbContext.cs +++ b/SecurityService.Database/DbContexts/AuthenticationDbContext.cs @@ -1,55 +1,22 @@ -namespace SecurityService.Database.DbContexts +namespace SecurityService.Database.DbContexts { using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Identity.EntityFrameworkCore; using Microsoft.EntityFrameworkCore; - /// - /// - /// - /// public class AuthenticationDbContext : IdentityDbContext { - #region Constructors - - /// - /// Initializes a new instance of the class. - /// - public AuthenticationDbContext() - { - // Paramaterless constructor required for migrations. - } - - /// - /// Initializes a new instance of the class. - /// - /// The options. - public AuthenticationDbContext(DbContextOptions options) : base(options) - { - } - - #endregion - - #region Methods - - /// - /// Called when [configuring]. - /// - /// The builder. - protected override void OnConfiguring(DbContextOptionsBuilder builder) + public AuthenticationDbContext(DbContextOptions options) + : base((DbContextOptions)options) { - base.OnConfiguring(builder); } - /// - /// Configures the schema needed for the identity framework. - /// - /// The builder being used to construct the model for this context. protected override void OnModelCreating(ModelBuilder builder) { base.OnModelCreating(builder); + // Customize the ASP.NET Identity model and override the defaults if needed. + // For example, you can rename the ASP.NET Identity table names and more. + // Add your customizations after calling base.OnModelCreating(builder); } - - #endregion } } \ No newline at end of file diff --git a/SecurityService.Database/Migrations/AuthenticationDbContext/20191105215459_InitialDbMigration.Designer.cs b/SecurityService.Database/Migrations/AuthenticationDb/20210607111618_InitialMigration.Designer.cs similarity index 83% rename from SecurityService.Database/Migrations/AuthenticationDbContext/20191105215459_InitialDbMigration.Designer.cs rename to SecurityService.Database/Migrations/AuthenticationDb/20210607111618_InitialMigration.Designer.cs index 40e9fbeb..b95b7123 100644 --- a/SecurityService.Database/Migrations/AuthenticationDbContext/20191105215459_InitialDbMigration.Designer.cs +++ b/SecurityService.Database/Migrations/AuthenticationDb/20210607111618_InitialMigration.Designer.cs @@ -1,26 +1,24 @@ // -using System; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using SecurityService.Database.DbContexts; - -namespace SecurityService.Database.Migrations.AuthenticationDbContext + +namespace SecurityService.Database.Migrations.AuthenticationDb { - using AuthenticationDbContext = DbContexts.AuthenticationDbContext; + using Microsoft.EntityFrameworkCore; + using Microsoft.EntityFrameworkCore.Infrastructure; + using Microsoft.EntityFrameworkCore.Metadata; + using Microsoft.EntityFrameworkCore.Migrations; + using SecurityService.Database.DbContexts; + using System; [DbContext(typeof(AuthenticationDbContext))] - [Migration("20191105215459_InitialDbMigration")] - partial class InitialDbMigration + [Migration("20210607111618_InitialMigration")] + partial class InitialMigration { protected override void BuildTargetModel(ModelBuilder modelBuilder) { #pragma warning disable 612, 618 modelBuilder - .HasAnnotation("ProductVersion", "3.0.0") .HasAnnotation("Relational:MaxIdentifierLength", 128) + .HasAnnotation("ProductVersion", "5.0.6") .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => @@ -33,18 +31,18 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) .HasColumnType("nvarchar(max)"); b.Property("Name") - .HasColumnType("nvarchar(256)") - .HasMaxLength(256); + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); b.Property("NormalizedName") - .HasColumnType("nvarchar(256)") - .HasMaxLength(256); + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); b.HasKey("Id"); b.HasIndex("NormalizedName") .IsUnique() - .HasName("RoleNameIndex") + .HasDatabaseName("RoleNameIndex") .HasFilter("[NormalizedName] IS NOT NULL"); b.ToTable("AspNetRoles"); @@ -74,71 +72,6 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.ToTable("AspNetRoleClaims"); }); - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUser", b => - { - b.Property("Id") - .HasColumnType("nvarchar(450)"); - - b.Property("AccessFailedCount") - .HasColumnType("int"); - - b.Property("ConcurrencyStamp") - .IsConcurrencyToken() - .HasColumnType("nvarchar(max)"); - - b.Property("Email") - .HasColumnType("nvarchar(256)") - .HasMaxLength(256); - - b.Property("EmailConfirmed") - .HasColumnType("bit"); - - b.Property("LockoutEnabled") - .HasColumnType("bit"); - - b.Property("LockoutEnd") - .HasColumnType("datetimeoffset"); - - b.Property("NormalizedEmail") - .HasColumnType("nvarchar(256)") - .HasMaxLength(256); - - b.Property("NormalizedUserName") - .HasColumnType("nvarchar(256)") - .HasMaxLength(256); - - b.Property("PasswordHash") - .HasColumnType("nvarchar(max)"); - - b.Property("PhoneNumber") - .HasColumnType("nvarchar(max)"); - - b.Property("PhoneNumberConfirmed") - .HasColumnType("bit"); - - b.Property("SecurityStamp") - .HasColumnType("nvarchar(max)"); - - b.Property("TwoFactorEnabled") - .HasColumnType("bit"); - - b.Property("UserName") - .HasColumnType("nvarchar(256)") - .HasMaxLength(256); - - b.HasKey("Id"); - - b.HasIndex("NormalizedEmail") - .HasName("EmailIndex"); - - b.HasIndex("NormalizedUserName") - .IsUnique() - .HasName("UserNameIndex") - .HasFilter("[NormalizedUserName] IS NOT NULL"); - - b.ToTable("AspNetUsers"); - }); - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => { b.Property("Id") @@ -219,6 +152,71 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.ToTable("AspNetUserTokens"); }); + modelBuilder.Entity("SecurityService.ApplicationUser", b => + { + b.Property("Id") + .HasColumnType("nvarchar(450)"); + + b.Property("AccessFailedCount") + .HasColumnType("int"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("nvarchar(max)"); + + b.Property("Email") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("EmailConfirmed") + .HasColumnType("bit"); + + b.Property("LockoutEnabled") + .HasColumnType("bit"); + + b.Property("LockoutEnd") + .HasColumnType("datetimeoffset"); + + b.Property("NormalizedEmail") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("NormalizedUserName") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("PasswordHash") + .HasColumnType("nvarchar(max)"); + + b.Property("PhoneNumber") + .HasColumnType("nvarchar(max)"); + + b.Property("PhoneNumberConfirmed") + .HasColumnType("bit"); + + b.Property("SecurityStamp") + .HasColumnType("nvarchar(max)"); + + b.Property("TwoFactorEnabled") + .HasColumnType("bit"); + + b.Property("UserName") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedEmail") + .HasDatabaseName("EmailIndex"); + + b.HasIndex("NormalizedUserName") + .IsUnique() + .HasDatabaseName("UserNameIndex") + .HasFilter("[NormalizedUserName] IS NOT NULL"); + + b.ToTable("AspNetUsers"); + }); + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => { b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) @@ -230,7 +228,7 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => { - b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null) + b.HasOne("SecurityService.ApplicationUser", null) .WithMany() .HasForeignKey("UserId") .OnDelete(DeleteBehavior.Cascade) @@ -239,7 +237,7 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => { - b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null) + b.HasOne("SecurityService.ApplicationUser", null) .WithMany() .HasForeignKey("UserId") .OnDelete(DeleteBehavior.Cascade) @@ -254,7 +252,7 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) .OnDelete(DeleteBehavior.Cascade) .IsRequired(); - b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null) + b.HasOne("SecurityService.ApplicationUser", null) .WithMany() .HasForeignKey("UserId") .OnDelete(DeleteBehavior.Cascade) @@ -263,7 +261,7 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => { - b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null) + b.HasOne("SecurityService.ApplicationUser", null) .WithMany() .HasForeignKey("UserId") .OnDelete(DeleteBehavior.Cascade) diff --git a/SecurityService.Database/Migrations/AuthenticationDbContext/20191105215459_InitialDbMigration.cs b/SecurityService.Database/Migrations/AuthenticationDb/20210607111618_InitialMigration.cs similarity index 63% rename from SecurityService.Database/Migrations/AuthenticationDbContext/20191105215459_InitialDbMigration.cs rename to SecurityService.Database/Migrations/AuthenticationDb/20210607111618_InitialMigration.cs index d1bda73e..665e8b8d 100644 --- a/SecurityService.Database/Migrations/AuthenticationDbContext/20191105215459_InitialDbMigration.cs +++ b/SecurityService.Database/Migrations/AuthenticationDb/20210607111618_InitialMigration.cs @@ -1,9 +1,9 @@ -using System; -using Microsoft.EntityFrameworkCore.Migrations; - -namespace SecurityService.Database.Migrations.AuthenticationDbContext +namespace SecurityService.Database.Migrations.AuthenticationDb { - public partial class InitialDbMigration : Migration + using System; + using Microsoft.EntityFrameworkCore.Migrations; + + public partial class InitialMigration : Migration { protected override void Up(MigrationBuilder migrationBuilder) { @@ -11,10 +11,10 @@ protected override void Up(MigrationBuilder migrationBuilder) name: "AspNetRoles", columns: table => new { - Id = table.Column(nullable: false), - Name = table.Column(maxLength: 256, nullable: true), - NormalizedName = table.Column(maxLength: 256, nullable: true), - ConcurrencyStamp = table.Column(nullable: true) + Id = table.Column(type: "nvarchar(450)", nullable: false), + Name = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: true), + NormalizedName = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: true), + ConcurrencyStamp = table.Column(type: "nvarchar(max)", nullable: true) }, constraints: table => { @@ -25,21 +25,21 @@ protected override void Up(MigrationBuilder migrationBuilder) name: "AspNetUsers", columns: table => new { - Id = table.Column(nullable: false), - UserName = table.Column(maxLength: 256, nullable: true), - NormalizedUserName = table.Column(maxLength: 256, nullable: true), - Email = table.Column(maxLength: 256, nullable: true), - NormalizedEmail = table.Column(maxLength: 256, nullable: true), - EmailConfirmed = table.Column(nullable: false), - PasswordHash = table.Column(nullable: true), - SecurityStamp = table.Column(nullable: true), - ConcurrencyStamp = table.Column(nullable: true), - PhoneNumber = table.Column(nullable: true), - PhoneNumberConfirmed = table.Column(nullable: false), - TwoFactorEnabled = table.Column(nullable: false), - LockoutEnd = table.Column(nullable: true), - LockoutEnabled = table.Column(nullable: false), - AccessFailedCount = table.Column(nullable: false) + Id = table.Column(type: "nvarchar(450)", nullable: false), + UserName = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: true), + NormalizedUserName = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: true), + Email = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: true), + NormalizedEmail = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: true), + EmailConfirmed = table.Column(type: "bit", nullable: false), + PasswordHash = table.Column(type: "nvarchar(max)", nullable: true), + SecurityStamp = table.Column(type: "nvarchar(max)", nullable: true), + ConcurrencyStamp = table.Column(type: "nvarchar(max)", nullable: true), + PhoneNumber = table.Column(type: "nvarchar(max)", nullable: true), + PhoneNumberConfirmed = table.Column(type: "bit", nullable: false), + TwoFactorEnabled = table.Column(type: "bit", nullable: false), + LockoutEnd = table.Column(type: "datetimeoffset", nullable: true), + LockoutEnabled = table.Column(type: "bit", nullable: false), + AccessFailedCount = table.Column(type: "int", nullable: false) }, constraints: table => { @@ -50,11 +50,11 @@ protected override void Up(MigrationBuilder migrationBuilder) name: "AspNetRoleClaims", columns: table => new { - Id = table.Column(nullable: false) + Id = table.Column(type: "int", nullable: false) .Annotation("SqlServer:Identity", "1, 1"), - RoleId = table.Column(nullable: false), - ClaimType = table.Column(nullable: true), - ClaimValue = table.Column(nullable: true) + RoleId = table.Column(type: "nvarchar(450)", nullable: false), + ClaimType = table.Column(type: "nvarchar(max)", nullable: true), + ClaimValue = table.Column(type: "nvarchar(max)", nullable: true) }, constraints: table => { @@ -71,11 +71,11 @@ protected override void Up(MigrationBuilder migrationBuilder) name: "AspNetUserClaims", columns: table => new { - Id = table.Column(nullable: false) + Id = table.Column(type: "int", nullable: false) .Annotation("SqlServer:Identity", "1, 1"), - UserId = table.Column(nullable: false), - ClaimType = table.Column(nullable: true), - ClaimValue = table.Column(nullable: true) + UserId = table.Column(type: "nvarchar(450)", nullable: false), + ClaimType = table.Column(type: "nvarchar(max)", nullable: true), + ClaimValue = table.Column(type: "nvarchar(max)", nullable: true) }, constraints: table => { @@ -92,10 +92,10 @@ protected override void Up(MigrationBuilder migrationBuilder) name: "AspNetUserLogins", columns: table => new { - LoginProvider = table.Column(nullable: false), - ProviderKey = table.Column(nullable: false), - ProviderDisplayName = table.Column(nullable: true), - UserId = table.Column(nullable: false) + LoginProvider = table.Column(type: "nvarchar(450)", nullable: false), + ProviderKey = table.Column(type: "nvarchar(450)", nullable: false), + ProviderDisplayName = table.Column(type: "nvarchar(max)", nullable: true), + UserId = table.Column(type: "nvarchar(450)", nullable: false) }, constraints: table => { @@ -112,8 +112,8 @@ protected override void Up(MigrationBuilder migrationBuilder) name: "AspNetUserRoles", columns: table => new { - UserId = table.Column(nullable: false), - RoleId = table.Column(nullable: false) + UserId = table.Column(type: "nvarchar(450)", nullable: false), + RoleId = table.Column(type: "nvarchar(450)", nullable: false) }, constraints: table => { @@ -136,10 +136,10 @@ protected override void Up(MigrationBuilder migrationBuilder) name: "AspNetUserTokens", columns: table => new { - UserId = table.Column(nullable: false), - LoginProvider = table.Column(nullable: false), - Name = table.Column(nullable: false), - Value = table.Column(nullable: true) + UserId = table.Column(type: "nvarchar(450)", nullable: false), + LoginProvider = table.Column(type: "nvarchar(450)", nullable: false), + Name = table.Column(type: "nvarchar(450)", nullable: false), + Value = table.Column(type: "nvarchar(max)", nullable: true) }, constraints: table => { diff --git a/SecurityService.Database/Migrations/AuthenticationDbContext/AuthenticationDbContextModelSnapshot.cs b/SecurityService.Database/Migrations/AuthenticationDb/AuthenticationDbContextModelSnapshot.cs similarity index 89% rename from SecurityService.Database/Migrations/AuthenticationDbContext/AuthenticationDbContextModelSnapshot.cs rename to SecurityService.Database/Migrations/AuthenticationDb/AuthenticationDbContextModelSnapshot.cs index b66af45c..55cb9e65 100644 --- a/SecurityService.Database/Migrations/AuthenticationDbContext/AuthenticationDbContextModelSnapshot.cs +++ b/SecurityService.Database/Migrations/AuthenticationDb/AuthenticationDbContextModelSnapshot.cs @@ -1,14 +1,12 @@ // -using System; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using SecurityService.Database.DbContexts; - -namespace SecurityService.Database.Migrations.AuthenticationDbContext + +namespace SecurityService.Database.Migrations.IdentityServer.AuthenticationDb { - using AuthenticationDbContext = DbContexts.AuthenticationDbContext; + using System; + using Microsoft.EntityFrameworkCore; + using Microsoft.EntityFrameworkCore.Infrastructure; + using Microsoft.EntityFrameworkCore.Metadata; + using SecurityService.Database.DbContexts; [DbContext(typeof(AuthenticationDbContext))] partial class AuthenticationDbContextModelSnapshot : ModelSnapshot @@ -17,9 +15,9 @@ protected override void BuildModel(ModelBuilder modelBuilder) { #pragma warning disable 612, 618 modelBuilder - .UseIdentityColumns() .HasAnnotation("Relational:MaxIdentifierLength", 128) - .HasAnnotation("ProductVersion", "5.0.2"); + .HasAnnotation("ProductVersion", "5.0.6") + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => { @@ -53,7 +51,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Property("Id") .ValueGeneratedOnAdd() .HasColumnType("int") - .UseIdentityColumn(); + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); b.Property("ClaimType") .HasColumnType("nvarchar(max)"); @@ -72,77 +70,12 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.ToTable("AspNetRoleClaims"); }); - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUser", b => - { - b.Property("Id") - .HasColumnType("nvarchar(450)"); - - b.Property("AccessFailedCount") - .HasColumnType("int"); - - b.Property("ConcurrencyStamp") - .IsConcurrencyToken() - .HasColumnType("nvarchar(max)"); - - b.Property("Email") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.Property("EmailConfirmed") - .HasColumnType("bit"); - - b.Property("LockoutEnabled") - .HasColumnType("bit"); - - b.Property("LockoutEnd") - .HasColumnType("datetimeoffset"); - - b.Property("NormalizedEmail") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.Property("NormalizedUserName") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.Property("PasswordHash") - .HasColumnType("nvarchar(max)"); - - b.Property("PhoneNumber") - .HasColumnType("nvarchar(max)"); - - b.Property("PhoneNumberConfirmed") - .HasColumnType("bit"); - - b.Property("SecurityStamp") - .HasColumnType("nvarchar(max)"); - - b.Property("TwoFactorEnabled") - .HasColumnType("bit"); - - b.Property("UserName") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.HasKey("Id"); - - b.HasIndex("NormalizedEmail") - .HasDatabaseName("EmailIndex"); - - b.HasIndex("NormalizedUserName") - .IsUnique() - .HasDatabaseName("UserNameIndex") - .HasFilter("[NormalizedUserName] IS NOT NULL"); - - b.ToTable("AspNetUsers"); - }); - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => { b.Property("Id") .ValueGeneratedOnAdd() .HasColumnType("int") - .UseIdentityColumn(); + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); b.Property("ClaimType") .HasColumnType("nvarchar(max)"); @@ -217,6 +150,71 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.ToTable("AspNetUserTokens"); }); + modelBuilder.Entity("SecurityService.ApplicationUser", b => + { + b.Property("Id") + .HasColumnType("nvarchar(450)"); + + b.Property("AccessFailedCount") + .HasColumnType("int"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("nvarchar(max)"); + + b.Property("Email") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("EmailConfirmed") + .HasColumnType("bit"); + + b.Property("LockoutEnabled") + .HasColumnType("bit"); + + b.Property("LockoutEnd") + .HasColumnType("datetimeoffset"); + + b.Property("NormalizedEmail") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("NormalizedUserName") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("PasswordHash") + .HasColumnType("nvarchar(max)"); + + b.Property("PhoneNumber") + .HasColumnType("nvarchar(max)"); + + b.Property("PhoneNumberConfirmed") + .HasColumnType("bit"); + + b.Property("SecurityStamp") + .HasColumnType("nvarchar(max)"); + + b.Property("TwoFactorEnabled") + .HasColumnType("bit"); + + b.Property("UserName") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedEmail") + .HasDatabaseName("EmailIndex"); + + b.HasIndex("NormalizedUserName") + .IsUnique() + .HasDatabaseName("UserNameIndex") + .HasFilter("[NormalizedUserName] IS NOT NULL"); + + b.ToTable("AspNetUsers"); + }); + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => { b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) @@ -228,7 +226,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => { - b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null) + b.HasOne("SecurityService.ApplicationUser", null) .WithMany() .HasForeignKey("UserId") .OnDelete(DeleteBehavior.Cascade) @@ -237,7 +235,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => { - b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null) + b.HasOne("SecurityService.ApplicationUser", null) .WithMany() .HasForeignKey("UserId") .OnDelete(DeleteBehavior.Cascade) @@ -252,7 +250,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) .OnDelete(DeleteBehavior.Cascade) .IsRequired(); - b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null) + b.HasOne("SecurityService.ApplicationUser", null) .WithMany() .HasForeignKey("UserId") .OnDelete(DeleteBehavior.Cascade) @@ -261,7 +259,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => { - b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null) + b.HasOne("SecurityService.ApplicationUser", null) .WithMany() .HasForeignKey("UserId") .OnDelete(DeleteBehavior.Cascade) diff --git a/SecurityService.Database/Migrations/ConfigurationDbContext/20210118212226_Identityv4.Designer.cs b/SecurityService.Database/Migrations/ConfigurationDb/20210607105411_InitialMigration.Designer.cs similarity index 72% rename from SecurityService.Database/Migrations/ConfigurationDbContext/20210118212226_Identityv4.Designer.cs rename to SecurityService.Database/Migrations/ConfigurationDb/20210607105411_InitialMigration.Designer.cs index b3acbe0c..934bdc9c 100644 --- a/SecurityService.Database/Migrations/ConfigurationDbContext/20210118212226_Identityv4.Designer.cs +++ b/SecurityService.Database/Migrations/ConfigurationDb/20210607105411_InitialMigration.Designer.cs @@ -1,34 +1,32 @@ // -using System; -using IdentityServer4.EntityFramework.DbContexts; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; - -namespace SecurityService.Database.Migrations.ConfigurationDbContext -{ - using ConfigurationDbContext = IdentityServer4.EntityFramework.DbContexts.ConfigurationDbContext; +namespace SecurityService.Database.Migrations.ConfigurationDb +{ + using Duende.IdentityServer.EntityFramework.DbContexts; + using Microsoft.EntityFrameworkCore; + using Microsoft.EntityFrameworkCore.Infrastructure; + using Microsoft.EntityFrameworkCore.Metadata; + using Microsoft.EntityFrameworkCore.Migrations; + using System; + [DbContext(typeof(ConfigurationDbContext))] - [Migration("20210118212226_Identityv4")] - partial class Identityv4 + [Migration("20210607105411_InitialMigration")] + partial class InitialMigration { protected override void BuildTargetModel(ModelBuilder modelBuilder) { #pragma warning disable 612, 618 modelBuilder - .UseIdentityColumns() .HasAnnotation("Relational:MaxIdentifierLength", 128) - .HasAnnotation("ProductVersion", "5.0.2"); + .HasAnnotation("ProductVersion", "5.0.6") + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ApiResource", b => + modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ApiResource", b => { b.Property("Id") .ValueGeneratedOnAdd() .HasColumnType("int") - .UseIdentityColumn(); + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); b.Property("AllowedAccessTokenSigningAlgorithms") .HasMaxLength(100) @@ -59,6 +57,9 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.Property("NonEditable") .HasColumnType("bit"); + b.Property("RequireResourceIndicator") + .HasColumnType("bit"); + b.Property("ShowInDiscoveryDocument") .HasColumnType("bit"); @@ -73,12 +74,12 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.ToTable("ApiResources"); }); - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ApiResourceClaim", b => + modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ApiResourceClaim", b => { b.Property("Id") .ValueGeneratedOnAdd() .HasColumnType("int") - .UseIdentityColumn(); + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); b.Property("ApiResourceId") .HasColumnType("int"); @@ -95,12 +96,12 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.ToTable("ApiResourceClaims"); }); - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ApiResourceProperty", b => + modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ApiResourceProperty", b => { b.Property("Id") .ValueGeneratedOnAdd() .HasColumnType("int") - .UseIdentityColumn(); + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); b.Property("ApiResourceId") .HasColumnType("int"); @@ -122,12 +123,12 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.ToTable("ApiResourceProperties"); }); - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ApiResourceScope", b => + modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ApiResourceScope", b => { b.Property("Id") .ValueGeneratedOnAdd() .HasColumnType("int") - .UseIdentityColumn(); + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); b.Property("ApiResourceId") .HasColumnType("int"); @@ -144,12 +145,12 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.ToTable("ApiResourceScopes"); }); - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ApiResourceSecret", b => + modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ApiResourceSecret", b => { b.Property("Id") .ValueGeneratedOnAdd() .HasColumnType("int") - .UseIdentityColumn(); + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); b.Property("ApiResourceId") .HasColumnType("int"); @@ -181,12 +182,12 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.ToTable("ApiResourceSecrets"); }); - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ApiScope", b => + modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ApiScope", b => { b.Property("Id") .ValueGeneratedOnAdd() .HasColumnType("int") - .UseIdentityColumn(); + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); b.Property("Description") .HasMaxLength(1000) @@ -221,12 +222,12 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.ToTable("ApiScopes"); }); - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ApiScopeClaim", b => + modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ApiScopeClaim", b => { b.Property("Id") .ValueGeneratedOnAdd() .HasColumnType("int") - .UseIdentityColumn(); + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); b.Property("ScopeId") .HasColumnType("int"); @@ -243,12 +244,12 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.ToTable("ApiScopeClaims"); }); - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ApiScopeProperty", b => + modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ApiScopeProperty", b => { b.Property("Id") .ValueGeneratedOnAdd() .HasColumnType("int") - .UseIdentityColumn(); + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); b.Property("Key") .IsRequired() @@ -270,12 +271,12 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.ToTable("ApiScopeProperties"); }); - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.Client", b => + modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.Client", b => { b.Property("Id") .ValueGeneratedOnAdd() .HasColumnType("int") - .UseIdentityColumn(); + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); b.Property("AbsoluteRefreshTokenLifetime") .HasColumnType("int"); @@ -428,12 +429,12 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.ToTable("Clients"); }); - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientClaim", b => + modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ClientClaim", b => { b.Property("Id") .ValueGeneratedOnAdd() .HasColumnType("int") - .UseIdentityColumn(); + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); b.Property("ClientId") .HasColumnType("int"); @@ -455,12 +456,12 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.ToTable("ClientClaims"); }); - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientCorsOrigin", b => + modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ClientCorsOrigin", b => { b.Property("Id") .ValueGeneratedOnAdd() .HasColumnType("int") - .UseIdentityColumn(); + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); b.Property("ClientId") .HasColumnType("int"); @@ -477,12 +478,12 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.ToTable("ClientCorsOrigins"); }); - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientGrantType", b => + modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ClientGrantType", b => { b.Property("Id") .ValueGeneratedOnAdd() .HasColumnType("int") - .UseIdentityColumn(); + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); b.Property("ClientId") .HasColumnType("int"); @@ -499,12 +500,12 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.ToTable("ClientGrantTypes"); }); - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientIdPRestriction", b => + modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ClientIdPRestriction", b => { b.Property("Id") .ValueGeneratedOnAdd() .HasColumnType("int") - .UseIdentityColumn(); + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); b.Property("ClientId") .HasColumnType("int"); @@ -521,12 +522,12 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.ToTable("ClientIdPRestrictions"); }); - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientPostLogoutRedirectUri", b => + modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ClientPostLogoutRedirectUri", b => { b.Property("Id") .ValueGeneratedOnAdd() .HasColumnType("int") - .UseIdentityColumn(); + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); b.Property("ClientId") .HasColumnType("int"); @@ -543,12 +544,12 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.ToTable("ClientPostLogoutRedirectUris"); }); - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientProperty", b => + modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ClientProperty", b => { b.Property("Id") .ValueGeneratedOnAdd() .HasColumnType("int") - .UseIdentityColumn(); + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); b.Property("ClientId") .HasColumnType("int"); @@ -570,12 +571,12 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.ToTable("ClientProperties"); }); - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientRedirectUri", b => + modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ClientRedirectUri", b => { b.Property("Id") .ValueGeneratedOnAdd() .HasColumnType("int") - .UseIdentityColumn(); + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); b.Property("ClientId") .HasColumnType("int"); @@ -592,12 +593,12 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.ToTable("ClientRedirectUris"); }); - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientScope", b => + modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ClientScope", b => { b.Property("Id") .ValueGeneratedOnAdd() .HasColumnType("int") - .UseIdentityColumn(); + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); b.Property("ClientId") .HasColumnType("int"); @@ -614,12 +615,12 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.ToTable("ClientScopes"); }); - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientSecret", b => + modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ClientSecret", b => { b.Property("Id") .ValueGeneratedOnAdd() .HasColumnType("int") - .UseIdentityColumn(); + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); b.Property("ClientId") .HasColumnType("int"); @@ -651,12 +652,44 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.ToTable("ClientSecrets"); }); - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.IdentityResource", b => + modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.IdentityProvider", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); + + b.Property("DisplayName") + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.Property("Enabled") + .HasColumnType("bit"); + + b.Property("Properties") + .HasColumnType("nvarchar(max)"); + + b.Property("Scheme") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.Property("Type") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("nvarchar(20)"); + + b.HasKey("Id"); + + b.ToTable("IdentityProviders"); + }); + + modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.IdentityResource", b => { b.Property("Id") .ValueGeneratedOnAdd() .HasColumnType("int") - .UseIdentityColumn(); + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); b.Property("Created") .HasColumnType("datetime2"); @@ -700,12 +733,12 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.ToTable("IdentityResources"); }); - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.IdentityResourceClaim", b => + modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.IdentityResourceClaim", b => { b.Property("Id") .ValueGeneratedOnAdd() .HasColumnType("int") - .UseIdentityColumn(); + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); b.Property("IdentityResourceId") .HasColumnType("int"); @@ -722,12 +755,12 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.ToTable("IdentityResourceClaims"); }); - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.IdentityResourceProperty", b => + modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.IdentityResourceProperty", b => { b.Property("Id") .ValueGeneratedOnAdd() .HasColumnType("int") - .UseIdentityColumn(); + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); b.Property("IdentityResourceId") .HasColumnType("int"); @@ -749,9 +782,9 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.ToTable("IdentityResourceProperties"); }); - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ApiResourceClaim", b => + modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ApiResourceClaim", b => { - b.HasOne("IdentityServer4.EntityFramework.Entities.ApiResource", "ApiResource") + b.HasOne("Duende.IdentityServer.EntityFramework.Entities.ApiResource", "ApiResource") .WithMany("UserClaims") .HasForeignKey("ApiResourceId") .OnDelete(DeleteBehavior.Cascade) @@ -760,9 +793,9 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.Navigation("ApiResource"); }); - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ApiResourceProperty", b => + modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ApiResourceProperty", b => { - b.HasOne("IdentityServer4.EntityFramework.Entities.ApiResource", "ApiResource") + b.HasOne("Duende.IdentityServer.EntityFramework.Entities.ApiResource", "ApiResource") .WithMany("Properties") .HasForeignKey("ApiResourceId") .OnDelete(DeleteBehavior.Cascade) @@ -771,9 +804,9 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.Navigation("ApiResource"); }); - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ApiResourceScope", b => + modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ApiResourceScope", b => { - b.HasOne("IdentityServer4.EntityFramework.Entities.ApiResource", "ApiResource") + b.HasOne("Duende.IdentityServer.EntityFramework.Entities.ApiResource", "ApiResource") .WithMany("Scopes") .HasForeignKey("ApiResourceId") .OnDelete(DeleteBehavior.Cascade) @@ -782,9 +815,9 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.Navigation("ApiResource"); }); - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ApiResourceSecret", b => + modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ApiResourceSecret", b => { - b.HasOne("IdentityServer4.EntityFramework.Entities.ApiResource", "ApiResource") + b.HasOne("Duende.IdentityServer.EntityFramework.Entities.ApiResource", "ApiResource") .WithMany("Secrets") .HasForeignKey("ApiResourceId") .OnDelete(DeleteBehavior.Cascade) @@ -793,9 +826,9 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.Navigation("ApiResource"); }); - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ApiScopeClaim", b => + modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ApiScopeClaim", b => { - b.HasOne("IdentityServer4.EntityFramework.Entities.ApiScope", "Scope") + b.HasOne("Duende.IdentityServer.EntityFramework.Entities.ApiScope", "Scope") .WithMany("UserClaims") .HasForeignKey("ScopeId") .OnDelete(DeleteBehavior.Cascade) @@ -804,9 +837,9 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.Navigation("Scope"); }); - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ApiScopeProperty", b => + modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ApiScopeProperty", b => { - b.HasOne("IdentityServer4.EntityFramework.Entities.ApiScope", "Scope") + b.HasOne("Duende.IdentityServer.EntityFramework.Entities.ApiScope", "Scope") .WithMany("Properties") .HasForeignKey("ScopeId") .OnDelete(DeleteBehavior.Cascade) @@ -815,9 +848,9 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.Navigation("Scope"); }); - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientClaim", b => + modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ClientClaim", b => { - b.HasOne("IdentityServer4.EntityFramework.Entities.Client", "Client") + b.HasOne("Duende.IdentityServer.EntityFramework.Entities.Client", "Client") .WithMany("Claims") .HasForeignKey("ClientId") .OnDelete(DeleteBehavior.Cascade) @@ -826,9 +859,9 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.Navigation("Client"); }); - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientCorsOrigin", b => + modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ClientCorsOrigin", b => { - b.HasOne("IdentityServer4.EntityFramework.Entities.Client", "Client") + b.HasOne("Duende.IdentityServer.EntityFramework.Entities.Client", "Client") .WithMany("AllowedCorsOrigins") .HasForeignKey("ClientId") .OnDelete(DeleteBehavior.Cascade) @@ -837,9 +870,9 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.Navigation("Client"); }); - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientGrantType", b => + modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ClientGrantType", b => { - b.HasOne("IdentityServer4.EntityFramework.Entities.Client", "Client") + b.HasOne("Duende.IdentityServer.EntityFramework.Entities.Client", "Client") .WithMany("AllowedGrantTypes") .HasForeignKey("ClientId") .OnDelete(DeleteBehavior.Cascade) @@ -848,9 +881,9 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.Navigation("Client"); }); - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientIdPRestriction", b => + modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ClientIdPRestriction", b => { - b.HasOne("IdentityServer4.EntityFramework.Entities.Client", "Client") + b.HasOne("Duende.IdentityServer.EntityFramework.Entities.Client", "Client") .WithMany("IdentityProviderRestrictions") .HasForeignKey("ClientId") .OnDelete(DeleteBehavior.Cascade) @@ -859,9 +892,9 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.Navigation("Client"); }); - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientPostLogoutRedirectUri", b => + modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ClientPostLogoutRedirectUri", b => { - b.HasOne("IdentityServer4.EntityFramework.Entities.Client", "Client") + b.HasOne("Duende.IdentityServer.EntityFramework.Entities.Client", "Client") .WithMany("PostLogoutRedirectUris") .HasForeignKey("ClientId") .OnDelete(DeleteBehavior.Cascade) @@ -870,9 +903,9 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.Navigation("Client"); }); - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientProperty", b => + modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ClientProperty", b => { - b.HasOne("IdentityServer4.EntityFramework.Entities.Client", "Client") + b.HasOne("Duende.IdentityServer.EntityFramework.Entities.Client", "Client") .WithMany("Properties") .HasForeignKey("ClientId") .OnDelete(DeleteBehavior.Cascade) @@ -881,9 +914,9 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.Navigation("Client"); }); - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientRedirectUri", b => + modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ClientRedirectUri", b => { - b.HasOne("IdentityServer4.EntityFramework.Entities.Client", "Client") + b.HasOne("Duende.IdentityServer.EntityFramework.Entities.Client", "Client") .WithMany("RedirectUris") .HasForeignKey("ClientId") .OnDelete(DeleteBehavior.Cascade) @@ -892,9 +925,9 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.Navigation("Client"); }); - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientScope", b => + modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ClientScope", b => { - b.HasOne("IdentityServer4.EntityFramework.Entities.Client", "Client") + b.HasOne("Duende.IdentityServer.EntityFramework.Entities.Client", "Client") .WithMany("AllowedScopes") .HasForeignKey("ClientId") .OnDelete(DeleteBehavior.Cascade) @@ -903,9 +936,9 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.Navigation("Client"); }); - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientSecret", b => + modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ClientSecret", b => { - b.HasOne("IdentityServer4.EntityFramework.Entities.Client", "Client") + b.HasOne("Duende.IdentityServer.EntityFramework.Entities.Client", "Client") .WithMany("ClientSecrets") .HasForeignKey("ClientId") .OnDelete(DeleteBehavior.Cascade) @@ -914,9 +947,9 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.Navigation("Client"); }); - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.IdentityResourceClaim", b => + modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.IdentityResourceClaim", b => { - b.HasOne("IdentityServer4.EntityFramework.Entities.IdentityResource", "IdentityResource") + b.HasOne("Duende.IdentityServer.EntityFramework.Entities.IdentityResource", "IdentityResource") .WithMany("UserClaims") .HasForeignKey("IdentityResourceId") .OnDelete(DeleteBehavior.Cascade) @@ -925,9 +958,9 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.Navigation("IdentityResource"); }); - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.IdentityResourceProperty", b => + modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.IdentityResourceProperty", b => { - b.HasOne("IdentityServer4.EntityFramework.Entities.IdentityResource", "IdentityResource") + b.HasOne("Duende.IdentityServer.EntityFramework.Entities.IdentityResource", "IdentityResource") .WithMany("Properties") .HasForeignKey("IdentityResourceId") .OnDelete(DeleteBehavior.Cascade) @@ -936,7 +969,7 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.Navigation("IdentityResource"); }); - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ApiResource", b => + modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ApiResource", b => { b.Navigation("Properties"); @@ -947,14 +980,14 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.Navigation("UserClaims"); }); - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ApiScope", b => + modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ApiScope", b => { b.Navigation("Properties"); b.Navigation("UserClaims"); }); - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.Client", b => + modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.Client", b => { b.Navigation("AllowedCorsOrigins"); @@ -975,7 +1008,7 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.Navigation("RedirectUris"); }); - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.IdentityResource", b => + modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.IdentityResource", b => { b.Navigation("Properties"); diff --git a/SecurityService.Database/Migrations/ConfigurationDb/20210607105411_InitialMigration.cs b/SecurityService.Database/Migrations/ConfigurationDb/20210607105411_InitialMigration.cs new file mode 100644 index 00000000..03a29182 --- /dev/null +++ b/SecurityService.Database/Migrations/ConfigurationDb/20210607105411_InitialMigration.cs @@ -0,0 +1,678 @@ +namespace SecurityService.Database.Migrations.ConfigurationDb +{ + using System; + using Microsoft.EntityFrameworkCore.Migrations; + + public partial class InitialMigration : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "ApiResources", + columns: table => new + { + Id = table.Column(type: "int", nullable: false) + .Annotation("SqlServer:Identity", "1, 1"), + Enabled = table.Column(type: "bit", nullable: false), + Name = table.Column(type: "nvarchar(200)", maxLength: 200, nullable: false), + DisplayName = table.Column(type: "nvarchar(200)", maxLength: 200, nullable: true), + Description = table.Column(type: "nvarchar(1000)", maxLength: 1000, nullable: true), + AllowedAccessTokenSigningAlgorithms = table.Column(type: "nvarchar(100)", maxLength: 100, nullable: true), + ShowInDiscoveryDocument = table.Column(type: "bit", nullable: false), + RequireResourceIndicator = table.Column(type: "bit", nullable: false), + Created = table.Column(type: "datetime2", nullable: false), + Updated = table.Column(type: "datetime2", nullable: true), + LastAccessed = table.Column(type: "datetime2", nullable: true), + NonEditable = table.Column(type: "bit", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_ApiResources", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "ApiScopes", + columns: table => new + { + Id = table.Column(type: "int", nullable: false) + .Annotation("SqlServer:Identity", "1, 1"), + Enabled = table.Column(type: "bit", nullable: false), + Name = table.Column(type: "nvarchar(200)", maxLength: 200, nullable: false), + DisplayName = table.Column(type: "nvarchar(200)", maxLength: 200, nullable: true), + Description = table.Column(type: "nvarchar(1000)", maxLength: 1000, nullable: true), + Required = table.Column(type: "bit", nullable: false), + Emphasize = table.Column(type: "bit", nullable: false), + ShowInDiscoveryDocument = table.Column(type: "bit", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_ApiScopes", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "Clients", + columns: table => new + { + Id = table.Column(type: "int", nullable: false) + .Annotation("SqlServer:Identity", "1, 1"), + Enabled = table.Column(type: "bit", nullable: false), + ClientId = table.Column(type: "nvarchar(200)", maxLength: 200, nullable: false), + ProtocolType = table.Column(type: "nvarchar(200)", maxLength: 200, nullable: false), + RequireClientSecret = table.Column(type: "bit", nullable: false), + ClientName = table.Column(type: "nvarchar(200)", maxLength: 200, nullable: true), + Description = table.Column(type: "nvarchar(1000)", maxLength: 1000, nullable: true), + ClientUri = table.Column(type: "nvarchar(2000)", maxLength: 2000, nullable: true), + LogoUri = table.Column(type: "nvarchar(2000)", maxLength: 2000, nullable: true), + RequireConsent = table.Column(type: "bit", nullable: false), + AllowRememberConsent = table.Column(type: "bit", nullable: false), + AlwaysIncludeUserClaimsInIdToken = table.Column(type: "bit", nullable: false), + RequirePkce = table.Column(type: "bit", nullable: false), + AllowPlainTextPkce = table.Column(type: "bit", nullable: false), + RequireRequestObject = table.Column(type: "bit", nullable: false), + AllowAccessTokensViaBrowser = table.Column(type: "bit", nullable: false), + FrontChannelLogoutUri = table.Column(type: "nvarchar(2000)", maxLength: 2000, nullable: true), + FrontChannelLogoutSessionRequired = table.Column(type: "bit", nullable: false), + BackChannelLogoutUri = table.Column(type: "nvarchar(2000)", maxLength: 2000, nullable: true), + BackChannelLogoutSessionRequired = table.Column(type: "bit", nullable: false), + AllowOfflineAccess = table.Column(type: "bit", nullable: false), + IdentityTokenLifetime = table.Column(type: "int", nullable: false), + AllowedIdentityTokenSigningAlgorithms = table.Column(type: "nvarchar(100)", maxLength: 100, nullable: true), + AccessTokenLifetime = table.Column(type: "int", nullable: false), + AuthorizationCodeLifetime = table.Column(type: "int", nullable: false), + ConsentLifetime = table.Column(type: "int", nullable: true), + AbsoluteRefreshTokenLifetime = table.Column(type: "int", nullable: false), + SlidingRefreshTokenLifetime = table.Column(type: "int", nullable: false), + RefreshTokenUsage = table.Column(type: "int", nullable: false), + UpdateAccessTokenClaimsOnRefresh = table.Column(type: "bit", nullable: false), + RefreshTokenExpiration = table.Column(type: "int", nullable: false), + AccessTokenType = table.Column(type: "int", nullable: false), + EnableLocalLogin = table.Column(type: "bit", nullable: false), + IncludeJwtId = table.Column(type: "bit", nullable: false), + AlwaysSendClientClaims = table.Column(type: "bit", nullable: false), + ClientClaimsPrefix = table.Column(type: "nvarchar(200)", maxLength: 200, nullable: true), + PairWiseSubjectSalt = table.Column(type: "nvarchar(200)", maxLength: 200, nullable: true), + Created = table.Column(type: "datetime2", nullable: false), + Updated = table.Column(type: "datetime2", nullable: true), + LastAccessed = table.Column(type: "datetime2", nullable: true), + UserSsoLifetime = table.Column(type: "int", nullable: true), + UserCodeType = table.Column(type: "nvarchar(100)", maxLength: 100, nullable: true), + DeviceCodeLifetime = table.Column(type: "int", nullable: false), + NonEditable = table.Column(type: "bit", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_Clients", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "IdentityProviders", + columns: table => new + { + Id = table.Column(type: "int", nullable: false) + .Annotation("SqlServer:Identity", "1, 1"), + Scheme = table.Column(type: "nvarchar(200)", maxLength: 200, nullable: false), + DisplayName = table.Column(type: "nvarchar(200)", maxLength: 200, nullable: true), + Enabled = table.Column(type: "bit", nullable: false), + Type = table.Column(type: "nvarchar(20)", maxLength: 20, nullable: false), + Properties = table.Column(type: "nvarchar(max)", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_IdentityProviders", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "IdentityResources", + columns: table => new + { + Id = table.Column(type: "int", nullable: false) + .Annotation("SqlServer:Identity", "1, 1"), + Enabled = table.Column(type: "bit", nullable: false), + Name = table.Column(type: "nvarchar(200)", maxLength: 200, nullable: false), + DisplayName = table.Column(type: "nvarchar(200)", maxLength: 200, nullable: true), + Description = table.Column(type: "nvarchar(1000)", maxLength: 1000, nullable: true), + Required = table.Column(type: "bit", nullable: false), + Emphasize = table.Column(type: "bit", nullable: false), + ShowInDiscoveryDocument = table.Column(type: "bit", nullable: false), + Created = table.Column(type: "datetime2", nullable: false), + Updated = table.Column(type: "datetime2", nullable: true), + NonEditable = table.Column(type: "bit", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_IdentityResources", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "ApiResourceClaims", + columns: table => new + { + Id = table.Column(type: "int", nullable: false) + .Annotation("SqlServer:Identity", "1, 1"), + ApiResourceId = table.Column(type: "int", nullable: false), + Type = table.Column(type: "nvarchar(200)", maxLength: 200, nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_ApiResourceClaims", x => x.Id); + table.ForeignKey( + name: "FK_ApiResourceClaims_ApiResources_ApiResourceId", + column: x => x.ApiResourceId, + principalTable: "ApiResources", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "ApiResourceProperties", + columns: table => new + { + Id = table.Column(type: "int", nullable: false) + .Annotation("SqlServer:Identity", "1, 1"), + ApiResourceId = table.Column(type: "int", nullable: false), + Key = table.Column(type: "nvarchar(250)", maxLength: 250, nullable: false), + Value = table.Column(type: "nvarchar(2000)", maxLength: 2000, nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_ApiResourceProperties", x => x.Id); + table.ForeignKey( + name: "FK_ApiResourceProperties_ApiResources_ApiResourceId", + column: x => x.ApiResourceId, + principalTable: "ApiResources", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "ApiResourceScopes", + columns: table => new + { + Id = table.Column(type: "int", nullable: false) + .Annotation("SqlServer:Identity", "1, 1"), + Scope = table.Column(type: "nvarchar(200)", maxLength: 200, nullable: false), + ApiResourceId = table.Column(type: "int", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_ApiResourceScopes", x => x.Id); + table.ForeignKey( + name: "FK_ApiResourceScopes_ApiResources_ApiResourceId", + column: x => x.ApiResourceId, + principalTable: "ApiResources", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "ApiResourceSecrets", + columns: table => new + { + Id = table.Column(type: "int", nullable: false) + .Annotation("SqlServer:Identity", "1, 1"), + ApiResourceId = table.Column(type: "int", nullable: false), + Description = table.Column(type: "nvarchar(1000)", maxLength: 1000, nullable: true), + Value = table.Column(type: "nvarchar(4000)", maxLength: 4000, nullable: false), + Expiration = table.Column(type: "datetime2", nullable: true), + Type = table.Column(type: "nvarchar(250)", maxLength: 250, nullable: false), + Created = table.Column(type: "datetime2", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_ApiResourceSecrets", x => x.Id); + table.ForeignKey( + name: "FK_ApiResourceSecrets_ApiResources_ApiResourceId", + column: x => x.ApiResourceId, + principalTable: "ApiResources", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "ApiScopeClaims", + columns: table => new + { + Id = table.Column(type: "int", nullable: false) + .Annotation("SqlServer:Identity", "1, 1"), + ScopeId = table.Column(type: "int", nullable: false), + Type = table.Column(type: "nvarchar(200)", maxLength: 200, nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_ApiScopeClaims", x => x.Id); + table.ForeignKey( + name: "FK_ApiScopeClaims_ApiScopes_ScopeId", + column: x => x.ScopeId, + principalTable: "ApiScopes", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "ApiScopeProperties", + columns: table => new + { + Id = table.Column(type: "int", nullable: false) + .Annotation("SqlServer:Identity", "1, 1"), + ScopeId = table.Column(type: "int", nullable: false), + Key = table.Column(type: "nvarchar(250)", maxLength: 250, nullable: false), + Value = table.Column(type: "nvarchar(2000)", maxLength: 2000, nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_ApiScopeProperties", x => x.Id); + table.ForeignKey( + name: "FK_ApiScopeProperties_ApiScopes_ScopeId", + column: x => x.ScopeId, + principalTable: "ApiScopes", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "ClientClaims", + columns: table => new + { + Id = table.Column(type: "int", nullable: false) + .Annotation("SqlServer:Identity", "1, 1"), + Type = table.Column(type: "nvarchar(250)", maxLength: 250, nullable: false), + Value = table.Column(type: "nvarchar(250)", maxLength: 250, nullable: false), + ClientId = table.Column(type: "int", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_ClientClaims", x => x.Id); + table.ForeignKey( + name: "FK_ClientClaims_Clients_ClientId", + column: x => x.ClientId, + principalTable: "Clients", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "ClientCorsOrigins", + columns: table => new + { + Id = table.Column(type: "int", nullable: false) + .Annotation("SqlServer:Identity", "1, 1"), + Origin = table.Column(type: "nvarchar(150)", maxLength: 150, nullable: false), + ClientId = table.Column(type: "int", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_ClientCorsOrigins", x => x.Id); + table.ForeignKey( + name: "FK_ClientCorsOrigins_Clients_ClientId", + column: x => x.ClientId, + principalTable: "Clients", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "ClientGrantTypes", + columns: table => new + { + Id = table.Column(type: "int", nullable: false) + .Annotation("SqlServer:Identity", "1, 1"), + GrantType = table.Column(type: "nvarchar(250)", maxLength: 250, nullable: false), + ClientId = table.Column(type: "int", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_ClientGrantTypes", x => x.Id); + table.ForeignKey( + name: "FK_ClientGrantTypes_Clients_ClientId", + column: x => x.ClientId, + principalTable: "Clients", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "ClientIdPRestrictions", + columns: table => new + { + Id = table.Column(type: "int", nullable: false) + .Annotation("SqlServer:Identity", "1, 1"), + Provider = table.Column(type: "nvarchar(200)", maxLength: 200, nullable: false), + ClientId = table.Column(type: "int", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_ClientIdPRestrictions", x => x.Id); + table.ForeignKey( + name: "FK_ClientIdPRestrictions_Clients_ClientId", + column: x => x.ClientId, + principalTable: "Clients", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "ClientPostLogoutRedirectUris", + columns: table => new + { + Id = table.Column(type: "int", nullable: false) + .Annotation("SqlServer:Identity", "1, 1"), + PostLogoutRedirectUri = table.Column(type: "nvarchar(2000)", maxLength: 2000, nullable: false), + ClientId = table.Column(type: "int", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_ClientPostLogoutRedirectUris", x => x.Id); + table.ForeignKey( + name: "FK_ClientPostLogoutRedirectUris_Clients_ClientId", + column: x => x.ClientId, + principalTable: "Clients", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "ClientProperties", + columns: table => new + { + Id = table.Column(type: "int", nullable: false) + .Annotation("SqlServer:Identity", "1, 1"), + ClientId = table.Column(type: "int", nullable: false), + Key = table.Column(type: "nvarchar(250)", maxLength: 250, nullable: false), + Value = table.Column(type: "nvarchar(2000)", maxLength: 2000, nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_ClientProperties", x => x.Id); + table.ForeignKey( + name: "FK_ClientProperties_Clients_ClientId", + column: x => x.ClientId, + principalTable: "Clients", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "ClientRedirectUris", + columns: table => new + { + Id = table.Column(type: "int", nullable: false) + .Annotation("SqlServer:Identity", "1, 1"), + RedirectUri = table.Column(type: "nvarchar(2000)", maxLength: 2000, nullable: false), + ClientId = table.Column(type: "int", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_ClientRedirectUris", x => x.Id); + table.ForeignKey( + name: "FK_ClientRedirectUris_Clients_ClientId", + column: x => x.ClientId, + principalTable: "Clients", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "ClientScopes", + columns: table => new + { + Id = table.Column(type: "int", nullable: false) + .Annotation("SqlServer:Identity", "1, 1"), + Scope = table.Column(type: "nvarchar(200)", maxLength: 200, nullable: false), + ClientId = table.Column(type: "int", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_ClientScopes", x => x.Id); + table.ForeignKey( + name: "FK_ClientScopes_Clients_ClientId", + column: x => x.ClientId, + principalTable: "Clients", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "ClientSecrets", + columns: table => new + { + Id = table.Column(type: "int", nullable: false) + .Annotation("SqlServer:Identity", "1, 1"), + ClientId = table.Column(type: "int", nullable: false), + Description = table.Column(type: "nvarchar(2000)", maxLength: 2000, nullable: true), + Value = table.Column(type: "nvarchar(4000)", maxLength: 4000, nullable: false), + Expiration = table.Column(type: "datetime2", nullable: true), + Type = table.Column(type: "nvarchar(250)", maxLength: 250, nullable: false), + Created = table.Column(type: "datetime2", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_ClientSecrets", x => x.Id); + table.ForeignKey( + name: "FK_ClientSecrets_Clients_ClientId", + column: x => x.ClientId, + principalTable: "Clients", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "IdentityResourceClaims", + columns: table => new + { + Id = table.Column(type: "int", nullable: false) + .Annotation("SqlServer:Identity", "1, 1"), + IdentityResourceId = table.Column(type: "int", nullable: false), + Type = table.Column(type: "nvarchar(200)", maxLength: 200, nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_IdentityResourceClaims", x => x.Id); + table.ForeignKey( + name: "FK_IdentityResourceClaims_IdentityResources_IdentityResourceId", + column: x => x.IdentityResourceId, + principalTable: "IdentityResources", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "IdentityResourceProperties", + columns: table => new + { + Id = table.Column(type: "int", nullable: false) + .Annotation("SqlServer:Identity", "1, 1"), + IdentityResourceId = table.Column(type: "int", nullable: false), + Key = table.Column(type: "nvarchar(250)", maxLength: 250, nullable: false), + Value = table.Column(type: "nvarchar(2000)", maxLength: 2000, nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_IdentityResourceProperties", x => x.Id); + table.ForeignKey( + name: "FK_IdentityResourceProperties_IdentityResources_IdentityResourceId", + column: x => x.IdentityResourceId, + principalTable: "IdentityResources", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateIndex( + name: "IX_ApiResourceClaims_ApiResourceId", + table: "ApiResourceClaims", + column: "ApiResourceId"); + + migrationBuilder.CreateIndex( + name: "IX_ApiResourceProperties_ApiResourceId", + table: "ApiResourceProperties", + column: "ApiResourceId"); + + migrationBuilder.CreateIndex( + name: "IX_ApiResources_Name", + table: "ApiResources", + column: "Name", + unique: true); + + migrationBuilder.CreateIndex( + name: "IX_ApiResourceScopes_ApiResourceId", + table: "ApiResourceScopes", + column: "ApiResourceId"); + + migrationBuilder.CreateIndex( + name: "IX_ApiResourceSecrets_ApiResourceId", + table: "ApiResourceSecrets", + column: "ApiResourceId"); + + migrationBuilder.CreateIndex( + name: "IX_ApiScopeClaims_ScopeId", + table: "ApiScopeClaims", + column: "ScopeId"); + + migrationBuilder.CreateIndex( + name: "IX_ApiScopeProperties_ScopeId", + table: "ApiScopeProperties", + column: "ScopeId"); + + migrationBuilder.CreateIndex( + name: "IX_ApiScopes_Name", + table: "ApiScopes", + column: "Name", + unique: true); + + migrationBuilder.CreateIndex( + name: "IX_ClientClaims_ClientId", + table: "ClientClaims", + column: "ClientId"); + + migrationBuilder.CreateIndex( + name: "IX_ClientCorsOrigins_ClientId", + table: "ClientCorsOrigins", + column: "ClientId"); + + migrationBuilder.CreateIndex( + name: "IX_ClientGrantTypes_ClientId", + table: "ClientGrantTypes", + column: "ClientId"); + + migrationBuilder.CreateIndex( + name: "IX_ClientIdPRestrictions_ClientId", + table: "ClientIdPRestrictions", + column: "ClientId"); + + migrationBuilder.CreateIndex( + name: "IX_ClientPostLogoutRedirectUris_ClientId", + table: "ClientPostLogoutRedirectUris", + column: "ClientId"); + + migrationBuilder.CreateIndex( + name: "IX_ClientProperties_ClientId", + table: "ClientProperties", + column: "ClientId"); + + migrationBuilder.CreateIndex( + name: "IX_ClientRedirectUris_ClientId", + table: "ClientRedirectUris", + column: "ClientId"); + + migrationBuilder.CreateIndex( + name: "IX_Clients_ClientId", + table: "Clients", + column: "ClientId", + unique: true); + + migrationBuilder.CreateIndex( + name: "IX_ClientScopes_ClientId", + table: "ClientScopes", + column: "ClientId"); + + migrationBuilder.CreateIndex( + name: "IX_ClientSecrets_ClientId", + table: "ClientSecrets", + column: "ClientId"); + + migrationBuilder.CreateIndex( + name: "IX_IdentityResourceClaims_IdentityResourceId", + table: "IdentityResourceClaims", + column: "IdentityResourceId"); + + migrationBuilder.CreateIndex( + name: "IX_IdentityResourceProperties_IdentityResourceId", + table: "IdentityResourceProperties", + column: "IdentityResourceId"); + + migrationBuilder.CreateIndex( + name: "IX_IdentityResources_Name", + table: "IdentityResources", + column: "Name", + unique: true); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "ApiResourceClaims"); + + migrationBuilder.DropTable( + name: "ApiResourceProperties"); + + migrationBuilder.DropTable( + name: "ApiResourceScopes"); + + migrationBuilder.DropTable( + name: "ApiResourceSecrets"); + + migrationBuilder.DropTable( + name: "ApiScopeClaims"); + + migrationBuilder.DropTable( + name: "ApiScopeProperties"); + + migrationBuilder.DropTable( + name: "ClientClaims"); + + migrationBuilder.DropTable( + name: "ClientCorsOrigins"); + + migrationBuilder.DropTable( + name: "ClientGrantTypes"); + + migrationBuilder.DropTable( + name: "ClientIdPRestrictions"); + + migrationBuilder.DropTable( + name: "ClientPostLogoutRedirectUris"); + + migrationBuilder.DropTable( + name: "ClientProperties"); + + migrationBuilder.DropTable( + name: "ClientRedirectUris"); + + migrationBuilder.DropTable( + name: "ClientScopes"); + + migrationBuilder.DropTable( + name: "ClientSecrets"); + + migrationBuilder.DropTable( + name: "IdentityProviders"); + + migrationBuilder.DropTable( + name: "IdentityResourceClaims"); + + migrationBuilder.DropTable( + name: "IdentityResourceProperties"); + + migrationBuilder.DropTable( + name: "ApiResources"); + + migrationBuilder.DropTable( + name: "ApiScopes"); + + migrationBuilder.DropTable( + name: "Clients"); + + migrationBuilder.DropTable( + name: "IdentityResources"); + } + } +} diff --git a/SecurityService.Database/Migrations/ConfigurationDbContext/ConfigurationDbContextModelSnapshot.cs b/SecurityService.Database/Migrations/ConfigurationDb/ConfigurationDbContextModelSnapshot.cs similarity index 73% rename from SecurityService.Database/Migrations/ConfigurationDbContext/ConfigurationDbContextModelSnapshot.cs rename to SecurityService.Database/Migrations/ConfigurationDb/ConfigurationDbContextModelSnapshot.cs index c13b6da5..76a15880 100644 --- a/SecurityService.Database/Migrations/ConfigurationDbContext/ConfigurationDbContextModelSnapshot.cs +++ b/SecurityService.Database/Migrations/ConfigurationDb/ConfigurationDbContextModelSnapshot.cs @@ -1,14 +1,13 @@ // -using System; -using IdentityServer4.EntityFramework.DbContexts; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; - -namespace SecurityService.Database.Migrations.ConfigurationDbContext + +namespace SecurityService.Database.Migrations.IdentityServer.ConfigurationDb { - using ConfigurationDbContext = IdentityServer4.EntityFramework.DbContexts.ConfigurationDbContext; + using System; + using Duende.IdentityServer.EntityFramework.DbContexts; + using Microsoft.EntityFrameworkCore; + using Microsoft.EntityFrameworkCore.Infrastructure; + using Microsoft.EntityFrameworkCore.Metadata; + using Microsoft.EntityFrameworkCore.Migrations; [DbContext(typeof(ConfigurationDbContext))] partial class ConfigurationDbContextModelSnapshot : ModelSnapshot @@ -17,16 +16,16 @@ protected override void BuildModel(ModelBuilder modelBuilder) { #pragma warning disable 612, 618 modelBuilder - .UseIdentityColumns() .HasAnnotation("Relational:MaxIdentifierLength", 128) - .HasAnnotation("ProductVersion", "5.0.2"); + .HasAnnotation("ProductVersion", "5.0.6") + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ApiResource", b => + modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ApiResource", b => { b.Property("Id") .ValueGeneratedOnAdd() .HasColumnType("int") - .UseIdentityColumn(); + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); b.Property("AllowedAccessTokenSigningAlgorithms") .HasMaxLength(100) @@ -57,6 +56,9 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Property("NonEditable") .HasColumnType("bit"); + b.Property("RequireResourceIndicator") + .HasColumnType("bit"); + b.Property("ShowInDiscoveryDocument") .HasColumnType("bit"); @@ -71,12 +73,12 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.ToTable("ApiResources"); }); - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ApiResourceClaim", b => + modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ApiResourceClaim", b => { b.Property("Id") .ValueGeneratedOnAdd() .HasColumnType("int") - .UseIdentityColumn(); + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); b.Property("ApiResourceId") .HasColumnType("int"); @@ -93,12 +95,12 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.ToTable("ApiResourceClaims"); }); - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ApiResourceProperty", b => + modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ApiResourceProperty", b => { b.Property("Id") .ValueGeneratedOnAdd() .HasColumnType("int") - .UseIdentityColumn(); + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); b.Property("ApiResourceId") .HasColumnType("int"); @@ -120,12 +122,12 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.ToTable("ApiResourceProperties"); }); - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ApiResourceScope", b => + modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ApiResourceScope", b => { b.Property("Id") .ValueGeneratedOnAdd() .HasColumnType("int") - .UseIdentityColumn(); + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); b.Property("ApiResourceId") .HasColumnType("int"); @@ -142,12 +144,12 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.ToTable("ApiResourceScopes"); }); - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ApiResourceSecret", b => + modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ApiResourceSecret", b => { b.Property("Id") .ValueGeneratedOnAdd() .HasColumnType("int") - .UseIdentityColumn(); + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); b.Property("ApiResourceId") .HasColumnType("int"); @@ -179,12 +181,12 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.ToTable("ApiResourceSecrets"); }); - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ApiScope", b => + modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ApiScope", b => { b.Property("Id") .ValueGeneratedOnAdd() .HasColumnType("int") - .UseIdentityColumn(); + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); b.Property("Description") .HasMaxLength(1000) @@ -219,12 +221,12 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.ToTable("ApiScopes"); }); - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ApiScopeClaim", b => + modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ApiScopeClaim", b => { b.Property("Id") .ValueGeneratedOnAdd() .HasColumnType("int") - .UseIdentityColumn(); + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); b.Property("ScopeId") .HasColumnType("int"); @@ -241,12 +243,12 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.ToTable("ApiScopeClaims"); }); - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ApiScopeProperty", b => + modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ApiScopeProperty", b => { b.Property("Id") .ValueGeneratedOnAdd() .HasColumnType("int") - .UseIdentityColumn(); + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); b.Property("Key") .IsRequired() @@ -268,12 +270,12 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.ToTable("ApiScopeProperties"); }); - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.Client", b => + modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.Client", b => { b.Property("Id") .ValueGeneratedOnAdd() .HasColumnType("int") - .UseIdentityColumn(); + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); b.Property("AbsoluteRefreshTokenLifetime") .HasColumnType("int"); @@ -426,12 +428,12 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.ToTable("Clients"); }); - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientClaim", b => + modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ClientClaim", b => { b.Property("Id") .ValueGeneratedOnAdd() .HasColumnType("int") - .UseIdentityColumn(); + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); b.Property("ClientId") .HasColumnType("int"); @@ -453,12 +455,12 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.ToTable("ClientClaims"); }); - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientCorsOrigin", b => + modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ClientCorsOrigin", b => { b.Property("Id") .ValueGeneratedOnAdd() .HasColumnType("int") - .UseIdentityColumn(); + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); b.Property("ClientId") .HasColumnType("int"); @@ -475,12 +477,12 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.ToTable("ClientCorsOrigins"); }); - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientGrantType", b => + modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ClientGrantType", b => { b.Property("Id") .ValueGeneratedOnAdd() .HasColumnType("int") - .UseIdentityColumn(); + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); b.Property("ClientId") .HasColumnType("int"); @@ -497,12 +499,12 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.ToTable("ClientGrantTypes"); }); - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientIdPRestriction", b => + modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ClientIdPRestriction", b => { b.Property("Id") .ValueGeneratedOnAdd() .HasColumnType("int") - .UseIdentityColumn(); + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); b.Property("ClientId") .HasColumnType("int"); @@ -519,12 +521,12 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.ToTable("ClientIdPRestrictions"); }); - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientPostLogoutRedirectUri", b => + modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ClientPostLogoutRedirectUri", b => { b.Property("Id") .ValueGeneratedOnAdd() .HasColumnType("int") - .UseIdentityColumn(); + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); b.Property("ClientId") .HasColumnType("int"); @@ -541,12 +543,12 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.ToTable("ClientPostLogoutRedirectUris"); }); - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientProperty", b => + modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ClientProperty", b => { b.Property("Id") .ValueGeneratedOnAdd() .HasColumnType("int") - .UseIdentityColumn(); + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); b.Property("ClientId") .HasColumnType("int"); @@ -568,12 +570,12 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.ToTable("ClientProperties"); }); - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientRedirectUri", b => + modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ClientRedirectUri", b => { b.Property("Id") .ValueGeneratedOnAdd() .HasColumnType("int") - .UseIdentityColumn(); + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); b.Property("ClientId") .HasColumnType("int"); @@ -590,12 +592,12 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.ToTable("ClientRedirectUris"); }); - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientScope", b => + modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ClientScope", b => { b.Property("Id") .ValueGeneratedOnAdd() .HasColumnType("int") - .UseIdentityColumn(); + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); b.Property("ClientId") .HasColumnType("int"); @@ -612,12 +614,12 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.ToTable("ClientScopes"); }); - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientSecret", b => + modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ClientSecret", b => { b.Property("Id") .ValueGeneratedOnAdd() .HasColumnType("int") - .UseIdentityColumn(); + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); b.Property("ClientId") .HasColumnType("int"); @@ -649,12 +651,44 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.ToTable("ClientSecrets"); }); - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.IdentityResource", b => + modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.IdentityProvider", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); + + b.Property("DisplayName") + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.Property("Enabled") + .HasColumnType("bit"); + + b.Property("Properties") + .HasColumnType("nvarchar(max)"); + + b.Property("Scheme") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.Property("Type") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("nvarchar(20)"); + + b.HasKey("Id"); + + b.ToTable("IdentityProviders"); + }); + + modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.IdentityResource", b => { b.Property("Id") .ValueGeneratedOnAdd() .HasColumnType("int") - .UseIdentityColumn(); + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); b.Property("Created") .HasColumnType("datetime2"); @@ -698,12 +732,12 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.ToTable("IdentityResources"); }); - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.IdentityResourceClaim", b => + modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.IdentityResourceClaim", b => { b.Property("Id") .ValueGeneratedOnAdd() .HasColumnType("int") - .UseIdentityColumn(); + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); b.Property("IdentityResourceId") .HasColumnType("int"); @@ -720,12 +754,12 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.ToTable("IdentityResourceClaims"); }); - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.IdentityResourceProperty", b => + modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.IdentityResourceProperty", b => { b.Property("Id") .ValueGeneratedOnAdd() .HasColumnType("int") - .UseIdentityColumn(); + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); b.Property("IdentityResourceId") .HasColumnType("int"); @@ -747,9 +781,9 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.ToTable("IdentityResourceProperties"); }); - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ApiResourceClaim", b => + modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ApiResourceClaim", b => { - b.HasOne("IdentityServer4.EntityFramework.Entities.ApiResource", "ApiResource") + b.HasOne("Duende.IdentityServer.EntityFramework.Entities.ApiResource", "ApiResource") .WithMany("UserClaims") .HasForeignKey("ApiResourceId") .OnDelete(DeleteBehavior.Cascade) @@ -758,9 +792,9 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Navigation("ApiResource"); }); - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ApiResourceProperty", b => + modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ApiResourceProperty", b => { - b.HasOne("IdentityServer4.EntityFramework.Entities.ApiResource", "ApiResource") + b.HasOne("Duende.IdentityServer.EntityFramework.Entities.ApiResource", "ApiResource") .WithMany("Properties") .HasForeignKey("ApiResourceId") .OnDelete(DeleteBehavior.Cascade) @@ -769,9 +803,9 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Navigation("ApiResource"); }); - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ApiResourceScope", b => + modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ApiResourceScope", b => { - b.HasOne("IdentityServer4.EntityFramework.Entities.ApiResource", "ApiResource") + b.HasOne("Duende.IdentityServer.EntityFramework.Entities.ApiResource", "ApiResource") .WithMany("Scopes") .HasForeignKey("ApiResourceId") .OnDelete(DeleteBehavior.Cascade) @@ -780,9 +814,9 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Navigation("ApiResource"); }); - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ApiResourceSecret", b => + modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ApiResourceSecret", b => { - b.HasOne("IdentityServer4.EntityFramework.Entities.ApiResource", "ApiResource") + b.HasOne("Duende.IdentityServer.EntityFramework.Entities.ApiResource", "ApiResource") .WithMany("Secrets") .HasForeignKey("ApiResourceId") .OnDelete(DeleteBehavior.Cascade) @@ -791,9 +825,9 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Navigation("ApiResource"); }); - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ApiScopeClaim", b => + modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ApiScopeClaim", b => { - b.HasOne("IdentityServer4.EntityFramework.Entities.ApiScope", "Scope") + b.HasOne("Duende.IdentityServer.EntityFramework.Entities.ApiScope", "Scope") .WithMany("UserClaims") .HasForeignKey("ScopeId") .OnDelete(DeleteBehavior.Cascade) @@ -802,9 +836,9 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Navigation("Scope"); }); - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ApiScopeProperty", b => + modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ApiScopeProperty", b => { - b.HasOne("IdentityServer4.EntityFramework.Entities.ApiScope", "Scope") + b.HasOne("Duende.IdentityServer.EntityFramework.Entities.ApiScope", "Scope") .WithMany("Properties") .HasForeignKey("ScopeId") .OnDelete(DeleteBehavior.Cascade) @@ -813,9 +847,9 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Navigation("Scope"); }); - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientClaim", b => + modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ClientClaim", b => { - b.HasOne("IdentityServer4.EntityFramework.Entities.Client", "Client") + b.HasOne("Duende.IdentityServer.EntityFramework.Entities.Client", "Client") .WithMany("Claims") .HasForeignKey("ClientId") .OnDelete(DeleteBehavior.Cascade) @@ -824,9 +858,9 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Navigation("Client"); }); - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientCorsOrigin", b => + modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ClientCorsOrigin", b => { - b.HasOne("IdentityServer4.EntityFramework.Entities.Client", "Client") + b.HasOne("Duende.IdentityServer.EntityFramework.Entities.Client", "Client") .WithMany("AllowedCorsOrigins") .HasForeignKey("ClientId") .OnDelete(DeleteBehavior.Cascade) @@ -835,9 +869,9 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Navigation("Client"); }); - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientGrantType", b => + modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ClientGrantType", b => { - b.HasOne("IdentityServer4.EntityFramework.Entities.Client", "Client") + b.HasOne("Duende.IdentityServer.EntityFramework.Entities.Client", "Client") .WithMany("AllowedGrantTypes") .HasForeignKey("ClientId") .OnDelete(DeleteBehavior.Cascade) @@ -846,9 +880,9 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Navigation("Client"); }); - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientIdPRestriction", b => + modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ClientIdPRestriction", b => { - b.HasOne("IdentityServer4.EntityFramework.Entities.Client", "Client") + b.HasOne("Duende.IdentityServer.EntityFramework.Entities.Client", "Client") .WithMany("IdentityProviderRestrictions") .HasForeignKey("ClientId") .OnDelete(DeleteBehavior.Cascade) @@ -857,9 +891,9 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Navigation("Client"); }); - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientPostLogoutRedirectUri", b => + modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ClientPostLogoutRedirectUri", b => { - b.HasOne("IdentityServer4.EntityFramework.Entities.Client", "Client") + b.HasOne("Duende.IdentityServer.EntityFramework.Entities.Client", "Client") .WithMany("PostLogoutRedirectUris") .HasForeignKey("ClientId") .OnDelete(DeleteBehavior.Cascade) @@ -868,9 +902,9 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Navigation("Client"); }); - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientProperty", b => + modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ClientProperty", b => { - b.HasOne("IdentityServer4.EntityFramework.Entities.Client", "Client") + b.HasOne("Duende.IdentityServer.EntityFramework.Entities.Client", "Client") .WithMany("Properties") .HasForeignKey("ClientId") .OnDelete(DeleteBehavior.Cascade) @@ -879,9 +913,9 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Navigation("Client"); }); - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientRedirectUri", b => + modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ClientRedirectUri", b => { - b.HasOne("IdentityServer4.EntityFramework.Entities.Client", "Client") + b.HasOne("Duende.IdentityServer.EntityFramework.Entities.Client", "Client") .WithMany("RedirectUris") .HasForeignKey("ClientId") .OnDelete(DeleteBehavior.Cascade) @@ -890,9 +924,9 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Navigation("Client"); }); - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientScope", b => + modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ClientScope", b => { - b.HasOne("IdentityServer4.EntityFramework.Entities.Client", "Client") + b.HasOne("Duende.IdentityServer.EntityFramework.Entities.Client", "Client") .WithMany("AllowedScopes") .HasForeignKey("ClientId") .OnDelete(DeleteBehavior.Cascade) @@ -901,9 +935,9 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Navigation("Client"); }); - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientSecret", b => + modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ClientSecret", b => { - b.HasOne("IdentityServer4.EntityFramework.Entities.Client", "Client") + b.HasOne("Duende.IdentityServer.EntityFramework.Entities.Client", "Client") .WithMany("ClientSecrets") .HasForeignKey("ClientId") .OnDelete(DeleteBehavior.Cascade) @@ -912,9 +946,9 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Navigation("Client"); }); - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.IdentityResourceClaim", b => + modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.IdentityResourceClaim", b => { - b.HasOne("IdentityServer4.EntityFramework.Entities.IdentityResource", "IdentityResource") + b.HasOne("Duende.IdentityServer.EntityFramework.Entities.IdentityResource", "IdentityResource") .WithMany("UserClaims") .HasForeignKey("IdentityResourceId") .OnDelete(DeleteBehavior.Cascade) @@ -923,9 +957,9 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Navigation("IdentityResource"); }); - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.IdentityResourceProperty", b => + modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.IdentityResourceProperty", b => { - b.HasOne("IdentityServer4.EntityFramework.Entities.IdentityResource", "IdentityResource") + b.HasOne("Duende.IdentityServer.EntityFramework.Entities.IdentityResource", "IdentityResource") .WithMany("Properties") .HasForeignKey("IdentityResourceId") .OnDelete(DeleteBehavior.Cascade) @@ -934,7 +968,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Navigation("IdentityResource"); }); - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ApiResource", b => + modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ApiResource", b => { b.Navigation("Properties"); @@ -945,14 +979,14 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Navigation("UserClaims"); }); - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ApiScope", b => + modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ApiScope", b => { b.Navigation("Properties"); b.Navigation("UserClaims"); }); - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.Client", b => + modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.Client", b => { b.Navigation("AllowedCorsOrigins"); @@ -973,7 +1007,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Navigation("RedirectUris"); }); - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.IdentityResource", b => + modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.IdentityResource", b => { b.Navigation("Properties"); diff --git a/SecurityService.Database/Migrations/ConfigurationDbContext/20191105215403_InitialDbMigration.Designer.cs b/SecurityService.Database/Migrations/ConfigurationDbContext/20191105215403_InitialDbMigration.Designer.cs deleted file mode 100644 index d331a580..00000000 --- a/SecurityService.Database/Migrations/ConfigurationDbContext/20191105215403_InitialDbMigration.Designer.cs +++ /dev/null @@ -1,837 +0,0 @@ -// -using System; -using IdentityServer4.EntityFramework.DbContexts; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; - -namespace SecurityService.Database.Migrations.ConfigurationDbContext -{ - using ConfigurationDbContext = IdentityServer4.EntityFramework.DbContexts.ConfigurationDbContext; - - [DbContext(typeof(ConfigurationDbContext))] - [Migration("20191105215403_InitialDbMigration")] - partial class InitialDbMigration - { - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("ProductVersion", "3.0.0") - .HasAnnotation("Relational:MaxIdentifierLength", 128) - .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); - - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ApiResource", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int") - .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); - - b.Property("Created") - .HasColumnType("datetime2"); - - b.Property("Description") - .HasColumnType("nvarchar(1000)") - .HasMaxLength(1000); - - b.Property("DisplayName") - .HasColumnType("nvarchar(200)") - .HasMaxLength(200); - - b.Property("Enabled") - .HasColumnType("bit"); - - b.Property("LastAccessed") - .HasColumnType("datetime2"); - - b.Property("Name") - .IsRequired() - .HasColumnType("nvarchar(200)") - .HasMaxLength(200); - - b.Property("NonEditable") - .HasColumnType("bit"); - - b.Property("Updated") - .HasColumnType("datetime2"); - - b.HasKey("Id"); - - b.HasIndex("Name") - .IsUnique(); - - b.ToTable("ApiResources"); - }); - - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ApiResourceClaim", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int") - .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); - - b.Property("ApiResourceId") - .HasColumnType("int"); - - b.Property("Type") - .IsRequired() - .HasColumnType("nvarchar(200)") - .HasMaxLength(200); - - b.HasKey("Id"); - - b.HasIndex("ApiResourceId"); - - b.ToTable("ApiClaims"); - }); - - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ApiResourceProperty", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int") - .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); - - b.Property("ApiResourceId") - .HasColumnType("int"); - - b.Property("Key") - .IsRequired() - .HasColumnType("nvarchar(250)") - .HasMaxLength(250); - - b.Property("Value") - .IsRequired() - .HasColumnType("nvarchar(2000)") - .HasMaxLength(2000); - - b.HasKey("Id"); - - b.HasIndex("ApiResourceId"); - - b.ToTable("ApiProperties"); - }); - - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ApiScope", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int") - .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); - - b.Property("ApiResourceId") - .HasColumnType("int"); - - b.Property("Description") - .HasColumnType("nvarchar(1000)") - .HasMaxLength(1000); - - b.Property("DisplayName") - .HasColumnType("nvarchar(200)") - .HasMaxLength(200); - - b.Property("Emphasize") - .HasColumnType("bit"); - - b.Property("Name") - .IsRequired() - .HasColumnType("nvarchar(200)") - .HasMaxLength(200); - - b.Property("Required") - .HasColumnType("bit"); - - b.Property("ShowInDiscoveryDocument") - .HasColumnType("bit"); - - b.HasKey("Id"); - - b.HasIndex("ApiResourceId"); - - b.HasIndex("Name") - .IsUnique(); - - b.ToTable("ApiScopes"); - }); - - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ApiScopeClaim", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int") - .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); - - b.Property("ApiScopeId") - .HasColumnType("int"); - - b.Property("Type") - .IsRequired() - .HasColumnType("nvarchar(200)") - .HasMaxLength(200); - - b.HasKey("Id"); - - b.HasIndex("ApiScopeId"); - - b.ToTable("ApiScopeClaims"); - }); - - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ApiSecret", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int") - .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); - - b.Property("ApiResourceId") - .HasColumnType("int"); - - b.Property("Created") - .HasColumnType("datetime2"); - - b.Property("Description") - .HasColumnType("nvarchar(1000)") - .HasMaxLength(1000); - - b.Property("Expiration") - .HasColumnType("datetime2"); - - b.Property("Type") - .IsRequired() - .HasColumnType("nvarchar(250)") - .HasMaxLength(250); - - b.Property("Value") - .IsRequired() - .HasColumnType("nvarchar(4000)") - .HasMaxLength(4000); - - b.HasKey("Id"); - - b.HasIndex("ApiResourceId"); - - b.ToTable("ApiSecrets"); - }); - - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.Client", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int") - .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); - - b.Property("AbsoluteRefreshTokenLifetime") - .HasColumnType("int"); - - b.Property("AccessTokenLifetime") - .HasColumnType("int"); - - b.Property("AccessTokenType") - .HasColumnType("int"); - - b.Property("AllowAccessTokensViaBrowser") - .HasColumnType("bit"); - - b.Property("AllowOfflineAccess") - .HasColumnType("bit"); - - b.Property("AllowPlainTextPkce") - .HasColumnType("bit"); - - b.Property("AllowRememberConsent") - .HasColumnType("bit"); - - b.Property("AlwaysIncludeUserClaimsInIdToken") - .HasColumnType("bit"); - - b.Property("AlwaysSendClientClaims") - .HasColumnType("bit"); - - b.Property("AuthorizationCodeLifetime") - .HasColumnType("int"); - - b.Property("BackChannelLogoutSessionRequired") - .HasColumnType("bit"); - - b.Property("BackChannelLogoutUri") - .HasColumnType("nvarchar(2000)") - .HasMaxLength(2000); - - b.Property("ClientClaimsPrefix") - .HasColumnType("nvarchar(200)") - .HasMaxLength(200); - - b.Property("ClientId") - .IsRequired() - .HasColumnType("nvarchar(200)") - .HasMaxLength(200); - - b.Property("ClientName") - .HasColumnType("nvarchar(200)") - .HasMaxLength(200); - - b.Property("ClientUri") - .HasColumnType("nvarchar(2000)") - .HasMaxLength(2000); - - b.Property("ConsentLifetime") - .HasColumnType("int"); - - b.Property("Created") - .HasColumnType("datetime2"); - - b.Property("Description") - .HasColumnType("nvarchar(1000)") - .HasMaxLength(1000); - - b.Property("DeviceCodeLifetime") - .HasColumnType("int"); - - b.Property("EnableLocalLogin") - .HasColumnType("bit"); - - b.Property("Enabled") - .HasColumnType("bit"); - - b.Property("FrontChannelLogoutSessionRequired") - .HasColumnType("bit"); - - b.Property("FrontChannelLogoutUri") - .HasColumnType("nvarchar(2000)") - .HasMaxLength(2000); - - b.Property("IdentityTokenLifetime") - .HasColumnType("int"); - - b.Property("IncludeJwtId") - .HasColumnType("bit"); - - b.Property("LastAccessed") - .HasColumnType("datetime2"); - - b.Property("LogoUri") - .HasColumnType("nvarchar(2000)") - .HasMaxLength(2000); - - b.Property("NonEditable") - .HasColumnType("bit"); - - b.Property("PairWiseSubjectSalt") - .HasColumnType("nvarchar(200)") - .HasMaxLength(200); - - b.Property("ProtocolType") - .IsRequired() - .HasColumnType("nvarchar(200)") - .HasMaxLength(200); - - b.Property("RefreshTokenExpiration") - .HasColumnType("int"); - - b.Property("RefreshTokenUsage") - .HasColumnType("int"); - - b.Property("RequireClientSecret") - .HasColumnType("bit"); - - b.Property("RequireConsent") - .HasColumnType("bit"); - - b.Property("RequirePkce") - .HasColumnType("bit"); - - b.Property("SlidingRefreshTokenLifetime") - .HasColumnType("int"); - - b.Property("UpdateAccessTokenClaimsOnRefresh") - .HasColumnType("bit"); - - b.Property("Updated") - .HasColumnType("datetime2"); - - b.Property("UserCodeType") - .HasColumnType("nvarchar(100)") - .HasMaxLength(100); - - b.Property("UserSsoLifetime") - .HasColumnType("int"); - - b.HasKey("Id"); - - b.HasIndex("ClientId") - .IsUnique(); - - b.ToTable("Clients"); - }); - - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientClaim", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int") - .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); - - b.Property("ClientId") - .HasColumnType("int"); - - b.Property("Type") - .IsRequired() - .HasColumnType("nvarchar(250)") - .HasMaxLength(250); - - b.Property("Value") - .IsRequired() - .HasColumnType("nvarchar(250)") - .HasMaxLength(250); - - b.HasKey("Id"); - - b.HasIndex("ClientId"); - - b.ToTable("ClientClaims"); - }); - - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientCorsOrigin", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int") - .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); - - b.Property("ClientId") - .HasColumnType("int"); - - b.Property("Origin") - .IsRequired() - .HasColumnType("nvarchar(150)") - .HasMaxLength(150); - - b.HasKey("Id"); - - b.HasIndex("ClientId"); - - b.ToTable("ClientCorsOrigins"); - }); - - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientGrantType", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int") - .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); - - b.Property("ClientId") - .HasColumnType("int"); - - b.Property("GrantType") - .IsRequired() - .HasColumnType("nvarchar(250)") - .HasMaxLength(250); - - b.HasKey("Id"); - - b.HasIndex("ClientId"); - - b.ToTable("ClientGrantTypes"); - }); - - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientIdPRestriction", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int") - .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); - - b.Property("ClientId") - .HasColumnType("int"); - - b.Property("Provider") - .IsRequired() - .HasColumnType("nvarchar(200)") - .HasMaxLength(200); - - b.HasKey("Id"); - - b.HasIndex("ClientId"); - - b.ToTable("ClientIdPRestrictions"); - }); - - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientPostLogoutRedirectUri", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int") - .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); - - b.Property("ClientId") - .HasColumnType("int"); - - b.Property("PostLogoutRedirectUri") - .IsRequired() - .HasColumnType("nvarchar(2000)") - .HasMaxLength(2000); - - b.HasKey("Id"); - - b.HasIndex("ClientId"); - - b.ToTable("ClientPostLogoutRedirectUris"); - }); - - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientProperty", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int") - .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); - - b.Property("ClientId") - .HasColumnType("int"); - - b.Property("Key") - .IsRequired() - .HasColumnType("nvarchar(250)") - .HasMaxLength(250); - - b.Property("Value") - .IsRequired() - .HasColumnType("nvarchar(2000)") - .HasMaxLength(2000); - - b.HasKey("Id"); - - b.HasIndex("ClientId"); - - b.ToTable("ClientProperties"); - }); - - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientRedirectUri", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int") - .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); - - b.Property("ClientId") - .HasColumnType("int"); - - b.Property("RedirectUri") - .IsRequired() - .HasColumnType("nvarchar(2000)") - .HasMaxLength(2000); - - b.HasKey("Id"); - - b.HasIndex("ClientId"); - - b.ToTable("ClientRedirectUris"); - }); - - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientScope", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int") - .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); - - b.Property("ClientId") - .HasColumnType("int"); - - b.Property("Scope") - .IsRequired() - .HasColumnType("nvarchar(200)") - .HasMaxLength(200); - - b.HasKey("Id"); - - b.HasIndex("ClientId"); - - b.ToTable("ClientScopes"); - }); - - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientSecret", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int") - .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); - - b.Property("ClientId") - .HasColumnType("int"); - - b.Property("Created") - .HasColumnType("datetime2"); - - b.Property("Description") - .HasColumnType("nvarchar(2000)") - .HasMaxLength(2000); - - b.Property("Expiration") - .HasColumnType("datetime2"); - - b.Property("Type") - .IsRequired() - .HasColumnType("nvarchar(250)") - .HasMaxLength(250); - - b.Property("Value") - .IsRequired() - .HasColumnType("nvarchar(4000)") - .HasMaxLength(4000); - - b.HasKey("Id"); - - b.HasIndex("ClientId"); - - b.ToTable("ClientSecrets"); - }); - - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.IdentityClaim", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int") - .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); - - b.Property("IdentityResourceId") - .HasColumnType("int"); - - b.Property("Type") - .IsRequired() - .HasColumnType("nvarchar(200)") - .HasMaxLength(200); - - b.HasKey("Id"); - - b.HasIndex("IdentityResourceId"); - - b.ToTable("IdentityClaims"); - }); - - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.IdentityResource", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int") - .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); - - b.Property("Created") - .HasColumnType("datetime2"); - - b.Property("Description") - .HasColumnType("nvarchar(1000)") - .HasMaxLength(1000); - - b.Property("DisplayName") - .HasColumnType("nvarchar(200)") - .HasMaxLength(200); - - b.Property("Emphasize") - .HasColumnType("bit"); - - b.Property("Enabled") - .HasColumnType("bit"); - - b.Property("Name") - .IsRequired() - .HasColumnType("nvarchar(200)") - .HasMaxLength(200); - - b.Property("NonEditable") - .HasColumnType("bit"); - - b.Property("Required") - .HasColumnType("bit"); - - b.Property("ShowInDiscoveryDocument") - .HasColumnType("bit"); - - b.Property("Updated") - .HasColumnType("datetime2"); - - b.HasKey("Id"); - - b.HasIndex("Name") - .IsUnique(); - - b.ToTable("IdentityResources"); - }); - - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.IdentityResourceProperty", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int") - .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); - - b.Property("IdentityResourceId") - .HasColumnType("int"); - - b.Property("Key") - .IsRequired() - .HasColumnType("nvarchar(250)") - .HasMaxLength(250); - - b.Property("Value") - .IsRequired() - .HasColumnType("nvarchar(2000)") - .HasMaxLength(2000); - - b.HasKey("Id"); - - b.HasIndex("IdentityResourceId"); - - b.ToTable("IdentityProperties"); - }); - - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ApiResourceClaim", b => - { - b.HasOne("IdentityServer4.EntityFramework.Entities.ApiResource", "ApiResource") - .WithMany("UserClaims") - .HasForeignKey("ApiResourceId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ApiResourceProperty", b => - { - b.HasOne("IdentityServer4.EntityFramework.Entities.ApiResource", "ApiResource") - .WithMany("Properties") - .HasForeignKey("ApiResourceId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ApiScope", b => - { - b.HasOne("IdentityServer4.EntityFramework.Entities.ApiResource", "ApiResource") - .WithMany("Scopes") - .HasForeignKey("ApiResourceId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ApiScopeClaim", b => - { - b.HasOne("IdentityServer4.EntityFramework.Entities.ApiScope", "ApiScope") - .WithMany("UserClaims") - .HasForeignKey("ApiScopeId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ApiSecret", b => - { - b.HasOne("IdentityServer4.EntityFramework.Entities.ApiResource", "ApiResource") - .WithMany("Secrets") - .HasForeignKey("ApiResourceId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientClaim", b => - { - b.HasOne("IdentityServer4.EntityFramework.Entities.Client", "Client") - .WithMany("Claims") - .HasForeignKey("ClientId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientCorsOrigin", b => - { - b.HasOne("IdentityServer4.EntityFramework.Entities.Client", "Client") - .WithMany("AllowedCorsOrigins") - .HasForeignKey("ClientId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientGrantType", b => - { - b.HasOne("IdentityServer4.EntityFramework.Entities.Client", "Client") - .WithMany("AllowedGrantTypes") - .HasForeignKey("ClientId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientIdPRestriction", b => - { - b.HasOne("IdentityServer4.EntityFramework.Entities.Client", "Client") - .WithMany("IdentityProviderRestrictions") - .HasForeignKey("ClientId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientPostLogoutRedirectUri", b => - { - b.HasOne("IdentityServer4.EntityFramework.Entities.Client", "Client") - .WithMany("PostLogoutRedirectUris") - .HasForeignKey("ClientId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientProperty", b => - { - b.HasOne("IdentityServer4.EntityFramework.Entities.Client", "Client") - .WithMany("Properties") - .HasForeignKey("ClientId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientRedirectUri", b => - { - b.HasOne("IdentityServer4.EntityFramework.Entities.Client", "Client") - .WithMany("RedirectUris") - .HasForeignKey("ClientId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientScope", b => - { - b.HasOne("IdentityServer4.EntityFramework.Entities.Client", "Client") - .WithMany("AllowedScopes") - .HasForeignKey("ClientId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientSecret", b => - { - b.HasOne("IdentityServer4.EntityFramework.Entities.Client", "Client") - .WithMany("ClientSecrets") - .HasForeignKey("ClientId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.IdentityClaim", b => - { - b.HasOne("IdentityServer4.EntityFramework.Entities.IdentityResource", "IdentityResource") - .WithMany("UserClaims") - .HasForeignKey("IdentityResourceId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.IdentityResourceProperty", b => - { - b.HasOne("IdentityServer4.EntityFramework.Entities.IdentityResource", "IdentityResource") - .WithMany("Properties") - .HasForeignKey("IdentityResourceId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/SecurityService.Database/Migrations/ConfigurationDbContext/20191105215403_InitialDbMigration.cs b/SecurityService.Database/Migrations/ConfigurationDbContext/20191105215403_InitialDbMigration.cs deleted file mode 100644 index 8835505c..00000000 --- a/SecurityService.Database/Migrations/ConfigurationDbContext/20191105215403_InitialDbMigration.cs +++ /dev/null @@ -1,607 +0,0 @@ -using System; -using Microsoft.EntityFrameworkCore.Migrations; - -namespace SecurityService.Database.Migrations.ConfigurationDbContext -{ - public partial class InitialDbMigration : Migration - { - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.CreateTable( - name: "ApiResources", - columns: table => new - { - Id = table.Column(nullable: false) - .Annotation("SqlServer:Identity", "1, 1"), - Enabled = table.Column(nullable: false), - Name = table.Column(maxLength: 200, nullable: false), - DisplayName = table.Column(maxLength: 200, nullable: true), - Description = table.Column(maxLength: 1000, nullable: true), - Created = table.Column(nullable: false), - Updated = table.Column(nullable: true), - LastAccessed = table.Column(nullable: true), - NonEditable = table.Column(nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_ApiResources", x => x.Id); - }); - - migrationBuilder.CreateTable( - name: "Clients", - columns: table => new - { - Id = table.Column(nullable: false) - .Annotation("SqlServer:Identity", "1, 1"), - Enabled = table.Column(nullable: false), - ClientId = table.Column(maxLength: 200, nullable: false), - ProtocolType = table.Column(maxLength: 200, nullable: false), - RequireClientSecret = table.Column(nullable: false), - ClientName = table.Column(maxLength: 200, nullable: true), - Description = table.Column(maxLength: 1000, nullable: true), - ClientUri = table.Column(maxLength: 2000, nullable: true), - LogoUri = table.Column(maxLength: 2000, nullable: true), - RequireConsent = table.Column(nullable: false), - AllowRememberConsent = table.Column(nullable: false), - AlwaysIncludeUserClaimsInIdToken = table.Column(nullable: false), - RequirePkce = table.Column(nullable: false), - AllowPlainTextPkce = table.Column(nullable: false), - AllowAccessTokensViaBrowser = table.Column(nullable: false), - FrontChannelLogoutUri = table.Column(maxLength: 2000, nullable: true), - FrontChannelLogoutSessionRequired = table.Column(nullable: false), - BackChannelLogoutUri = table.Column(maxLength: 2000, nullable: true), - BackChannelLogoutSessionRequired = table.Column(nullable: false), - AllowOfflineAccess = table.Column(nullable: false), - IdentityTokenLifetime = table.Column(nullable: false), - AccessTokenLifetime = table.Column(nullable: false), - AuthorizationCodeLifetime = table.Column(nullable: false), - ConsentLifetime = table.Column(nullable: true), - AbsoluteRefreshTokenLifetime = table.Column(nullable: false), - SlidingRefreshTokenLifetime = table.Column(nullable: false), - RefreshTokenUsage = table.Column(nullable: false), - UpdateAccessTokenClaimsOnRefresh = table.Column(nullable: false), - RefreshTokenExpiration = table.Column(nullable: false), - AccessTokenType = table.Column(nullable: false), - EnableLocalLogin = table.Column(nullable: false), - IncludeJwtId = table.Column(nullable: false), - AlwaysSendClientClaims = table.Column(nullable: false), - ClientClaimsPrefix = table.Column(maxLength: 200, nullable: true), - PairWiseSubjectSalt = table.Column(maxLength: 200, nullable: true), - Created = table.Column(nullable: false), - Updated = table.Column(nullable: true), - LastAccessed = table.Column(nullable: true), - UserSsoLifetime = table.Column(nullable: true), - UserCodeType = table.Column(maxLength: 100, nullable: true), - DeviceCodeLifetime = table.Column(nullable: false), - NonEditable = table.Column(nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_Clients", x => x.Id); - }); - - migrationBuilder.CreateTable( - name: "IdentityResources", - columns: table => new - { - Id = table.Column(nullable: false) - .Annotation("SqlServer:Identity", "1, 1"), - Enabled = table.Column(nullable: false), - Name = table.Column(maxLength: 200, nullable: false), - DisplayName = table.Column(maxLength: 200, nullable: true), - Description = table.Column(maxLength: 1000, nullable: true), - Required = table.Column(nullable: false), - Emphasize = table.Column(nullable: false), - ShowInDiscoveryDocument = table.Column(nullable: false), - Created = table.Column(nullable: false), - Updated = table.Column(nullable: true), - NonEditable = table.Column(nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_IdentityResources", x => x.Id); - }); - - migrationBuilder.CreateTable( - name: "ApiClaims", - columns: table => new - { - Id = table.Column(nullable: false) - .Annotation("SqlServer:Identity", "1, 1"), - Type = table.Column(maxLength: 200, nullable: false), - ApiResourceId = table.Column(nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_ApiClaims", x => x.Id); - table.ForeignKey( - name: "FK_ApiClaims_ApiResources_ApiResourceId", - column: x => x.ApiResourceId, - principalTable: "ApiResources", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "ApiProperties", - columns: table => new - { - Id = table.Column(nullable: false) - .Annotation("SqlServer:Identity", "1, 1"), - Key = table.Column(maxLength: 250, nullable: false), - Value = table.Column(maxLength: 2000, nullable: false), - ApiResourceId = table.Column(nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_ApiProperties", x => x.Id); - table.ForeignKey( - name: "FK_ApiProperties_ApiResources_ApiResourceId", - column: x => x.ApiResourceId, - principalTable: "ApiResources", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "ApiScopes", - columns: table => new - { - Id = table.Column(nullable: false) - .Annotation("SqlServer:Identity", "1, 1"), - Name = table.Column(maxLength: 200, nullable: false), - DisplayName = table.Column(maxLength: 200, nullable: true), - Description = table.Column(maxLength: 1000, nullable: true), - Required = table.Column(nullable: false), - Emphasize = table.Column(nullable: false), - ShowInDiscoveryDocument = table.Column(nullable: false), - ApiResourceId = table.Column(nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_ApiScopes", x => x.Id); - table.ForeignKey( - name: "FK_ApiScopes_ApiResources_ApiResourceId", - column: x => x.ApiResourceId, - principalTable: "ApiResources", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "ApiSecrets", - columns: table => new - { - Id = table.Column(nullable: false) - .Annotation("SqlServer:Identity", "1, 1"), - Description = table.Column(maxLength: 1000, nullable: true), - Value = table.Column(maxLength: 4000, nullable: false), - Expiration = table.Column(nullable: true), - Type = table.Column(maxLength: 250, nullable: false), - Created = table.Column(nullable: false), - ApiResourceId = table.Column(nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_ApiSecrets", x => x.Id); - table.ForeignKey( - name: "FK_ApiSecrets_ApiResources_ApiResourceId", - column: x => x.ApiResourceId, - principalTable: "ApiResources", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "ClientClaims", - columns: table => new - { - Id = table.Column(nullable: false) - .Annotation("SqlServer:Identity", "1, 1"), - Type = table.Column(maxLength: 250, nullable: false), - Value = table.Column(maxLength: 250, nullable: false), - ClientId = table.Column(nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_ClientClaims", x => x.Id); - table.ForeignKey( - name: "FK_ClientClaims_Clients_ClientId", - column: x => x.ClientId, - principalTable: "Clients", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "ClientCorsOrigins", - columns: table => new - { - Id = table.Column(nullable: false) - .Annotation("SqlServer:Identity", "1, 1"), - Origin = table.Column(maxLength: 150, nullable: false), - ClientId = table.Column(nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_ClientCorsOrigins", x => x.Id); - table.ForeignKey( - name: "FK_ClientCorsOrigins_Clients_ClientId", - column: x => x.ClientId, - principalTable: "Clients", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "ClientGrantTypes", - columns: table => new - { - Id = table.Column(nullable: false) - .Annotation("SqlServer:Identity", "1, 1"), - GrantType = table.Column(maxLength: 250, nullable: false), - ClientId = table.Column(nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_ClientGrantTypes", x => x.Id); - table.ForeignKey( - name: "FK_ClientGrantTypes_Clients_ClientId", - column: x => x.ClientId, - principalTable: "Clients", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "ClientIdPRestrictions", - columns: table => new - { - Id = table.Column(nullable: false) - .Annotation("SqlServer:Identity", "1, 1"), - Provider = table.Column(maxLength: 200, nullable: false), - ClientId = table.Column(nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_ClientIdPRestrictions", x => x.Id); - table.ForeignKey( - name: "FK_ClientIdPRestrictions_Clients_ClientId", - column: x => x.ClientId, - principalTable: "Clients", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "ClientPostLogoutRedirectUris", - columns: table => new - { - Id = table.Column(nullable: false) - .Annotation("SqlServer:Identity", "1, 1"), - PostLogoutRedirectUri = table.Column(maxLength: 2000, nullable: false), - ClientId = table.Column(nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_ClientPostLogoutRedirectUris", x => x.Id); - table.ForeignKey( - name: "FK_ClientPostLogoutRedirectUris_Clients_ClientId", - column: x => x.ClientId, - principalTable: "Clients", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "ClientProperties", - columns: table => new - { - Id = table.Column(nullable: false) - .Annotation("SqlServer:Identity", "1, 1"), - Key = table.Column(maxLength: 250, nullable: false), - Value = table.Column(maxLength: 2000, nullable: false), - ClientId = table.Column(nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_ClientProperties", x => x.Id); - table.ForeignKey( - name: "FK_ClientProperties_Clients_ClientId", - column: x => x.ClientId, - principalTable: "Clients", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "ClientRedirectUris", - columns: table => new - { - Id = table.Column(nullable: false) - .Annotation("SqlServer:Identity", "1, 1"), - RedirectUri = table.Column(maxLength: 2000, nullable: false), - ClientId = table.Column(nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_ClientRedirectUris", x => x.Id); - table.ForeignKey( - name: "FK_ClientRedirectUris_Clients_ClientId", - column: x => x.ClientId, - principalTable: "Clients", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "ClientScopes", - columns: table => new - { - Id = table.Column(nullable: false) - .Annotation("SqlServer:Identity", "1, 1"), - Scope = table.Column(maxLength: 200, nullable: false), - ClientId = table.Column(nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_ClientScopes", x => x.Id); - table.ForeignKey( - name: "FK_ClientScopes_Clients_ClientId", - column: x => x.ClientId, - principalTable: "Clients", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "ClientSecrets", - columns: table => new - { - Id = table.Column(nullable: false) - .Annotation("SqlServer:Identity", "1, 1"), - Description = table.Column(maxLength: 2000, nullable: true), - Value = table.Column(maxLength: 4000, nullable: false), - Expiration = table.Column(nullable: true), - Type = table.Column(maxLength: 250, nullable: false), - Created = table.Column(nullable: false), - ClientId = table.Column(nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_ClientSecrets", x => x.Id); - table.ForeignKey( - name: "FK_ClientSecrets_Clients_ClientId", - column: x => x.ClientId, - principalTable: "Clients", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "IdentityClaims", - columns: table => new - { - Id = table.Column(nullable: false) - .Annotation("SqlServer:Identity", "1, 1"), - Type = table.Column(maxLength: 200, nullable: false), - IdentityResourceId = table.Column(nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_IdentityClaims", x => x.Id); - table.ForeignKey( - name: "FK_IdentityClaims_IdentityResources_IdentityResourceId", - column: x => x.IdentityResourceId, - principalTable: "IdentityResources", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "IdentityProperties", - columns: table => new - { - Id = table.Column(nullable: false) - .Annotation("SqlServer:Identity", "1, 1"), - Key = table.Column(maxLength: 250, nullable: false), - Value = table.Column(maxLength: 2000, nullable: false), - IdentityResourceId = table.Column(nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_IdentityProperties", x => x.Id); - table.ForeignKey( - name: "FK_IdentityProperties_IdentityResources_IdentityResourceId", - column: x => x.IdentityResourceId, - principalTable: "IdentityResources", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "ApiScopeClaims", - columns: table => new - { - Id = table.Column(nullable: false) - .Annotation("SqlServer:Identity", "1, 1"), - Type = table.Column(maxLength: 200, nullable: false), - ApiScopeId = table.Column(nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_ApiScopeClaims", x => x.Id); - table.ForeignKey( - name: "FK_ApiScopeClaims_ApiScopes_ApiScopeId", - column: x => x.ApiScopeId, - principalTable: "ApiScopes", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateIndex( - name: "IX_ApiClaims_ApiResourceId", - table: "ApiClaims", - column: "ApiResourceId"); - - migrationBuilder.CreateIndex( - name: "IX_ApiProperties_ApiResourceId", - table: "ApiProperties", - column: "ApiResourceId"); - - migrationBuilder.CreateIndex( - name: "IX_ApiResources_Name", - table: "ApiResources", - column: "Name", - unique: true); - - migrationBuilder.CreateIndex( - name: "IX_ApiScopeClaims_ApiScopeId", - table: "ApiScopeClaims", - column: "ApiScopeId"); - - migrationBuilder.CreateIndex( - name: "IX_ApiScopes_ApiResourceId", - table: "ApiScopes", - column: "ApiResourceId"); - - migrationBuilder.CreateIndex( - name: "IX_ApiScopes_Name", - table: "ApiScopes", - column: "Name", - unique: true); - - migrationBuilder.CreateIndex( - name: "IX_ApiSecrets_ApiResourceId", - table: "ApiSecrets", - column: "ApiResourceId"); - - migrationBuilder.CreateIndex( - name: "IX_ClientClaims_ClientId", - table: "ClientClaims", - column: "ClientId"); - - migrationBuilder.CreateIndex( - name: "IX_ClientCorsOrigins_ClientId", - table: "ClientCorsOrigins", - column: "ClientId"); - - migrationBuilder.CreateIndex( - name: "IX_ClientGrantTypes_ClientId", - table: "ClientGrantTypes", - column: "ClientId"); - - migrationBuilder.CreateIndex( - name: "IX_ClientIdPRestrictions_ClientId", - table: "ClientIdPRestrictions", - column: "ClientId"); - - migrationBuilder.CreateIndex( - name: "IX_ClientPostLogoutRedirectUris_ClientId", - table: "ClientPostLogoutRedirectUris", - column: "ClientId"); - - migrationBuilder.CreateIndex( - name: "IX_ClientProperties_ClientId", - table: "ClientProperties", - column: "ClientId"); - - migrationBuilder.CreateIndex( - name: "IX_ClientRedirectUris_ClientId", - table: "ClientRedirectUris", - column: "ClientId"); - - migrationBuilder.CreateIndex( - name: "IX_Clients_ClientId", - table: "Clients", - column: "ClientId", - unique: true); - - migrationBuilder.CreateIndex( - name: "IX_ClientScopes_ClientId", - table: "ClientScopes", - column: "ClientId"); - - migrationBuilder.CreateIndex( - name: "IX_ClientSecrets_ClientId", - table: "ClientSecrets", - column: "ClientId"); - - migrationBuilder.CreateIndex( - name: "IX_IdentityClaims_IdentityResourceId", - table: "IdentityClaims", - column: "IdentityResourceId"); - - migrationBuilder.CreateIndex( - name: "IX_IdentityProperties_IdentityResourceId", - table: "IdentityProperties", - column: "IdentityResourceId"); - - migrationBuilder.CreateIndex( - name: "IX_IdentityResources_Name", - table: "IdentityResources", - column: "Name", - unique: true); - } - - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropTable( - name: "ApiClaims"); - - migrationBuilder.DropTable( - name: "ApiProperties"); - - migrationBuilder.DropTable( - name: "ApiScopeClaims"); - - migrationBuilder.DropTable( - name: "ApiSecrets"); - - migrationBuilder.DropTable( - name: "ClientClaims"); - - migrationBuilder.DropTable( - name: "ClientCorsOrigins"); - - migrationBuilder.DropTable( - name: "ClientGrantTypes"); - - migrationBuilder.DropTable( - name: "ClientIdPRestrictions"); - - migrationBuilder.DropTable( - name: "ClientPostLogoutRedirectUris"); - - migrationBuilder.DropTable( - name: "ClientProperties"); - - migrationBuilder.DropTable( - name: "ClientRedirectUris"); - - migrationBuilder.DropTable( - name: "ClientScopes"); - - migrationBuilder.DropTable( - name: "ClientSecrets"); - - migrationBuilder.DropTable( - name: "IdentityClaims"); - - migrationBuilder.DropTable( - name: "IdentityProperties"); - - migrationBuilder.DropTable( - name: "ApiScopes"); - - migrationBuilder.DropTable( - name: "Clients"); - - migrationBuilder.DropTable( - name: "IdentityResources"); - - migrationBuilder.DropTable( - name: "ApiResources"); - } - } -} diff --git a/SecurityService.Database/Migrations/ConfigurationDbContext/20210118212226_Identityv4.cs b/SecurityService.Database/Migrations/ConfigurationDbContext/20210118212226_Identityv4.cs deleted file mode 100644 index d3d91131..00000000 --- a/SecurityService.Database/Migrations/ConfigurationDbContext/20210118212226_Identityv4.cs +++ /dev/null @@ -1,502 +0,0 @@ -using System; -using Microsoft.EntityFrameworkCore.Migrations; - -namespace SecurityService.Database.Migrations.ConfigurationDbContext -{ - public partial class Identityv4 : Migration - { - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropForeignKey( - name: "FK_ApiClaims_ApiResources_ApiResourceId", - table: "ApiClaims"); - - migrationBuilder.DropForeignKey( - name: "FK_ApiProperties_ApiResources_ApiResourceId", - table: "ApiProperties"); - - migrationBuilder.DropForeignKey( - name: "FK_ApiScopeClaims_ApiScopes_ApiScopeId", - table: "ApiScopeClaims"); - - migrationBuilder.DropForeignKey( - name: "FK_ApiScopes_ApiResources_ApiResourceId", - table: "ApiScopes"); - - migrationBuilder.DropForeignKey( - name: "FK_IdentityProperties_IdentityResources_IdentityResourceId", - table: "IdentityProperties"); - - migrationBuilder.DropTable( - name: "ApiSecrets"); - - migrationBuilder.DropTable( - name: "IdentityClaims"); - - migrationBuilder.DropIndex( - name: "IX_ApiScopes_ApiResourceId", - table: "ApiScopes"); - - migrationBuilder.DropPrimaryKey( - name: "PK_IdentityProperties", - table: "IdentityProperties"); - - migrationBuilder.DropPrimaryKey( - name: "PK_ApiProperties", - table: "ApiProperties"); - - migrationBuilder.DropPrimaryKey( - name: "PK_ApiClaims", - table: "ApiClaims"); - - migrationBuilder.DropColumn( - name: "ApiResourceId", - table: "ApiScopes"); - - migrationBuilder.RenameTable( - name: "IdentityProperties", - newName: "IdentityResourceProperties"); - - migrationBuilder.RenameTable( - name: "ApiProperties", - newName: "ApiResourceProperties"); - - migrationBuilder.RenameTable( - name: "ApiClaims", - newName: "ApiResourceClaims"); - - migrationBuilder.RenameColumn( - name: "ApiScopeId", - table: "ApiScopeClaims", - newName: "ScopeId"); - - migrationBuilder.RenameIndex( - name: "IX_ApiScopeClaims_ApiScopeId", - table: "ApiScopeClaims", - newName: "IX_ApiScopeClaims_ScopeId"); - - migrationBuilder.RenameIndex( - name: "IX_IdentityProperties_IdentityResourceId", - table: "IdentityResourceProperties", - newName: "IX_IdentityResourceProperties_IdentityResourceId"); - - migrationBuilder.RenameIndex( - name: "IX_ApiProperties_ApiResourceId", - table: "ApiResourceProperties", - newName: "IX_ApiResourceProperties_ApiResourceId"); - - migrationBuilder.RenameIndex( - name: "IX_ApiClaims_ApiResourceId", - table: "ApiResourceClaims", - newName: "IX_ApiResourceClaims_ApiResourceId"); - - migrationBuilder.AddColumn( - name: "AllowedIdentityTokenSigningAlgorithms", - table: "Clients", - type: "nvarchar(100)", - maxLength: 100, - nullable: true); - - migrationBuilder.AddColumn( - name: "RequireRequestObject", - table: "Clients", - type: "bit", - nullable: false, - defaultValue: false); - - migrationBuilder.AddColumn( - name: "Enabled", - table: "ApiScopes", - type: "bit", - nullable: false, - defaultValue: false); - - migrationBuilder.AddColumn( - name: "AllowedAccessTokenSigningAlgorithms", - table: "ApiResources", - type: "nvarchar(100)", - maxLength: 100, - nullable: true); - - migrationBuilder.AddColumn( - name: "ShowInDiscoveryDocument", - table: "ApiResources", - type: "bit", - nullable: false, - defaultValue: false); - - migrationBuilder.AddPrimaryKey( - name: "PK_IdentityResourceProperties", - table: "IdentityResourceProperties", - column: "Id"); - - migrationBuilder.AddPrimaryKey( - name: "PK_ApiResourceProperties", - table: "ApiResourceProperties", - column: "Id"); - - migrationBuilder.AddPrimaryKey( - name: "PK_ApiResourceClaims", - table: "ApiResourceClaims", - column: "Id"); - - migrationBuilder.CreateTable( - name: "ApiResourceScopes", - columns: table => new - { - Id = table.Column(type: "int", nullable: false) - .Annotation("SqlServer:Identity", "1, 1"), - Scope = table.Column(type: "nvarchar(200)", maxLength: 200, nullable: false), - ApiResourceId = table.Column(type: "int", nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_ApiResourceScopes", x => x.Id); - table.ForeignKey( - name: "FK_ApiResourceScopes_ApiResources_ApiResourceId", - column: x => x.ApiResourceId, - principalTable: "ApiResources", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "ApiResourceSecrets", - columns: table => new - { - Id = table.Column(type: "int", nullable: false) - .Annotation("SqlServer:Identity", "1, 1"), - ApiResourceId = table.Column(type: "int", nullable: false), - Description = table.Column(type: "nvarchar(1000)", maxLength: 1000, nullable: true), - Value = table.Column(type: "nvarchar(4000)", maxLength: 4000, nullable: false), - Expiration = table.Column(type: "datetime2", nullable: true), - Type = table.Column(type: "nvarchar(250)", maxLength: 250, nullable: false), - Created = table.Column(type: "datetime2", nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_ApiResourceSecrets", x => x.Id); - table.ForeignKey( - name: "FK_ApiResourceSecrets_ApiResources_ApiResourceId", - column: x => x.ApiResourceId, - principalTable: "ApiResources", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "ApiScopeProperties", - columns: table => new - { - Id = table.Column(type: "int", nullable: false) - .Annotation("SqlServer:Identity", "1, 1"), - ScopeId = table.Column(type: "int", nullable: false), - Key = table.Column(type: "nvarchar(250)", maxLength: 250, nullable: false), - Value = table.Column(type: "nvarchar(2000)", maxLength: 2000, nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_ApiScopeProperties", x => x.Id); - table.ForeignKey( - name: "FK_ApiScopeProperties_ApiScopes_ScopeId", - column: x => x.ScopeId, - principalTable: "ApiScopes", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "IdentityResourceClaims", - columns: table => new - { - Id = table.Column(type: "int", nullable: false) - .Annotation("SqlServer:Identity", "1, 1"), - IdentityResourceId = table.Column(type: "int", nullable: false), - Type = table.Column(type: "nvarchar(200)", maxLength: 200, nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_IdentityResourceClaims", x => x.Id); - table.ForeignKey( - name: "FK_IdentityResourceClaims_IdentityResources_IdentityResourceId", - column: x => x.IdentityResourceId, - principalTable: "IdentityResources", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateIndex( - name: "IX_ApiResourceScopes_ApiResourceId", - table: "ApiResourceScopes", - column: "ApiResourceId"); - - migrationBuilder.CreateIndex( - name: "IX_ApiResourceSecrets_ApiResourceId", - table: "ApiResourceSecrets", - column: "ApiResourceId"); - - migrationBuilder.CreateIndex( - name: "IX_ApiScopeProperties_ScopeId", - table: "ApiScopeProperties", - column: "ScopeId"); - - migrationBuilder.CreateIndex( - name: "IX_IdentityResourceClaims_IdentityResourceId", - table: "IdentityResourceClaims", - column: "IdentityResourceId"); - - migrationBuilder.AddForeignKey( - name: "FK_ApiResourceClaims_ApiResources_ApiResourceId", - table: "ApiResourceClaims", - column: "ApiResourceId", - principalTable: "ApiResources", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - - migrationBuilder.AddForeignKey( - name: "FK_ApiResourceProperties_ApiResources_ApiResourceId", - table: "ApiResourceProperties", - column: "ApiResourceId", - principalTable: "ApiResources", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - - migrationBuilder.AddForeignKey( - name: "FK_ApiScopeClaims_ApiScopes_ScopeId", - table: "ApiScopeClaims", - column: "ScopeId", - principalTable: "ApiScopes", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - - migrationBuilder.AddForeignKey( - name: "FK_IdentityResourceProperties_IdentityResources_IdentityResourceId", - table: "IdentityResourceProperties", - column: "IdentityResourceId", - principalTable: "IdentityResources", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - } - - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropForeignKey( - name: "FK_ApiResourceClaims_ApiResources_ApiResourceId", - table: "ApiResourceClaims"); - - migrationBuilder.DropForeignKey( - name: "FK_ApiResourceProperties_ApiResources_ApiResourceId", - table: "ApiResourceProperties"); - - migrationBuilder.DropForeignKey( - name: "FK_ApiScopeClaims_ApiScopes_ScopeId", - table: "ApiScopeClaims"); - - migrationBuilder.DropForeignKey( - name: "FK_IdentityResourceProperties_IdentityResources_IdentityResourceId", - table: "IdentityResourceProperties"); - - migrationBuilder.DropTable( - name: "ApiResourceScopes"); - - migrationBuilder.DropTable( - name: "ApiResourceSecrets"); - - migrationBuilder.DropTable( - name: "ApiScopeProperties"); - - migrationBuilder.DropTable( - name: "IdentityResourceClaims"); - - migrationBuilder.DropPrimaryKey( - name: "PK_IdentityResourceProperties", - table: "IdentityResourceProperties"); - - migrationBuilder.DropPrimaryKey( - name: "PK_ApiResourceProperties", - table: "ApiResourceProperties"); - - migrationBuilder.DropPrimaryKey( - name: "PK_ApiResourceClaims", - table: "ApiResourceClaims"); - - migrationBuilder.DropColumn( - name: "AllowedIdentityTokenSigningAlgorithms", - table: "Clients"); - - migrationBuilder.DropColumn( - name: "RequireRequestObject", - table: "Clients"); - - migrationBuilder.DropColumn( - name: "Enabled", - table: "ApiScopes"); - - migrationBuilder.DropColumn( - name: "AllowedAccessTokenSigningAlgorithms", - table: "ApiResources"); - - migrationBuilder.DropColumn( - name: "ShowInDiscoveryDocument", - table: "ApiResources"); - - migrationBuilder.RenameTable( - name: "IdentityResourceProperties", - newName: "IdentityProperties"); - - migrationBuilder.RenameTable( - name: "ApiResourceProperties", - newName: "ApiProperties"); - - migrationBuilder.RenameTable( - name: "ApiResourceClaims", - newName: "ApiClaims"); - - migrationBuilder.RenameColumn( - name: "ScopeId", - table: "ApiScopeClaims", - newName: "ApiScopeId"); - - migrationBuilder.RenameIndex( - name: "IX_ApiScopeClaims_ScopeId", - table: "ApiScopeClaims", - newName: "IX_ApiScopeClaims_ApiScopeId"); - - migrationBuilder.RenameIndex( - name: "IX_IdentityResourceProperties_IdentityResourceId", - table: "IdentityProperties", - newName: "IX_IdentityProperties_IdentityResourceId"); - - migrationBuilder.RenameIndex( - name: "IX_ApiResourceProperties_ApiResourceId", - table: "ApiProperties", - newName: "IX_ApiProperties_ApiResourceId"); - - migrationBuilder.RenameIndex( - name: "IX_ApiResourceClaims_ApiResourceId", - table: "ApiClaims", - newName: "IX_ApiClaims_ApiResourceId"); - - migrationBuilder.AddColumn( - name: "ApiResourceId", - table: "ApiScopes", - type: "int", - nullable: false, - defaultValue: 0); - - migrationBuilder.AddPrimaryKey( - name: "PK_IdentityProperties", - table: "IdentityProperties", - column: "Id"); - - migrationBuilder.AddPrimaryKey( - name: "PK_ApiProperties", - table: "ApiProperties", - column: "Id"); - - migrationBuilder.AddPrimaryKey( - name: "PK_ApiClaims", - table: "ApiClaims", - column: "Id"); - - migrationBuilder.CreateTable( - name: "ApiSecrets", - columns: table => new - { - Id = table.Column(type: "int", nullable: false) - .Annotation("SqlServer:Identity", "1, 1"), - ApiResourceId = table.Column(type: "int", nullable: false), - Created = table.Column(type: "datetime2", nullable: false), - Description = table.Column(type: "nvarchar(1000)", maxLength: 1000, nullable: true), - Expiration = table.Column(type: "datetime2", nullable: true), - Type = table.Column(type: "nvarchar(250)", maxLength: 250, nullable: false), - Value = table.Column(type: "nvarchar(4000)", maxLength: 4000, nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_ApiSecrets", x => x.Id); - table.ForeignKey( - name: "FK_ApiSecrets_ApiResources_ApiResourceId", - column: x => x.ApiResourceId, - principalTable: "ApiResources", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "IdentityClaims", - columns: table => new - { - Id = table.Column(type: "int", nullable: false) - .Annotation("SqlServer:Identity", "1, 1"), - IdentityResourceId = table.Column(type: "int", nullable: false), - Type = table.Column(type: "nvarchar(200)", maxLength: 200, nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_IdentityClaims", x => x.Id); - table.ForeignKey( - name: "FK_IdentityClaims_IdentityResources_IdentityResourceId", - column: x => x.IdentityResourceId, - principalTable: "IdentityResources", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateIndex( - name: "IX_ApiScopes_ApiResourceId", - table: "ApiScopes", - column: "ApiResourceId"); - - migrationBuilder.CreateIndex( - name: "IX_ApiSecrets_ApiResourceId", - table: "ApiSecrets", - column: "ApiResourceId"); - - migrationBuilder.CreateIndex( - name: "IX_IdentityClaims_IdentityResourceId", - table: "IdentityClaims", - column: "IdentityResourceId"); - - migrationBuilder.AddForeignKey( - name: "FK_ApiClaims_ApiResources_ApiResourceId", - table: "ApiClaims", - column: "ApiResourceId", - principalTable: "ApiResources", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - - migrationBuilder.AddForeignKey( - name: "FK_ApiProperties_ApiResources_ApiResourceId", - table: "ApiProperties", - column: "ApiResourceId", - principalTable: "ApiResources", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - - migrationBuilder.AddForeignKey( - name: "FK_ApiScopeClaims_ApiScopes_ApiScopeId", - table: "ApiScopeClaims", - column: "ApiScopeId", - principalTable: "ApiScopes", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - - migrationBuilder.AddForeignKey( - name: "FK_ApiScopes_ApiResources_ApiResourceId", - table: "ApiScopes", - column: "ApiResourceId", - principalTable: "ApiResources", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - - migrationBuilder.AddForeignKey( - name: "FK_IdentityProperties_IdentityResources_IdentityResourceId", - table: "IdentityProperties", - column: "IdentityResourceId", - principalTable: "IdentityResources", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - } - } -} diff --git a/SecurityService.Database/Migrations/PersistedGrantDbContext/20210118212333_Identityv4.Designer.cs b/SecurityService.Database/Migrations/PersistedGrantDb/20210607105327_InitialMigration.Designer.cs similarity index 65% rename from SecurityService.Database/Migrations/PersistedGrantDbContext/20210118212333_Identityv4.Designer.cs rename to SecurityService.Database/Migrations/PersistedGrantDb/20210607105327_InitialMigration.Designer.cs index c7d6e23a..e664210c 100644 --- a/SecurityService.Database/Migrations/PersistedGrantDbContext/20210118212333_Identityv4.Designer.cs +++ b/SecurityService.Database/Migrations/PersistedGrantDb/20210607105327_InitialMigration.Designer.cs @@ -1,29 +1,27 @@ // -using System; -using IdentityServer4.EntityFramework.DbContexts; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; - -namespace SecurityService.Database.Migrations.PersistedGrantDbContext + +namespace SecurityService.Database.Migrations.PersistedGrantDb { - using PersistedGrantDbContext = IdentityServer4.EntityFramework.DbContexts.PersistedGrantDbContext; + using System; + using Duende.IdentityServer.EntityFramework.DbContexts; + using Microsoft.EntityFrameworkCore; + using Microsoft.EntityFrameworkCore.Infrastructure; + using Microsoft.EntityFrameworkCore.Metadata; + using Microsoft.EntityFrameworkCore.Migrations; [DbContext(typeof(PersistedGrantDbContext))] - [Migration("20210118212333_Identityv4")] - partial class Identityv4 + [Migration("20210607105327_InitialMigration")] + partial class InitialMigration { protected override void BuildTargetModel(ModelBuilder modelBuilder) { #pragma warning disable 612, 618 modelBuilder - .UseIdentityColumns() .HasAnnotation("Relational:MaxIdentifierLength", 128) - .HasAnnotation("ProductVersion", "5.0.2"); + .HasAnnotation("ProductVersion", "5.0.6") + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.DeviceFlowCodes", b => + modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.DeviceFlowCodes", b => { b.Property("UserCode") .HasMaxLength(200) @@ -73,7 +71,43 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.ToTable("DeviceCodes"); }); - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.PersistedGrant", b => + modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.Key", b => + { + b.Property("Id") + .HasColumnType("nvarchar(450)"); + + b.Property("Algorithm") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.Property("Created") + .HasColumnType("datetime2"); + + b.Property("Data") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("DataProtected") + .HasColumnType("bit"); + + b.Property("IsX509Certificate") + .HasColumnType("bit"); + + b.Property("Use") + .HasColumnType("nvarchar(450)"); + + b.Property("Version") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("Use"); + + b.ToTable("Keys"); + }); + + modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.PersistedGrant", b => { b.Property("Key") .HasMaxLength(200) @@ -117,6 +151,8 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.HasKey("Key"); + b.HasIndex("ConsumedTime"); + b.HasIndex("Expiration"); b.HasIndex("SubjectId", "ClientId", "Type"); diff --git a/SecurityService.Database/Migrations/PersistedGrantDb/20210607105327_InitialMigration.cs b/SecurityService.Database/Migrations/PersistedGrantDb/20210607105327_InitialMigration.cs new file mode 100644 index 00000000..6e50b7b2 --- /dev/null +++ b/SecurityService.Database/Migrations/PersistedGrantDb/20210607105327_InitialMigration.cs @@ -0,0 +1,116 @@ +namespace SecurityService.Database.Migrations.PersistedGrantDb +{ + using Microsoft.EntityFrameworkCore.Migrations; + using System; + + public partial class InitialMigration : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "DeviceCodes", + columns: table => new + { + UserCode = table.Column(type: "nvarchar(200)", maxLength: 200, nullable: false), + DeviceCode = table.Column(type: "nvarchar(200)", maxLength: 200, nullable: false), + SubjectId = table.Column(type: "nvarchar(200)", maxLength: 200, nullable: true), + SessionId = table.Column(type: "nvarchar(100)", maxLength: 100, nullable: true), + ClientId = table.Column(type: "nvarchar(200)", maxLength: 200, nullable: false), + Description = table.Column(type: "nvarchar(200)", maxLength: 200, nullable: true), + CreationTime = table.Column(type: "datetime2", nullable: false), + Expiration = table.Column(type: "datetime2", nullable: false), + Data = table.Column(type: "nvarchar(max)", maxLength: 50000, nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_DeviceCodes", x => x.UserCode); + }); + + migrationBuilder.CreateTable( + name: "Keys", + columns: table => new + { + Id = table.Column(type: "nvarchar(450)", nullable: false), + Version = table.Column(type: "int", nullable: false), + Created = table.Column(type: "datetime2", nullable: false), + Use = table.Column(type: "nvarchar(450)", nullable: true), + Algorithm = table.Column(type: "nvarchar(100)", maxLength: 100, nullable: false), + IsX509Certificate = table.Column(type: "bit", nullable: false), + DataProtected = table.Column(type: "bit", nullable: false), + Data = table.Column(type: "nvarchar(max)", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_Keys", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "PersistedGrants", + columns: table => new + { + Key = table.Column(type: "nvarchar(200)", maxLength: 200, nullable: false), + Type = table.Column(type: "nvarchar(50)", maxLength: 50, nullable: false), + SubjectId = table.Column(type: "nvarchar(200)", maxLength: 200, nullable: true), + SessionId = table.Column(type: "nvarchar(100)", maxLength: 100, nullable: true), + ClientId = table.Column(type: "nvarchar(200)", maxLength: 200, nullable: false), + Description = table.Column(type: "nvarchar(200)", maxLength: 200, nullable: true), + CreationTime = table.Column(type: "datetime2", nullable: false), + Expiration = table.Column(type: "datetime2", nullable: true), + ConsumedTime = table.Column(type: "datetime2", nullable: true), + Data = table.Column(type: "nvarchar(max)", maxLength: 50000, nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_PersistedGrants", x => x.Key); + }); + + migrationBuilder.CreateIndex( + name: "IX_DeviceCodes_DeviceCode", + table: "DeviceCodes", + column: "DeviceCode", + unique: true); + + migrationBuilder.CreateIndex( + name: "IX_DeviceCodes_Expiration", + table: "DeviceCodes", + column: "Expiration"); + + migrationBuilder.CreateIndex( + name: "IX_Keys_Use", + table: "Keys", + column: "Use"); + + migrationBuilder.CreateIndex( + name: "IX_PersistedGrants_ConsumedTime", + table: "PersistedGrants", + column: "ConsumedTime"); + + migrationBuilder.CreateIndex( + name: "IX_PersistedGrants_Expiration", + table: "PersistedGrants", + column: "Expiration"); + + migrationBuilder.CreateIndex( + name: "IX_PersistedGrants_SubjectId_ClientId_Type", + table: "PersistedGrants", + columns: new[] { "SubjectId", "ClientId", "Type" }); + + migrationBuilder.CreateIndex( + name: "IX_PersistedGrants_SubjectId_SessionId_Type", + table: "PersistedGrants", + columns: new[] { "SubjectId", "SessionId", "Type" }); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "DeviceCodes"); + + migrationBuilder.DropTable( + name: "Keys"); + + migrationBuilder.DropTable( + name: "PersistedGrants"); + } + } +} diff --git a/SecurityService.Database/Migrations/PersistedGrantDbContext/PersistedGrantDbContextModelSnapshot.cs b/SecurityService.Database/Migrations/PersistedGrantDb/PersistedGrantDbContextModelSnapshot.cs similarity index 67% rename from SecurityService.Database/Migrations/PersistedGrantDbContext/PersistedGrantDbContextModelSnapshot.cs rename to SecurityService.Database/Migrations/PersistedGrantDb/PersistedGrantDbContextModelSnapshot.cs index 9a4ca2fb..c59b98d9 100644 --- a/SecurityService.Database/Migrations/PersistedGrantDbContext/PersistedGrantDbContextModelSnapshot.cs +++ b/SecurityService.Database/Migrations/PersistedGrantDb/PersistedGrantDbContextModelSnapshot.cs @@ -1,14 +1,12 @@ // -using System; -using IdentityServer4.EntityFramework.DbContexts; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; - -namespace SecurityService.Database.Migrations.PersistedGrantDbContext + +namespace SecurityService.Database.Migrations.IdentityServer.PersistedGrantDb { - using PersistedGrantDbContext = IdentityServer4.EntityFramework.DbContexts.PersistedGrantDbContext; + using Duende.IdentityServer.EntityFramework.DbContexts; + using Microsoft.EntityFrameworkCore; + using Microsoft.EntityFrameworkCore.Infrastructure; + using Microsoft.EntityFrameworkCore.Metadata; + using System; [DbContext(typeof(PersistedGrantDbContext))] partial class PersistedGrantDbContextModelSnapshot : ModelSnapshot @@ -17,11 +15,11 @@ protected override void BuildModel(ModelBuilder modelBuilder) { #pragma warning disable 612, 618 modelBuilder - .UseIdentityColumns() .HasAnnotation("Relational:MaxIdentifierLength", 128) - .HasAnnotation("ProductVersion", "5.0.2"); + .HasAnnotation("ProductVersion", "5.0.6") + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.DeviceFlowCodes", b => + modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.DeviceFlowCodes", b => { b.Property("UserCode") .HasMaxLength(200) @@ -71,7 +69,43 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.ToTable("DeviceCodes"); }); - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.PersistedGrant", b => + modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.Key", b => + { + b.Property("Id") + .HasColumnType("nvarchar(450)"); + + b.Property("Algorithm") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.Property("Created") + .HasColumnType("datetime2"); + + b.Property("Data") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("DataProtected") + .HasColumnType("bit"); + + b.Property("IsX509Certificate") + .HasColumnType("bit"); + + b.Property("Use") + .HasColumnType("nvarchar(450)"); + + b.Property("Version") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("Use"); + + b.ToTable("Keys"); + }); + + modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.PersistedGrant", b => { b.Property("Key") .HasMaxLength(200) @@ -115,6 +149,8 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.HasKey("Key"); + b.HasIndex("ConsumedTime"); + b.HasIndex("Expiration"); b.HasIndex("SubjectId", "ClientId", "Type"); diff --git a/SecurityService.Database/Migrations/PersistedGrantDbContext/20191105215225_InitialDbMigration.Designer.cs b/SecurityService.Database/Migrations/PersistedGrantDbContext/20191105215225_InitialDbMigration.Designer.cs deleted file mode 100644 index 391c3280..00000000 --- a/SecurityService.Database/Migrations/PersistedGrantDbContext/20191105215225_InitialDbMigration.Designer.cs +++ /dev/null @@ -1,110 +0,0 @@ -// -using System; -using IdentityServer4.EntityFramework.DbContexts; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; - -namespace SecurityService.Database.Migrations.PersistedGrantDbContext -{ - using PersistedGrantDbContext = IdentityServer4.EntityFramework.DbContexts.PersistedGrantDbContext; - - [DbContext(typeof(PersistedGrantDbContext))] - [Migration("20191105215225_InitialDbMigration")] - partial class InitialDbMigration - { - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("ProductVersion", "3.0.0") - .HasAnnotation("Relational:MaxIdentifierLength", 128) - .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); - - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.DeviceFlowCodes", b => - { - b.Property("UserCode") - .HasColumnType("nvarchar(200)") - .HasMaxLength(200); - - b.Property("ClientId") - .IsRequired() - .HasColumnType("nvarchar(200)") - .HasMaxLength(200); - - b.Property("CreationTime") - .HasColumnType("datetime2"); - - b.Property("Data") - .IsRequired() - .HasColumnType("nvarchar(max)") - .HasMaxLength(50000); - - b.Property("DeviceCode") - .IsRequired() - .HasColumnType("nvarchar(200)") - .HasMaxLength(200); - - b.Property("Expiration") - .IsRequired() - .HasColumnType("datetime2"); - - b.Property("SubjectId") - .HasColumnType("nvarchar(200)") - .HasMaxLength(200); - - b.HasKey("UserCode"); - - b.HasIndex("DeviceCode") - .IsUnique(); - - b.HasIndex("Expiration"); - - b.ToTable("DeviceCodes"); - }); - - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.PersistedGrant", b => - { - b.Property("Key") - .HasColumnType("nvarchar(200)") - .HasMaxLength(200); - - b.Property("ClientId") - .IsRequired() - .HasColumnType("nvarchar(200)") - .HasMaxLength(200); - - b.Property("CreationTime") - .HasColumnType("datetime2"); - - b.Property("Data") - .IsRequired() - .HasColumnType("nvarchar(max)") - .HasMaxLength(50000); - - b.Property("Expiration") - .HasColumnType("datetime2"); - - b.Property("SubjectId") - .HasColumnType("nvarchar(200)") - .HasMaxLength(200); - - b.Property("Type") - .IsRequired() - .HasColumnType("nvarchar(50)") - .HasMaxLength(50); - - b.HasKey("Key"); - - b.HasIndex("Expiration"); - - b.HasIndex("SubjectId", "ClientId", "Type"); - - b.ToTable("PersistedGrants"); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/SecurityService.Database/Migrations/PersistedGrantDbContext/20191105215225_InitialDbMigration.cs b/SecurityService.Database/Migrations/PersistedGrantDbContext/20191105215225_InitialDbMigration.cs deleted file mode 100644 index a9b54116..00000000 --- a/SecurityService.Database/Migrations/PersistedGrantDbContext/20191105215225_InitialDbMigration.cs +++ /dev/null @@ -1,75 +0,0 @@ -using System; -using Microsoft.EntityFrameworkCore.Migrations; - -namespace SecurityService.Database.Migrations.PersistedGrantDbContext -{ - public partial class InitialDbMigration : Migration - { - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.CreateTable( - name: "DeviceCodes", - columns: table => new - { - UserCode = table.Column(maxLength: 200, nullable: false), - DeviceCode = table.Column(maxLength: 200, nullable: false), - SubjectId = table.Column(maxLength: 200, nullable: true), - ClientId = table.Column(maxLength: 200, nullable: false), - CreationTime = table.Column(nullable: false), - Expiration = table.Column(nullable: false), - Data = table.Column(maxLength: 50000, nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_DeviceCodes", x => x.UserCode); - }); - - migrationBuilder.CreateTable( - name: "PersistedGrants", - columns: table => new - { - Key = table.Column(maxLength: 200, nullable: false), - Type = table.Column(maxLength: 50, nullable: false), - SubjectId = table.Column(maxLength: 200, nullable: true), - ClientId = table.Column(maxLength: 200, nullable: false), - CreationTime = table.Column(nullable: false), - Expiration = table.Column(nullable: true), - Data = table.Column(maxLength: 50000, nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_PersistedGrants", x => x.Key); - }); - - migrationBuilder.CreateIndex( - name: "IX_DeviceCodes_DeviceCode", - table: "DeviceCodes", - column: "DeviceCode", - unique: true); - - migrationBuilder.CreateIndex( - name: "IX_DeviceCodes_Expiration", - table: "DeviceCodes", - column: "Expiration"); - - migrationBuilder.CreateIndex( - name: "IX_PersistedGrants_Expiration", - table: "PersistedGrants", - column: "Expiration"); - - migrationBuilder.CreateIndex( - name: "IX_PersistedGrants_SubjectId_ClientId_Type", - table: "PersistedGrants", - columns: new[] { "SubjectId", "ClientId", "Type" }); - } - - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropTable( - name: "DeviceCodes"); - - migrationBuilder.DropTable( - name: "PersistedGrants"); - } - } -} diff --git a/SecurityService.Database/Migrations/PersistedGrantDbContext/20210118212333_Identityv4.cs b/SecurityService.Database/Migrations/PersistedGrantDbContext/20210118212333_Identityv4.cs deleted file mode 100644 index d0f98e12..00000000 --- a/SecurityService.Database/Migrations/PersistedGrantDbContext/20210118212333_Identityv4.cs +++ /dev/null @@ -1,77 +0,0 @@ -using System; -using Microsoft.EntityFrameworkCore.Migrations; - -namespace SecurityService.Database.Migrations.PersistedGrantDbContext -{ - public partial class Identityv4 : Migration - { - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.AddColumn( - name: "ConsumedTime", - table: "PersistedGrants", - type: "datetime2", - nullable: true); - - migrationBuilder.AddColumn( - name: "Description", - table: "PersistedGrants", - type: "nvarchar(200)", - maxLength: 200, - nullable: true); - - migrationBuilder.AddColumn( - name: "SessionId", - table: "PersistedGrants", - type: "nvarchar(100)", - maxLength: 100, - nullable: true); - - migrationBuilder.AddColumn( - name: "Description", - table: "DeviceCodes", - type: "nvarchar(200)", - maxLength: 200, - nullable: true); - - migrationBuilder.AddColumn( - name: "SessionId", - table: "DeviceCodes", - type: "nvarchar(100)", - maxLength: 100, - nullable: true); - - migrationBuilder.CreateIndex( - name: "IX_PersistedGrants_SubjectId_SessionId_Type", - table: "PersistedGrants", - columns: new[] { "SubjectId", "SessionId", "Type" }); - } - - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropIndex( - name: "IX_PersistedGrants_SubjectId_SessionId_Type", - table: "PersistedGrants"); - - migrationBuilder.DropColumn( - name: "ConsumedTime", - table: "PersistedGrants"); - - migrationBuilder.DropColumn( - name: "Description", - table: "PersistedGrants"); - - migrationBuilder.DropColumn( - name: "SessionId", - table: "PersistedGrants"); - - migrationBuilder.DropColumn( - name: "Description", - table: "DeviceCodes"); - - migrationBuilder.DropColumn( - name: "SessionId", - table: "DeviceCodes"); - } - } -} diff --git a/SecurityService.Database/SecurityService.Database.csproj b/SecurityService.Database/SecurityService.Database.csproj index c9684826..1863889f 100644 --- a/SecurityService.Database/SecurityService.Database.csproj +++ b/SecurityService.Database/SecurityService.Database.csproj @@ -1,25 +1,22 @@  - net5.0 - None + net5.0 - - - - - - - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - + + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + diff --git a/SecurityService.Database/Seeding/DatabaseSeeding.cs b/SecurityService.Database/Seeding/DatabaseSeeding.cs deleted file mode 100644 index c504672e..00000000 --- a/SecurityService.Database/Seeding/DatabaseSeeding.cs +++ /dev/null @@ -1,134 +0,0 @@ -namespace SecurityService.Database.Seeding -{ - using System; - using System.Collections.Generic; - using System.Linq; - using System.Threading; - using DbContexts; - using IdentityServer4.EntityFramework.DbContexts; - using IdentityServer4.EntityFramework.Entities; - using Microsoft.EntityFrameworkCore; - - public class DatabaseSeeding - { - #region Methods - - /// - /// Initialises the authentication database. - /// - /// The authentication database context. - /// Type of the seeding. - public static void InitialiseAuthenticationDatabase(AuthenticationDbContext authenticationDbContext, - SeedingType seedingType) - { - Boolean isDbInitialised = false; - Int32 retryCounter = 0; - while (retryCounter < 20 && !isDbInitialised) - { - try - { - if (authenticationDbContext.Database.IsSqlServer()) - { - authenticationDbContext.Database.Migrate(); - } - - isDbInitialised = true; - break; - } - catch (Exception ex) - { - retryCounter++; - Thread.Sleep(10000); - } - } - - if (!isDbInitialised) - { - String connString = authenticationDbContext.Database.GetDbConnection().ConnectionString; - - Exception newException = new Exception($"Error initialising Db with Connection String [{connString}]"); - throw newException; - } - } - - /// - /// Initialises the configuration database. - /// - /// The configuration database context. - /// Type of the seeding. - public static void InitialiseConfigurationDatabase(ConfigurationDbContext configurationDbContext, - SeedingType seedingType) - { - Boolean isDbInitialised = false; - Int32 retryCounter = 0; - while (retryCounter < 20 && !isDbInitialised) - { - try - { - if (configurationDbContext.Database.IsSqlServer()) - { - configurationDbContext.Database.Migrate(); - } - - configurationDbContext.SaveChanges(); - - isDbInitialised = true; - break; - } - catch (Exception ex) - { - retryCounter++; - Thread.Sleep(10000); - } - } - - if (!isDbInitialised) - { - String connString = configurationDbContext.Database.GetDbConnection().ConnectionString; - - Exception newException = new Exception($"Error initialising Db with Connection String [{connString}]"); - throw newException; - } - } - - /// - /// Initialises the persisted grant database. - /// - /// The persisted grant database context. - /// Type of the seeding. - public static void InitialisePersistedGrantDatabase(PersistedGrantDbContext persistedGrantDbContext, - SeedingType seedingType) - { - Boolean isDbInitialised = false; - Int32 retryCounter = 0; - while (retryCounter < 20 && !isDbInitialised) - { - try - { - if (persistedGrantDbContext.Database.IsSqlServer()) - { - persistedGrantDbContext.Database.Migrate(); - } - - isDbInitialised = true; - break; - } - catch (Exception ex) - { - retryCounter++; - Thread.Sleep(10000); - } - } - - if (!isDbInitialised) - { - String connString = persistedGrantDbContext.Database.GetDbConnection().ConnectionString; - - Exception newException = new Exception($"Error initialising Db with Connection String [{connString}]"); - throw newException; - } - } - - #endregion - } -} diff --git a/SecurityService.Database/Seeding/SeedingType.cs b/SecurityService.Database/Seeding/SeedingType.cs deleted file mode 100644 index 65bb6996..00000000 --- a/SecurityService.Database/Seeding/SeedingType.cs +++ /dev/null @@ -1,11 +0,0 @@ -namespace SecurityService.Database.Seeding -{ - public enum SeedingType - { - NotSet = 0, - IntegrationTest, - Development, - Staging, - Production - } -} \ No newline at end of file diff --git a/SecurityService.IntegrationTests/Clients/Clients.feature.cs b/SecurityService.IntegrationTests/Clients/Clients.feature.cs index 58e35c4b..9db96344 100644 --- a/SecurityService.IntegrationTests/Clients/Clients.feature.cs +++ b/SecurityService.IntegrationTests/Clients/Clients.feature.cs @@ -140,7 +140,7 @@ public virtual void CreateClient() "A second test client", "Secret2", "Scope1, Scope2", - "hybrid", + "authorization_code", "http://localhost/signin-oidc", "http://localhost/signout-oidc", "true"}); @@ -205,7 +205,7 @@ public virtual void GetClient() "A second test client", "Secret2", "Scope1, Scope2", - "hybrid", + "authorization_code", "http://localhost/signin-oidc", "http://localhost/signout-oidc", "true"}); @@ -248,7 +248,7 @@ public virtual void GetClient() "Test Client 2", "A second test client", "Scope1, Scope2", - "hybrid", + "authorization_code", "http://localhost/signin-oidc", "http://localhost/signout-oidc", "true"}); @@ -316,7 +316,7 @@ public virtual void GetClients() "A second test client", "Secret2", "Scope1, Scope2", - "hybrid", + "authorization_code", "http://localhost/signin-oidc", "http://localhost/signout-oidc", "true"}); @@ -346,7 +346,7 @@ public virtual void GetClients() "Test Client 2", "A second test client", "Scope1, Scope2", - "hybrid", + "authorization_code", "http://localhost/signin-oidc", "http://localhost/signout-oidc", "true"}); diff --git a/SecurityService.IntegrationTests/Common/DockerHelper.cs b/SecurityService.IntegrationTests/Common/DockerHelper.cs index bbb3522f..f4ef61c3 100644 --- a/SecurityService.IntegrationTests/Common/DockerHelper.cs +++ b/SecurityService.IntegrationTests/Common/DockerHelper.cs @@ -19,8 +19,6 @@ namespace SecurityService.IntergrationTests.Common using Ductus.FluentDocker.Model.Builders; using Ductus.FluentDocker.Services; using Ductus.FluentDocker.Services.Extensions; - using IdentityServer4.EntityFramework.DbContexts; - using IdentityServer4.EntityFramework.Options; using Microsoft.EntityFrameworkCore; using TechTalk.SpecFlow; @@ -74,7 +72,7 @@ public async Task StartContainersForScenarioRun(String scenarioName) this.SetupSecurityServiceContainer(traceFolder); this.SecurityServicePort = this.SecurityServiceContainer.ToHostExposedEndpoint("5001/tcp").Port; - Func securityServiceBaseAddressResolver = api => $"http://127.0.0.1:{this.SecurityServicePort}"; + Func securityServiceBaseAddressResolver = api => $"https://127.0.0.1:{this.SecurityServicePort}"; HttpClient httpClient = new HttpClient(); this.SecurityServiceClient = new SecurityServiceClient(securityServiceBaseAddressResolver,httpClient); @@ -92,8 +90,8 @@ private void SetupSecurityServiceContainer(String traceFolder) // Management API Container this.SecurityServiceContainer = new Builder().UseContainer().WithName(this.SecurityServiceContainerName) .WithEnvironment("ASPNETCORE_ENVIRONMENT=IntegrationTest", - $"ServiceOptions:PublicOrigin=http://127.0.0.1:5001", - $"ServiceOptions:IssuerUrl=http://127.0.0.1:5001") + $"ServiceOptions:PublicOrigin=https://127.0.0.1:5001", + $"ServiceOptions:IssuerUrl=https://127.0.0.1:5001") .UseImage("securityservice").ExposePort(5001).UseNetwork(new List { this.TestNetwork diff --git a/SecurityService.Manager/ISecurityServiceManager.cs b/SecurityService.Manager/ISecurityServiceManager.cs deleted file mode 100644 index fc510e8e..00000000 --- a/SecurityService.Manager/ISecurityServiceManager.cs +++ /dev/null @@ -1,247 +0,0 @@ -namespace SecurityService.Manager -{ - using System; - using System.Collections.Generic; - using System.Threading; - using System.Threading.Tasks; - using IdentityServer4.Models; - using Models; - - /// - /// - /// - public interface ISecurityServiceManager - { - #region Methods - - /// - /// Creates the API scope. - /// - /// The name. - /// The display name. - /// The description. - /// The cancellation token. - /// - Task CreateApiScope(String name, - String displayName, - String description, - CancellationToken cancellationToken); - - /// - /// Gets the API scope. - /// - /// Name of the API scope. - /// The cancellation token. - /// - Task GetApiScope(String apiScopeName, CancellationToken cancellationToken); - - /// - /// Gets the API scopes. - /// - /// The cancellation token. - /// - Task> GetApiScopes(CancellationToken cancellationToken); - - /// - /// Creates the API resource. - /// - /// The name. - /// The display name. - /// The description. - /// The secret. - /// The scopes. - /// The user claims. - /// The cancellation token. - /// - Task CreateApiResource(String name, - String displayName, - String description, - String secret, - List scopes, - List userClaims, - CancellationToken cancellationToken); - - /// - /// Creates the client. - /// - /// The client identifier. - /// The secret. - /// Name of the client. - /// The client description. - /// The allowed scopes. - /// The allowed grant types. - /// The client redirect uris. - /// The client post logout redirect uris. - /// if set to true [require consent]. - /// if set to true [allow offline access]. - /// The cancellation token. - /// - Task CreateClient(String clientId, - String secret, - String clientName, - String clientDescription, - List allowedScopes, - List allowedGrantTypes, - List clientRedirectUris, - List clientPostLogoutRedirectUris, - Boolean requireConsent, - Boolean allowOfflineAccess, - CancellationToken cancellationToken); - - /// - /// Creates the identity resource. - /// - /// The name. - /// The display name. - /// The description. - /// if set to true [required]. - /// if set to true [emphasize]. - /// if set to true [show in discovery document]. - /// The claims. - /// The cancellation token. - /// - Task CreateIdentityResource(String name, - String displayName, - String description, - Boolean required, - Boolean emphasize, - Boolean showInDiscoveryDocument, - List claims, - CancellationToken cancellationToken); - - /// - /// Creates the role. - /// - /// Name of the role. - /// The cancellation token. - /// - Task CreateRole(String roleName, - CancellationToken cancellationToken); - - /// - /// Registers the user. - /// - /// Name of the given. - /// Name of the middle. - /// Name of the family. - /// Name of the user. - /// The password. - /// The email address. - /// The phone number. - /// The claims. - /// The roles. - /// The cancellation token. - /// - Task CreateUser(String givenName, - String middleName, - String familyName, - String userName, - String password, - String emailAddress, - String phoneNumber, - Dictionary claims, - List roles, - CancellationToken cancellationToken); - - /// - /// Gets the API resource. - /// - /// Name of the API resource. - /// The cancellation token. - /// - Task GetApiResource(String apiResourceName, - CancellationToken cancellationToken); - - /// - /// Gets the API resources. - /// - /// The cancellation token. - /// - Task> GetApiResources(CancellationToken cancellationToken); - - /// - /// Gets the client. - /// - /// The client identifier. - /// The cancellation token. - /// - Task GetClient(String clientId, - CancellationToken cancellationToken); - - /// - /// Gets the clients. - /// - /// The cancellation token. - /// - Task> GetClients(CancellationToken cancellationToken); - - /// - /// Gets the identity resource. - /// - /// Name of the identity resource. - /// The cancellation token. - /// - Task GetIdentityResource(String identityResourceName, - CancellationToken cancellationToken); - - /// - /// Gets the API resources. - /// - /// The cancellation token. - /// - Task> GetIdentityResources(CancellationToken cancellationToken); - - /// - /// Gets the role. - /// - /// The role identifier. - /// The cancellation token. - /// - Task GetRole(Guid roleId, - CancellationToken cancellationToken); - - /// - /// Gets the roles. - /// - /// The cancellation token. - /// - Task> GetRoles(CancellationToken cancellationToken); - - /// - /// Gets the user by user identifier. - /// - /// The user identifier. - /// The cancellation token. - /// - Task GetUser(Guid userId, - CancellationToken cancellationToken); - - /// - /// Gets the users. - /// - /// Name of the user. - /// The cancellation token. - /// - Task> GetUsers(String userName, - CancellationToken cancellationToken); - - /// - /// Signouts this instance. - /// - /// - Task Signout(); - - /// - /// Validates the credentials. - /// - /// Name of the user. - /// The password. - /// The cancellation token. - /// - Task ValidateCredentials(String userName, - String password, - CancellationToken cancellationToken); - - #endregion - } -} \ No newline at end of file diff --git a/SecurityService.Manager/SecurityService.Manager.csproj b/SecurityService.Manager/SecurityService.Manager.csproj deleted file mode 100644 index 876bf959..00000000 --- a/SecurityService.Manager/SecurityService.Manager.csproj +++ /dev/null @@ -1,37 +0,0 @@ - - - - net5.0 - - - - - - - - - - - - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - - - - - - - - - - - - diff --git a/SecurityService.Models/AccountOptions.cs b/SecurityService.Models/AccountOptions.cs index 9e800c8a..02486fdb 100644 --- a/SecurityService.Models/AccountOptions.cs +++ b/SecurityService.Models/AccountOptions.cs @@ -3,9 +3,6 @@ using System; using System.Diagnostics.CodeAnalysis; - /// - /// - /// [ExcludeFromCodeCoverage] public class AccountOptions { diff --git a/SecurityService.Models/ConsentOptions.cs b/SecurityService.Models/ConsentOptions.cs index 4b46abe3..ff40014f 100644 --- a/SecurityService.Models/ConsentOptions.cs +++ b/SecurityService.Models/ConsentOptions.cs @@ -3,9 +3,6 @@ using System; using System.Diagnostics.CodeAnalysis; - /// - /// - /// [ExcludeFromCodeCoverage] public class ConsentOptions { diff --git a/SecurityService.Models/RoleDetails.cs b/SecurityService.Models/RoleDetails.cs index e5e165b9..1cea4f7f 100644 --- a/SecurityService.Models/RoleDetails.cs +++ b/SecurityService.Models/RoleDetails.cs @@ -1,9 +1,6 @@ -using System; -using System.Collections.Generic; -using System.Text; - -namespace SecurityService.Models +namespace SecurityService.Models { + using System; using System.Diagnostics.CodeAnalysis; [ExcludeFromCodeCoverage] @@ -25,4 +22,4 @@ public class RoleDetails /// public String RoleName { get; set; } } -} +} \ No newline at end of file diff --git a/SecurityService.Models/SecurityService.Models.csproj b/SecurityService.Models/SecurityService.Models.csproj index 0bf14e11..f208d303 100644 --- a/SecurityService.Models/SecurityService.Models.csproj +++ b/SecurityService.Models/SecurityService.Models.csproj @@ -1,7 +1,7 @@ - net5.0 + net5.0 diff --git a/SecurityService.Models/UserDetails.cs b/SecurityService.Models/UserDetails.cs index 288a8e64..f949b3f4 100644 --- a/SecurityService.Models/UserDetails.cs +++ b/SecurityService.Models/UserDetails.cs @@ -1,9 +1,7 @@ -using System; -using System.Collections.Generic; -using System.Text; - -namespace SecurityService.Models +namespace SecurityService.Models { + using System; + using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; [ExcludeFromCodeCoverage] diff --git a/SecurityService.OpenIdConnect.IntegrationTests/Common/DockerHelper.cs b/SecurityService.OpenIdConnect.IntegrationTests/Common/DockerHelper.cs index 790301b4..a5af636e 100644 --- a/SecurityService.OpenIdConnect.IntegrationTests/Common/DockerHelper.cs +++ b/SecurityService.OpenIdConnect.IntegrationTests/Common/DockerHelper.cs @@ -13,6 +13,7 @@ using Ductus.FluentDocker.Builders; using Ductus.FluentDocker.Commands; using Ductus.FluentDocker.Common; + using Ductus.FluentDocker.Model.Builders; using Ductus.FluentDocker.Services; using Ductus.FluentDocker.Services.Extensions; using Shared.Logger; @@ -105,7 +106,7 @@ public override async Task StartContainersForScenarioRun(String scenarioName) (String, String, String) dockerCredentials = ("https://www.docker.com", "stuartferguson", "Sc0tland"); // Setup the container names - this.SecurityServiceContainerName = $"securityservice{testGuid:N}"; + this.SecurityServiceContainerName = $"identity-server"; this.SecurityServiceTestUIContainerName = $"securityservicetestui{testGuid:N}"; INetworkService testNetwork = this.SetupTestNetwork(); @@ -115,10 +116,10 @@ public override async Task StartContainersForScenarioRun(String scenarioName) this.Logger, "securityservice", testNetwork, - 5551, + 5001, dockerCredentials); - this.SecurityServicePort = securityServiceContainer.ToHostExposedEndpoint("5551/tcp").Port; + this.SecurityServicePort = securityServiceContainer.ToHostExposedEndpoint("5001/tcp").Port; IContainerService securityServiceTestUIContainer = DockerHelper.SetupSecurityServiceTestUIContainer(this.SecurityServiceTestUIContainerName, this.SecurityServiceContainerName, @@ -128,7 +129,7 @@ public override async Task StartContainersForScenarioRun(String scenarioName) this.SecurityServiceTestUIPort = securityServiceTestUIContainer.ToHostExposedEndpoint("5004/tcp").Port; - Func securityServiceBaseAddressResolver = api => $"http://127.0.0.1:{this.SecurityServicePort}"; + Func securityServiceBaseAddressResolver = api => $"https://localhost:{this.SecurityServicePort}"; HttpClient httpClient = new HttpClient(); this.SecurityServiceClient = new SecurityServiceClient(securityServiceBaseAddressResolver, httpClient); @@ -238,10 +239,12 @@ private static IContainerService SetupSecurityServiceContainer(String containerN logger.LogInformation("About to Start Security Container"); List environmentVariables = new List(); - environmentVariables.Add($"ServiceOptions:PublicOrigin=http://{containerName}:{dockerPort}"); - environmentVariables.Add($"ServiceOptions:IssuerUrl=http://{containerName}:{dockerPort}"); + environmentVariables.Add($"ServiceOptions:PublicOrigin=https://identity-server:{dockerPort}"); + environmentVariables.Add($"ServiceOptions:IssuerUrl=https://identity-server:{dockerPort}"); environmentVariables.Add("ASPNETCORE_ENVIRONMENT=IntegrationTest"); - environmentVariables.Add("urls=http://*:5551"); + environmentVariables.Add("urls=https://*:5001"); + environmentVariables.Add("ASPNETCORE_Kestrel__Certificates__Default__Password=password"); + environmentVariables.Add("ASPNETCORE_Kestrel__Certificates__Default__Path=aspnetapp-identity-server.pfx"); if (additionalEnvironmentVariables != null) { @@ -250,7 +253,7 @@ private static IContainerService SetupSecurityServiceContainer(String containerN ContainerBuilder securityServiceContainer = new Builder().UseContainer().WithName(containerName) .WithEnvironment(environmentVariables.ToArray()).UseImage(imageName, forceLatestImage) - .ExposePort(dockerPort, 5551).UseNetwork(new List + .ExposePort(dockerPort, 5001).UseNetwork(new List { networkService }.ToArray()); @@ -261,10 +264,11 @@ private static IContainerService SetupSecurityServiceContainer(String containerN } // Now build and return the container - IContainerService builtContainer = securityServiceContainer.Build().Start().WaitForPort("5551/tcp", 30000); + IContainerService builtContainer = securityServiceContainer.Build().Start().WaitForPort("5001/tcp", 30000); Thread.Sleep(20000); // This hack is in till health checks implemented :| - DockerHelper.AddEntryToHostsFile("127.0.0.1", containerName); + //DockerHelper.AddEntryToHostsFile("127.0.0.1", containerName); + DockerHelper.AddEntryToHostsFile("localhost", containerName); logger.LogInformation("Security Service Container Started"); @@ -288,10 +292,13 @@ private static IContainerService SetupSecurityServiceTestUIContainer(String cont { // Management API Container IContainerService securityServiceTestUIContainer = new Builder().UseContainer().WithName(containerName) - .WithEnvironment($"Authority=http://{securityServiceContainerName}:{securityServiceContainerPort}", + .WithEnvironment($"Authority=https://identity-server:{securityServiceContainerPort}", $"ClientId={clientDetails.clientId}", - $"ClientSecret={clientDetails.clientSecret}") //, - .UseImage("securityservicetestwebclient").ExposePort(5004) + $"ClientSecret={clientDetails.clientSecret}", + "urls=https://*:5004", + "ASPNETCORE_Kestrel__Certificates__Default__Password=password", + "ASPNETCORE_Kestrel__Certificates__Default__Path=aspnetapp-web-api.pfx") + .UseImage("securityservicetestui").ExposePort(5004) .UseNetwork(new List { networkService diff --git a/SecurityService.OpenIdConnect.IntegrationTests/Common/Hooks.cs b/SecurityService.OpenIdConnect.IntegrationTests/Common/Hooks.cs index 959633c2..41f0a20b 100644 --- a/SecurityService.OpenIdConnect.IntegrationTests/Common/Hooks.cs +++ b/SecurityService.OpenIdConnect.IntegrationTests/Common/Hooks.cs @@ -66,7 +66,7 @@ public void AfterScenario() public async Task BeforeScenario() { String? browser = Environment.GetEnvironmentVariable("Browser"); - ///browser = "Firefox"; + browser = "Chrome"; if (browser == null || browser == "Chrome") { @@ -74,10 +74,10 @@ public async Task BeforeScenario() options.AddArguments("--disable-gpu"); options.AddArguments("--no-sandbox"); options.AddArguments("--disable-dev-shm-usage"); - var experimentalFlags = new List(); - experimentalFlags.Add("same-site-by-default-cookies@2"); - experimentalFlags.Add("cookies-without-same-site-must-be-secure@2"); - options.AddLocalStatePreference("browser.enabled_labs_experiments", experimentalFlags); + //var experimentalFlags = new List(); + //experimentalFlags.Add("same-site-by-default-cookies@2"); + //experimentalFlags.Add("cookies-without-same-site-must-be-secure@2"); + //options.AddLocalStatePreference("browser.enabled_labs_experiments", experimentalFlags); this.WebDriver = new ChromeDriver(options); } @@ -102,10 +102,10 @@ public async Task BeforeScenario() { EdgeOptions options = new EdgeOptions(); options.UseChromium = true; - List experimentalFlags = new List(); - experimentalFlags.Add("same-site-by-default-cookies@2"); - experimentalFlags.Add("cookies-without-same-site-must-be-secure@2"); - options.AddLocalStatePreference("browser.enabled_labs_experiments", experimentalFlags); + //List experimentalFlags = new List(); + //experimentalFlags.Add("same-site-by-default-cookies@2"); + //experimentalFlags.Add("cookies-without-same-site-must-be-secure@2"); + //options.AddLocalStatePreference("browser.enabled_labs_experiments", experimentalFlags); this.WebDriver = new EdgeDriver(options); } diff --git a/SecurityService.OpenIdConnect.IntegrationTests/Common/SharedSteps.cs b/SecurityService.OpenIdConnect.IntegrationTests/Common/SharedSteps.cs index 5eca45cc..8dda4713 100644 --- a/SecurityService.OpenIdConnect.IntegrationTests/Common/SharedSteps.cs +++ b/SecurityService.OpenIdConnect.IntegrationTests/Common/SharedSteps.cs @@ -166,9 +166,9 @@ public async Task GivenICreateTheFollowingClients(Table table) String postLogoutRedirectUris = SpecflowTableHelper.GetStringRowValue(tableRow, "PostLogoutRedirectUris"); scopes = scopes.Replace("[id]", this.TestingContext.DockerHelper.TestId.ToString("N")); - redirectUris = redirectUris.Replace("[url]", this.TestingContext.DockerHelper.SecurityServiceContainerName); + redirectUris = redirectUris.Replace("[url]", "localhost"); redirectUris = redirectUris.Replace("[port]", this.TestingContext.DockerHelper.SecurityServiceTestUIPort.ToString()); - postLogoutRedirectUris = postLogoutRedirectUris.Replace("[url]", this.TestingContext.DockerHelper.SecurityServiceContainerName); + postLogoutRedirectUris = postLogoutRedirectUris.Replace("[url]", "localhost"); postLogoutRedirectUris = postLogoutRedirectUris.Replace("[port]", this.TestingContext.DockerHelper.SecurityServiceTestUIPort.ToString()); CreateClientRequest createClientRequest = new CreateClientRequest diff --git a/SecurityService.OpenIdConnect.IntegrationTests/UserLogin/UserLogin.feature b/SecurityService.OpenIdConnect.IntegrationTests/UserLogin/UserLogin.feature index dd8a6112..63f2d4f7 100644 --- a/SecurityService.OpenIdConnect.IntegrationTests/UserLogin/UserLogin.feature +++ b/SecurityService.OpenIdConnect.IntegrationTests/UserLogin/UserLogin.feature @@ -19,7 +19,7 @@ Background: Given I create the following clients | ClientId | Name | Secret | Scopes | GrantTypes | RedirectUris | PostLogoutRedirectUris | RequireConsent | AllowOfflineAccess | - | estateUIClient | Merchant Client | Secret1 | estateManagement,openid,email,profile | hybrid | http://[url]:[port]/signin-oidc | http://[url]:[port]/signout-oidc | false | true | + | estateUIClient | Merchant Client | Secret1 | estateManagement,openid,email,profile | hybrid | https://[url]:[port]/signin-oidc | https://[url]:[port]/signout-oidc | false | true | Given I create the following users | Email Address | Password | Phone Number | Given Name | Middle Name | Family Name | Claims | Roles | diff --git a/SecurityService.OpenIdConnect.IntegrationTests/UserLogin/UserLogin.feature.cs b/SecurityService.OpenIdConnect.IntegrationTests/UserLogin/UserLogin.feature.cs index 2c750950..e2d3ded1 100644 --- a/SecurityService.OpenIdConnect.IntegrationTests/UserLogin/UserLogin.feature.cs +++ b/SecurityService.OpenIdConnect.IntegrationTests/UserLogin/UserLogin.feature.cs @@ -149,8 +149,8 @@ public virtual void FeatureBackground() "Secret1", "estateManagement,openid,email,profile", "hybrid", - "http://[url]:[port]/signin-oidc", - "http://[url]:[port]/signout-oidc", + "https://[url]:[port]/signin-oidc", + "https://[url]:[port]/signout-oidc", "false", "true"}); #line 20 diff --git a/SecurityService.OpenIdConnect.IntegrationTests/UserLogin/UserLoginSteps.cs b/SecurityService.OpenIdConnect.IntegrationTests/UserLogin/UserLoginSteps.cs index d6ace27a..cc3ba92a 100644 --- a/SecurityService.OpenIdConnect.IntegrationTests/UserLogin/UserLoginSteps.cs +++ b/SecurityService.OpenIdConnect.IntegrationTests/UserLogin/UserLoginSteps.cs @@ -50,8 +50,8 @@ public UserLoginSteps(TestingContext testingContext, [Given(@"I am on the application home page")] public void GivenIAmOnTheApplicationHomePage() { - this.WebDriver.Navigate().GoToUrl($"http://{this.TestingContext.DockerHelper.SecurityServiceContainerName}:{this.TestingContext.DockerHelper.SecurityServiceTestUIPort}"); - this.WebDriver.Title.ShouldBe("Home Page - SecurityServiceTestWebClient"); + this.WebDriver.Navigate().GoToUrl($"https://localhost:{this.TestingContext.DockerHelper.SecurityServiceTestUIPort}"); + this.WebDriver.Title.ShouldBe("Home Page - SecurityServiceTestUI"); } [When(@"I click the '(.*)' link")] @@ -84,7 +84,7 @@ await Retry.For(async () => Console.WriteLine($"Source Is [{page}"); - this.WebDriver.Title.ShouldBe("Privacy Policy - SecurityServiceTestWebClient"); + this.WebDriver.Title.ShouldBe("Privacy Policy - SecurityServiceTestUI"); }); diff --git a/SecurityService.UnitTests/BootstrapperTests.cs b/SecurityService.UnitTests/BootstrapperTests.cs index 0977a85a..883af2ec 100644 --- a/SecurityService.UnitTests/BootstrapperTests.cs +++ b/SecurityService.UnitTests/BootstrapperTests.cs @@ -2,8 +2,8 @@ { using System; using System.Collections.Generic; - using IdentityServer4.Services; - using IdentityServer4.Stores; + using Duende.IdentityServer.Services; + using Duende.IdentityServer.Stores; using Lamar; using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.DataProtection; diff --git a/SecurityService.UnitTests/ModelFactoryTests.cs b/SecurityService.UnitTests/ModelFactoryTests.cs index c996d160..6716cfcf 100644 --- a/SecurityService.UnitTests/ModelFactoryTests.cs +++ b/SecurityService.UnitTests/ModelFactoryTests.cs @@ -4,8 +4,8 @@ using System.Collections.Generic; using System.Linq; using DataTransferObjects.Responses; + using Duende.IdentityServer.Models; using Factories; - using IdentityServer4.Models; using Shouldly; using Xunit; using RoleDetails = Models.RoleDetails; diff --git a/SecurityService.UnitTests/SecurityService.UnitTests.csproj b/SecurityService.UnitTests/SecurityService.UnitTests.csproj index cbe0a1b3..ff0e272b 100644 --- a/SecurityService.UnitTests/SecurityService.UnitTests.csproj +++ b/SecurityService.UnitTests/SecurityService.UnitTests.csproj @@ -25,7 +25,7 @@ - + diff --git a/SecurityService.UnitTests/SecurityServiceManagerTestSetup.cs b/SecurityService.UnitTests/SecurityServiceManagerTestSetup.cs index 615b9ccb..f2c76140 100644 --- a/SecurityService.UnitTests/SecurityServiceManagerTestSetup.cs +++ b/SecurityService.UnitTests/SecurityServiceManagerTestSetup.cs @@ -6,11 +6,9 @@ using System.Security.Claims; using System.Threading; using System.Threading.Tasks; - using IdentityServer4.EntityFramework.DbContexts; - using IdentityServer4.EntityFramework.Entities; - using IdentityServer4.EntityFramework.Interfaces; - using IdentityServer4.EntityFramework.Options; - using Manager; + using BusinessLogic; + using Duende.IdentityServer.EntityFramework.DbContexts; + using Duende.IdentityServer.EntityFramework.Options; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Identity; using Microsoft.EntityFrameworkCore; diff --git a/SecurityService.UnitTests/SecurityServiceManagerTests.cs b/SecurityService.UnitTests/SecurityServiceManagerTests.cs index 898c5d2c..b0d5c913 100644 --- a/SecurityService.UnitTests/SecurityServiceManagerTests.cs +++ b/SecurityService.UnitTests/SecurityServiceManagerTests.cs @@ -6,15 +6,15 @@ using System.Security.Claims; using System.Threading; using System.Threading.Tasks; + using BusinessLogic.Exceptions; + using Duende.IdentityServer.EntityFramework.DbContexts; + using Duende.IdentityServer.EntityFramework.Entities; using IdentityModel; - using IdentityServer4.EntityFramework.DbContexts; - using IdentityServer4.EntityFramework.Entities; - using Manager; - using Manager.Exceptions; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Identity; using Models; using Moq; + using SecurityService.BusinessLogic; using Shared.Exceptions; using Shouldly; using Xunit; @@ -613,7 +613,7 @@ await context.ApiResources.AddAsync(new ApiResource SecurityServiceManager securityServiceManager = this.SetupSecurityServiceManager(context); - IdentityServer4.Models.ApiResource apiResource = + Duende.IdentityServer.Models.ApiResource apiResource = await securityServiceManager.GetApiResource(SecurityServiceManagerTestData.ApiResourceName, CancellationToken.None); apiResource.Name.ShouldBe(SecurityServiceManagerTestData.ApiResourceName); @@ -682,7 +682,7 @@ await context.ApiResources.AddAsync(new ApiResource SecurityServiceManager securityServiceManager = this.SetupSecurityServiceManager(context); - List apiResources = await securityServiceManager.GetApiResources(CancellationToken.None); + List apiResources = await securityServiceManager.GetApiResources(CancellationToken.None); apiResources.ShouldNotBeNull(); apiResources.ShouldNotBeEmpty(); @@ -740,7 +740,7 @@ await context.Clients.AddAsync(new Client SecurityServiceManager securityServiceManager = this.SetupSecurityServiceManager(context); - IdentityServer4.Models.Client client = await securityServiceManager.GetClient(SecurityServiceManagerTestData.ClientId, CancellationToken.None); + Duende.IdentityServer.Models.Client client = await securityServiceManager.GetClient(SecurityServiceManagerTestData.ClientId, CancellationToken.None); client.ClientId.ShouldBe(SecurityServiceManagerTestData.ClientId); client.ClientName.ShouldBe(SecurityServiceManagerTestData.ClientName); @@ -810,7 +810,7 @@ await context.Clients.AddAsync(new Client SecurityServiceManager securityServiceManager = this.SetupSecurityServiceManager(context); - List clients = await securityServiceManager.GetClients(CancellationToken.None); + List clients = await securityServiceManager.GetClients(CancellationToken.None); clients.ShouldNotBeNull(); clients.ShouldNotBeEmpty(); @@ -841,7 +841,7 @@ await context.IdentityResources.AddAsync(new IdentityResource SecurityServiceManager securityServiceManager = this.SetupSecurityServiceManager(context); - IdentityServer4.Models.IdentityResource identityResource = + Duende.IdentityServer.Models.IdentityResource identityResource = await securityServiceManager.GetIdentityResource(SecurityServiceManagerTestData.IdentityResourceName, CancellationToken.None); identityResource.Name.ShouldBe(SecurityServiceManagerTestData.IdentityResourceName); @@ -891,7 +891,7 @@ await context.IdentityResources.AddAsync(new IdentityResource SecurityServiceManager securityServiceManager = this.SetupSecurityServiceManager(context); - List identityResources = await securityServiceManager.GetIdentityResources(CancellationToken.None); + List identityResources = await securityServiceManager.GetIdentityResources(CancellationToken.None); identityResources.ShouldNotBeNull(); identityResources.ShouldNotBeEmpty(); @@ -1128,7 +1128,7 @@ await context.ApiScopes.AddAsync(new ApiScope SecurityServiceManager securityServiceManager = this.SetupSecurityServiceManager(context); - IdentityServer4.Models.ApiScope apiScope = await securityServiceManager.GetApiScope(SecurityServiceManagerTestData.ApiScopeName, CancellationToken.None); + Duende.IdentityServer.Models.ApiScope apiScope = await securityServiceManager.GetApiScope(SecurityServiceManagerTestData.ApiScopeName, CancellationToken.None); apiScope.Name.ShouldBe(SecurityServiceManagerTestData.ApiScopeName); apiScope.Description.ShouldBe(SecurityServiceManagerTestData.ApiScopeDescription); @@ -1174,7 +1174,7 @@ await context.ApiScopes.AddAsync(new ApiScope SecurityServiceManager securityServiceManager = this.SetupSecurityServiceManager(context); - List apiScopes = await securityServiceManager.GetApiScopes(CancellationToken.None); + List apiScopes = await securityServiceManager.GetApiScopes(CancellationToken.None); apiScopes.ShouldNotBeNull(); apiScopes.ShouldNotBeEmpty(); diff --git a/SecurityService.sln b/SecurityService.sln index b1762065..561b915e 100644 --- a/SecurityService.sln +++ b/SecurityService.sln @@ -1,31 +1,31 @@  Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Version 16 -VisualStudioVersion = 16.0.28711.60 +VisualStudioVersion = 16.0.31321.278 MinimumVisualStudioVersion = 10.0.40219.1 -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{892940BA-FF36-468A-B8AD-34379F15CFA5}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SecurityService", "SecurityService\SecurityService.csproj", "{5840CEF3-26C0-4323-A549-5D1560B1AFFA}" EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{A4EF772C-5311-4633-94C5-2D45BFD25432}" +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{FBA324D4-A2B7-4539-B63E-AF254EA7DA50}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SecurityService.Manager", "SecurityService.Manager\SecurityService.Manager.csproj", "{5B6E1756-8A03-4AEF-BD69-DB216E7C1768}" +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{62BD199E-BDB7-4D33-92E4-3FE97D5EBC91}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SecurityService.DataTransferObjects", "SecurityService.DataTransferObjects\SecurityService.DataTransferObjects.csproj", "{50FF6ECD-4223-4262-B14F-433A502E0CEB}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SecurityServiceTestUI", "SecurityServiceTestUI\SecurityServiceTestUI.csproj", "{22896ACB-CC99-4C85-B0E1-BCECD4C6237E}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SecurityService.UnitTests", "SecurityService.UnitTests\SecurityService.UnitTests.csproj", "{BAAC4343-4F17-4B3C-80F0-DA7BB647180C}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SecurityService.BusinessLogic", "SecurityService.BusinessLogic\SecurityService.BusinessLogic.csproj", "{C2CC4428-8084-4F01-8805-C96DD5CCC8A1}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SecurityService", "SecurityService\SecurityService.csproj", "{54A4CB95-033D-4D83-A1E7-D6184F54A61D}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SecurityService.Models", "SecurityService.Models\SecurityService.Models.csproj", "{30AD0D29-6620-4A66-978E-4633E1771BB4}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SecurityService.Models", "SecurityService.Models\SecurityService.Models.csproj", "{BA43067E-A3F4-4939-A465-F3270F273C34}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SecurityService.Database", "SecurityService.Database\SecurityService.Database.csproj", "{DACF45B4-E05C-483A-B392-D3C08D98F93E}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SecurityService.Database", "SecurityService.Database\SecurityService.Database.csproj", "{BE33088C-6CDC-47C1-938E-431661AEEBDB}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SecurityService.DataTransferObjects", "SecurityService.DataTransferObjects\SecurityService.DataTransferObjects.csproj", "{50CA3826-663C-423A-A872-6BFE5B43A638}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SecurityService.IntegrationTests", "SecurityService.IntegrationTests\SecurityService.IntegrationTests.csproj", "{F49D537A-BD95-42BD-80AB-C1744A306769}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SecurityService.UnitTests", "SecurityService.UnitTests\SecurityService.UnitTests.csproj", "{7B581D8A-EB93-47D4-9802-F5AA04536D00}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SecurityService.Client", "SecurityService.Client\SecurityService.Client.csproj", "{26E284A5-7AF9-489E-90AB-2C92C4713550}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SecurityService.Client", "SecurityService.Client\SecurityService.Client.csproj", "{7CC70B33-75CD-46C0-82A5-87E5E60C9535}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SecurityServiceTestWebClient", "SecurityServiceTestWebClient\SecurityServiceTestWebClient.csproj", "{67C9AB6A-D59B-4597-ABAB-1B9578698796}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SecurityService.IntegrationTests", "SecurityService.IntegrationTests\SecurityService.IntegrationTests.csproj", "{28C72B39-1803-49D7-9289-C71A620E4EF1}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SecurityService.OpenIdConnect.IntegrationTests", "SecurityService.OpenIdConnect.IntegrationTests\SecurityService.OpenIdConnect.IntegrationTests.csproj", "{06A11669-7D02-40EA-9C68-F8CD178149A7}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SecurityService.OpenIdConnect.IntegrationTests", "SecurityService.OpenIdConnect.IntegrationTests\SecurityService.OpenIdConnect.IntegrationTests.csproj", "{5BAEC61F-39FF-4197-A73A-A8A8B5BDFE86}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -33,63 +33,63 @@ Global Release|Any CPU = Release|Any CPU EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution - {5B6E1756-8A03-4AEF-BD69-DB216E7C1768}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {5B6E1756-8A03-4AEF-BD69-DB216E7C1768}.Debug|Any CPU.Build.0 = Debug|Any CPU - {5B6E1756-8A03-4AEF-BD69-DB216E7C1768}.Release|Any CPU.ActiveCfg = Release|Any CPU - {5B6E1756-8A03-4AEF-BD69-DB216E7C1768}.Release|Any CPU.Build.0 = Release|Any CPU - {50FF6ECD-4223-4262-B14F-433A502E0CEB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {50FF6ECD-4223-4262-B14F-433A502E0CEB}.Debug|Any CPU.Build.0 = Debug|Any CPU - {50FF6ECD-4223-4262-B14F-433A502E0CEB}.Release|Any CPU.ActiveCfg = Release|Any CPU - {50FF6ECD-4223-4262-B14F-433A502E0CEB}.Release|Any CPU.Build.0 = Release|Any CPU - {BAAC4343-4F17-4B3C-80F0-DA7BB647180C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {BAAC4343-4F17-4B3C-80F0-DA7BB647180C}.Debug|Any CPU.Build.0 = Debug|Any CPU - {BAAC4343-4F17-4B3C-80F0-DA7BB647180C}.Release|Any CPU.ActiveCfg = Release|Any CPU - {BAAC4343-4F17-4B3C-80F0-DA7BB647180C}.Release|Any CPU.Build.0 = Release|Any CPU - {54A4CB95-033D-4D83-A1E7-D6184F54A61D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {54A4CB95-033D-4D83-A1E7-D6184F54A61D}.Debug|Any CPU.Build.0 = Debug|Any CPU - {54A4CB95-033D-4D83-A1E7-D6184F54A61D}.Release|Any CPU.ActiveCfg = Release|Any CPU - {54A4CB95-033D-4D83-A1E7-D6184F54A61D}.Release|Any CPU.Build.0 = Release|Any CPU - {BA43067E-A3F4-4939-A465-F3270F273C34}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {BA43067E-A3F4-4939-A465-F3270F273C34}.Debug|Any CPU.Build.0 = Debug|Any CPU - {BA43067E-A3F4-4939-A465-F3270F273C34}.Release|Any CPU.ActiveCfg = Release|Any CPU - {BA43067E-A3F4-4939-A465-F3270F273C34}.Release|Any CPU.Build.0 = Release|Any CPU - {BE33088C-6CDC-47C1-938E-431661AEEBDB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {BE33088C-6CDC-47C1-938E-431661AEEBDB}.Debug|Any CPU.Build.0 = Debug|Any CPU - {BE33088C-6CDC-47C1-938E-431661AEEBDB}.Release|Any CPU.ActiveCfg = Release|Any CPU - {BE33088C-6CDC-47C1-938E-431661AEEBDB}.Release|Any CPU.Build.0 = Release|Any CPU - {F49D537A-BD95-42BD-80AB-C1744A306769}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {F49D537A-BD95-42BD-80AB-C1744A306769}.Debug|Any CPU.Build.0 = Debug|Any CPU - {F49D537A-BD95-42BD-80AB-C1744A306769}.Release|Any CPU.ActiveCfg = Release|Any CPU - {F49D537A-BD95-42BD-80AB-C1744A306769}.Release|Any CPU.Build.0 = Release|Any CPU - {26E284A5-7AF9-489E-90AB-2C92C4713550}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {26E284A5-7AF9-489E-90AB-2C92C4713550}.Debug|Any CPU.Build.0 = Debug|Any CPU - {26E284A5-7AF9-489E-90AB-2C92C4713550}.Release|Any CPU.ActiveCfg = Release|Any CPU - {26E284A5-7AF9-489E-90AB-2C92C4713550}.Release|Any CPU.Build.0 = Release|Any CPU - {67C9AB6A-D59B-4597-ABAB-1B9578698796}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {67C9AB6A-D59B-4597-ABAB-1B9578698796}.Debug|Any CPU.Build.0 = Debug|Any CPU - {67C9AB6A-D59B-4597-ABAB-1B9578698796}.Release|Any CPU.ActiveCfg = Release|Any CPU - {67C9AB6A-D59B-4597-ABAB-1B9578698796}.Release|Any CPU.Build.0 = Release|Any CPU - {06A11669-7D02-40EA-9C68-F8CD178149A7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {06A11669-7D02-40EA-9C68-F8CD178149A7}.Debug|Any CPU.Build.0 = Debug|Any CPU - {06A11669-7D02-40EA-9C68-F8CD178149A7}.Release|Any CPU.ActiveCfg = Release|Any CPU - {06A11669-7D02-40EA-9C68-F8CD178149A7}.Release|Any CPU.Build.0 = Release|Any CPU + {5840CEF3-26C0-4323-A549-5D1560B1AFFA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {5840CEF3-26C0-4323-A549-5D1560B1AFFA}.Debug|Any CPU.Build.0 = Debug|Any CPU + {5840CEF3-26C0-4323-A549-5D1560B1AFFA}.Release|Any CPU.ActiveCfg = Release|Any CPU + {5840CEF3-26C0-4323-A549-5D1560B1AFFA}.Release|Any CPU.Build.0 = Release|Any CPU + {22896ACB-CC99-4C85-B0E1-BCECD4C6237E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {22896ACB-CC99-4C85-B0E1-BCECD4C6237E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {22896ACB-CC99-4C85-B0E1-BCECD4C6237E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {22896ACB-CC99-4C85-B0E1-BCECD4C6237E}.Release|Any CPU.Build.0 = Release|Any CPU + {C2CC4428-8084-4F01-8805-C96DD5CCC8A1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C2CC4428-8084-4F01-8805-C96DD5CCC8A1}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C2CC4428-8084-4F01-8805-C96DD5CCC8A1}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C2CC4428-8084-4F01-8805-C96DD5CCC8A1}.Release|Any CPU.Build.0 = Release|Any CPU + {30AD0D29-6620-4A66-978E-4633E1771BB4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {30AD0D29-6620-4A66-978E-4633E1771BB4}.Debug|Any CPU.Build.0 = Debug|Any CPU + {30AD0D29-6620-4A66-978E-4633E1771BB4}.Release|Any CPU.ActiveCfg = Release|Any CPU + {30AD0D29-6620-4A66-978E-4633E1771BB4}.Release|Any CPU.Build.0 = Release|Any CPU + {DACF45B4-E05C-483A-B392-D3C08D98F93E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {DACF45B4-E05C-483A-B392-D3C08D98F93E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {DACF45B4-E05C-483A-B392-D3C08D98F93E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {DACF45B4-E05C-483A-B392-D3C08D98F93E}.Release|Any CPU.Build.0 = Release|Any CPU + {50CA3826-663C-423A-A872-6BFE5B43A638}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {50CA3826-663C-423A-A872-6BFE5B43A638}.Debug|Any CPU.Build.0 = Debug|Any CPU + {50CA3826-663C-423A-A872-6BFE5B43A638}.Release|Any CPU.ActiveCfg = Release|Any CPU + {50CA3826-663C-423A-A872-6BFE5B43A638}.Release|Any CPU.Build.0 = Release|Any CPU + {7B581D8A-EB93-47D4-9802-F5AA04536D00}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {7B581D8A-EB93-47D4-9802-F5AA04536D00}.Debug|Any CPU.Build.0 = Debug|Any CPU + {7B581D8A-EB93-47D4-9802-F5AA04536D00}.Release|Any CPU.ActiveCfg = Release|Any CPU + {7B581D8A-EB93-47D4-9802-F5AA04536D00}.Release|Any CPU.Build.0 = Release|Any CPU + {7CC70B33-75CD-46C0-82A5-87E5E60C9535}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {7CC70B33-75CD-46C0-82A5-87E5E60C9535}.Debug|Any CPU.Build.0 = Debug|Any CPU + {7CC70B33-75CD-46C0-82A5-87E5E60C9535}.Release|Any CPU.ActiveCfg = Release|Any CPU + {7CC70B33-75CD-46C0-82A5-87E5E60C9535}.Release|Any CPU.Build.0 = Release|Any CPU + {28C72B39-1803-49D7-9289-C71A620E4EF1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {28C72B39-1803-49D7-9289-C71A620E4EF1}.Debug|Any CPU.Build.0 = Debug|Any CPU + {28C72B39-1803-49D7-9289-C71A620E4EF1}.Release|Any CPU.ActiveCfg = Release|Any CPU + {28C72B39-1803-49D7-9289-C71A620E4EF1}.Release|Any CPU.Build.0 = Release|Any CPU + {5BAEC61F-39FF-4197-A73A-A8A8B5BDFE86}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {5BAEC61F-39FF-4197-A73A-A8A8B5BDFE86}.Debug|Any CPU.Build.0 = Debug|Any CPU + {5BAEC61F-39FF-4197-A73A-A8A8B5BDFE86}.Release|Any CPU.ActiveCfg = Release|Any CPU + {5BAEC61F-39FF-4197-A73A-A8A8B5BDFE86}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection GlobalSection(NestedProjects) = preSolution - {5B6E1756-8A03-4AEF-BD69-DB216E7C1768} = {892940BA-FF36-468A-B8AD-34379F15CFA5} - {50FF6ECD-4223-4262-B14F-433A502E0CEB} = {892940BA-FF36-468A-B8AD-34379F15CFA5} - {BAAC4343-4F17-4B3C-80F0-DA7BB647180C} = {A4EF772C-5311-4633-94C5-2D45BFD25432} - {54A4CB95-033D-4D83-A1E7-D6184F54A61D} = {892940BA-FF36-468A-B8AD-34379F15CFA5} - {BA43067E-A3F4-4939-A465-F3270F273C34} = {892940BA-FF36-468A-B8AD-34379F15CFA5} - {BE33088C-6CDC-47C1-938E-431661AEEBDB} = {892940BA-FF36-468A-B8AD-34379F15CFA5} - {F49D537A-BD95-42BD-80AB-C1744A306769} = {A4EF772C-5311-4633-94C5-2D45BFD25432} - {26E284A5-7AF9-489E-90AB-2C92C4713550} = {892940BA-FF36-468A-B8AD-34379F15CFA5} - {67C9AB6A-D59B-4597-ABAB-1B9578698796} = {A4EF772C-5311-4633-94C5-2D45BFD25432} - {06A11669-7D02-40EA-9C68-F8CD178149A7} = {A4EF772C-5311-4633-94C5-2D45BFD25432} + {5840CEF3-26C0-4323-A549-5D1560B1AFFA} = {FBA324D4-A2B7-4539-B63E-AF254EA7DA50} + {22896ACB-CC99-4C85-B0E1-BCECD4C6237E} = {62BD199E-BDB7-4D33-92E4-3FE97D5EBC91} + {C2CC4428-8084-4F01-8805-C96DD5CCC8A1} = {FBA324D4-A2B7-4539-B63E-AF254EA7DA50} + {30AD0D29-6620-4A66-978E-4633E1771BB4} = {FBA324D4-A2B7-4539-B63E-AF254EA7DA50} + {DACF45B4-E05C-483A-B392-D3C08D98F93E} = {FBA324D4-A2B7-4539-B63E-AF254EA7DA50} + {50CA3826-663C-423A-A872-6BFE5B43A638} = {FBA324D4-A2B7-4539-B63E-AF254EA7DA50} + {7B581D8A-EB93-47D4-9802-F5AA04536D00} = {62BD199E-BDB7-4D33-92E4-3FE97D5EBC91} + {7CC70B33-75CD-46C0-82A5-87E5E60C9535} = {FBA324D4-A2B7-4539-B63E-AF254EA7DA50} + {28C72B39-1803-49D7-9289-C71A620E4EF1} = {62BD199E-BDB7-4D33-92E4-3FE97D5EBC91} + {5BAEC61F-39FF-4197-A73A-A8A8B5BDFE86} = {62BD199E-BDB7-4D33-92E4-3FE97D5EBC91} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {C2243F66-F2ED-4AD3-9E7B-169E12725BB9} + SolutionGuid = {91D97431-DF9A-4A33-860E-27734BFD4496} EndGlobalSection EndGlobal diff --git a/SecurityService/Common/StartupExtensions.cs b/SecurityService/Common/StartupExtensions.cs index 3ea29bd5..96e43d2c 100644 --- a/SecurityService/Common/StartupExtensions.cs +++ b/SecurityService/Common/StartupExtensions.cs @@ -4,7 +4,7 @@ namespace SecurityService using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using Database.DbContexts; - using IdentityServer4.Models; + using Duende.IdentityServer.Models; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.DependencyInjection; diff --git a/SecurityService/Config.cs b/SecurityService/Config.cs new file mode 100644 index 00000000..8753985f --- /dev/null +++ b/SecurityService/Config.cs @@ -0,0 +1,116 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace SecurityService +{ + using System.Security.Claims; + using System.Text.Json; + using Duende.IdentityServer; + using Duende.IdentityServer.Models; + using Duende.IdentityServer.Test; + using IdentityModel; + + public static class Config + { + public static IEnumerable IdentityResources => + new IdentityResource[] + { + new IdentityResources.OpenId(), + new IdentityResources.Profile(), + }; + + public static IEnumerable ApiScopes => + new ApiScope[] + { + new ApiScope("scope1"), + new ApiScope("scope2"), + }; + + public static IEnumerable Clients => + new List + { + // machine to machine client (from quickstart 1) + new Client + { + ClientId = "client", + ClientSecrets = { new Secret("secret".Sha256()) }, + + AllowedGrantTypes = GrantTypes.ClientCredentials, + // scopes that client has access to + AllowedScopes = { "api1" } + }, + // interactive ASP.NET Core MVC client + new Client + { + ClientId = "mvc", + ClientSecrets = { new Secret("secret".Sha256()) }, + + AllowedGrantTypes = GrantTypes.Code, + + // where to redirect to after login + RedirectUris = { "https://localhost:5004/signin-oidc" }, + + // where to redirect to after logout + PostLogoutRedirectUris = { "https://localhost:5004/signout-callback-oidc" }, + + AllowedScopes = new List + { + IdentityServerConstants.StandardScopes.OpenId, + IdentityServerConstants.StandardScopes.Profile + } + } + }; + + public static List Users + { + get + { + var address = new + { + street_address = "One Hacker Way", + locality = "Heidelberg", + postal_code = 69118, + country = "Germany" + }; + + return new List + { + new TestUser + { + SubjectId = "818727", + Username = "alice", + Password = "alice", + Claims = + { + new Claim(JwtClaimTypes.Name, "Alice Smith"), + new Claim(JwtClaimTypes.GivenName, "Alice"), + new Claim(JwtClaimTypes.FamilyName, "Smith"), + new Claim(JwtClaimTypes.Email, "AliceSmith@email.com"), + new Claim(JwtClaimTypes.EmailVerified, "true", ClaimValueTypes.Boolean), + new Claim(JwtClaimTypes.WebSite, "http://alice.com"), + new Claim(JwtClaimTypes.Address, JsonSerializer.Serialize(address), IdentityServerConstants.ClaimValueTypes.Json) + } + }, + new TestUser + { + SubjectId = "88421113", + Username = "bob", + Password = "bob", + Claims = + { + new Claim(JwtClaimTypes.Name, "Bob Smith"), + new Claim(JwtClaimTypes.GivenName, "Bob"), + new Claim(JwtClaimTypes.FamilyName, "Smith"), + new Claim(JwtClaimTypes.Email, "BobSmith@email.com"), + new Claim(JwtClaimTypes.EmailVerified, "true", ClaimValueTypes.Boolean), + new Claim(JwtClaimTypes.WebSite, "http://bob.com"), + new Claim(JwtClaimTypes.Address, JsonSerializer.Serialize(address), IdentityServerConstants.ClaimValueTypes.Json) + } + } + }; + } + } + } +} diff --git a/SecurityService/Controllers/Account/AccountController.cs b/SecurityService/Controllers/Account/AccountController.cs index 8f94c449..16b8b741 100644 --- a/SecurityService/Controllers/Account/AccountController.cs +++ b/SecurityService/Controllers/Account/AccountController.cs @@ -1,151 +1,80 @@ -namespace SecurityService.Controllers.Account +// Copyright (c) Duende Software. All rights reserved. +// See LICENSE in the project root for license information. + + +using IdentityModel; +using Microsoft.AspNetCore.Authentication; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Identity; +using Microsoft.AspNetCore.Mvc; +using System; +using System.Linq; +using System.Threading.Tasks; +using Duende.IdentityServer.Events; +using Duende.IdentityServer.Extensions; +using Duende.IdentityServer.Models; +using Duende.IdentityServer.Services; +using Duende.IdentityServer.Stores; + +namespace IdentityServerHost.Quickstart.UI { - using System; - using System.Diagnostics.CodeAnalysis; - using System.Linq; - using System.Threading; - using System.Threading.Tasks; - using IdentityModel; - using IdentityServer4; - using IdentityServer4.Events; - using IdentityServer4.Extensions; - using IdentityServer4.Models; - using IdentityServer4.Services; - using IdentityServer4.Stores; - using Manager; - using Microsoft.AspNetCore.Authentication; - using Microsoft.AspNetCore.Authorization; - using Microsoft.AspNetCore.Http; - using Microsoft.AspNetCore.Mvc; - using Models; - using Shared.Exceptions; - using ViewModels; - - /// - /// This sample controller implements a typical login/logout/provision workflow for local and external accounts. - /// The login service encapsulates the interactions with the user data store. This data store is in-memory only and cannot be used for production! - /// The interaction service provides a way for the UI to communicate with identityserver for validation and context retrieval - /// - /// - [Route(AccountController.ControllerRoute)] - [ExcludeFromCodeCoverage] [SecurityHeaders] [AllowAnonymous] - [ApiExplorerSettings(IgnoreApi = true)] public class AccountController : Controller { - #region Fields - - /// - /// The client store - /// - private readonly IClientStore _clientStore; - - /// - /// The events - /// - private readonly IEventService _events; - - /// - /// The interaction - /// + private readonly UserManager _userManager; + private readonly SignInManager _signInManager; private readonly IIdentityServerInteractionService _interaction; - - /// - /// The scheme provider - /// + private readonly IClientStore _clientStore; private readonly IAuthenticationSchemeProvider _schemeProvider; + private readonly IIdentityProviderStore _identityProviderStore; + private readonly IEventService _events; - /// - /// The security service manager - /// - private readonly ISecurityServiceManager _securityServiceManager; - - #endregion - - #region Constructors - - /// - /// Initializes a new instance of the class. - /// - /// The interaction. - /// The client store. - /// The scheme provider. - /// The events. - /// The security service manager. - public AccountController(IIdentityServerInteractionService interaction, - IClientStore clientStore, - IAuthenticationSchemeProvider schemeProvider, - IEventService events, - ISecurityServiceManager securityServiceManager) - { - this._interaction = interaction; - this._clientStore = clientStore; - this._schemeProvider = schemeProvider; - this._events = events; - this._securityServiceManager = securityServiceManager; - } - - #endregion - - #region Methods - - /// - /// Accesses the denied. - /// - /// - [HttpGet] - [Route("accessdenied")] - public IActionResult AccessDenied() + public AccountController( + UserManager userManager, + SignInManager signInManager, + IIdentityServerInteractionService interaction, + IClientStore clientStore, + IAuthenticationSchemeProvider schemeProvider, + IIdentityProviderStore identityProviderStore, + IEventService events) { - return this.View(); + _userManager = userManager; + _signInManager = signInManager; + _interaction = interaction; + _clientStore = clientStore; + _schemeProvider = schemeProvider; + _identityProviderStore = identityProviderStore; + _events = events; } /// /// Entry point into the login workflow /// - /// The return URL. - /// [HttpGet] - [Route("login")] - public async Task Login(String returnUrl) + public async Task Login(string returnUrl) { // build a model so we know what to show on the login page - var vm = await this.BuildLoginViewModelAsync(returnUrl); + var vm = await BuildLoginViewModelAsync(returnUrl); if (vm.IsExternalLoginOnly) { // we only have one option for logging in and it's an external provider - return this.RedirectToAction("Challenge", - "External", - new - { - scheme = vm.ExternalLoginScheme, - returnUrl - }); + return RedirectToAction("Challenge", "External", new { scheme = vm.ExternalLoginScheme, returnUrl }); } - return this.View(vm); + return View(vm); } /// /// Handle postback from username/password login /// - /// The model. - /// The button. - /// The cancellation token. - /// - /// No user found with Username [{model.Username}] - /// invalid return URL [HttpPost] [ValidateAntiForgeryToken] - [Route("login")] - public async Task Login(LoginInputModel model, - String button, - CancellationToken cancellationToken) + public async Task Login(LoginInputModel model, string button) { // check if we are in the context of an authorization request - var context = await this._interaction.GetAuthorizationContextAsync(model.ReturnUrl); + var context = await _interaction.GetAuthorizationContextAsync(model.ReturnUrl); // the user clicked the "cancel" button if (button != "login") @@ -155,7 +84,7 @@ public async Task Login(LoginInputModel model, // if the user cancels, send a result back into IdentityServer as if they // denied the consent (even if this client does not require consent). // this will send back an access denied OIDC error response to the client. - await this._interaction.DenyAuthorizationAsync(context, AuthorizationError.AccessDenied); + await _interaction.DenyAuthorizationAsync(context, AuthorizationError.AccessDenied); // we can trust model.ReturnUrl since GetAuthorizationContextAsync returned non-null if (context.IsNativeClient()) @@ -165,50 +94,22 @@ public async Task Login(LoginInputModel model, return this.LoadingPage("Redirect", model.ReturnUrl); } - return this.Redirect(model.ReturnUrl); + return Redirect(model.ReturnUrl); + } + else + { + // since we don't have a valid context, then we just go back to the home page + return Redirect("~/"); } - - // since we don't have a valid context, then we just go back to the home page - return this.Redirect("~/"); } - if (this.ModelState.IsValid) + if (ModelState.IsValid) { - // validate username/password against in-memory store - if (await this._securityServiceManager.ValidateCredentials(model.Username, model.Password, cancellationToken)) + var result = await _signInManager.PasswordSignInAsync(model.Username, model.Password, model.RememberLogin, lockoutOnFailure: true); + if (result.Succeeded) { - var userList = await this._securityServiceManager.GetUsers(model.Username, cancellationToken); - - var user = userList.SingleOrDefault(); - - if (user == null) - { - throw new NotFoundException($"No user found with Username [{model.Username}]"); - } - - await this._events.RaiseAsync(new UserLoginSuccessEvent(user.Username, user.SubjectId, user.Username, clientId:context?.Client.ClientId)); - - // only set explicit expiration here if user chooses "remember me". - // otherwise we rely upon expiration configured in cookie middleware. - AuthenticationProperties props = null; - if (AccountOptions.AllowRememberLogin && model.RememberLogin) - { - props = new AuthenticationProperties - { - IsPersistent = true, - ExpiresUtc = DateTimeOffset.UtcNow.Add(AccountOptions.RememberMeLoginDuration) - }; - } - - ; - - // issue authentication cookie with subject ID and username - var isuser = new IdentityServerUser(user.SubjectId) - { - DisplayName = user.Username - }; - - await this.HttpContext.SignInAsync(isuser, props); + var user = await _userManager.FindByNameAsync(model.Username); + await _events.RaiseAsync(new UserLoginSuccessEvent(user.UserName, user.Id, user.UserName, clientId: context?.Client.ClientId)); if (context != null) { @@ -220,75 +121,71 @@ public async Task Login(LoginInputModel model, } // we can trust model.ReturnUrl since GetAuthorizationContextAsync returned non-null - return this.Redirect(model.ReturnUrl); + return Redirect(model.ReturnUrl); } // request for a local page - if (this.Url.IsLocalUrl(model.ReturnUrl)) + if (Url.IsLocalUrl(model.ReturnUrl)) { - return this.Redirect(model.ReturnUrl); + return Redirect(model.ReturnUrl); } - - if (string.IsNullOrEmpty(model.ReturnUrl)) + else if (string.IsNullOrEmpty(model.ReturnUrl)) { - return this.Redirect("~/"); + return Redirect("~/"); + } + else + { + // user might have clicked on a malicious link - should be logged + throw new Exception("invalid return URL"); } - - // user might have clicked on a malicious link - should be logged - throw new Exception("invalid return URL"); } - await this._events.RaiseAsync(new UserLoginFailureEvent(model.Username, "invalid credentials", clientId:context?.Client.ClientId)); - this.ModelState.AddModelError(string.Empty, AccountOptions.InvalidCredentialsErrorMessage); + await _events.RaiseAsync(new UserLoginFailureEvent(model.Username, "invalid credentials", clientId:context?.Client.ClientId)); + ModelState.AddModelError(string.Empty, AccountOptions.InvalidCredentialsErrorMessage); } // something went wrong, show form with error - var vm = await this.BuildLoginViewModelAsync(model); - return this.View(vm); + var vm = await BuildLoginViewModelAsync(model); + return View(vm); } + /// /// Show logout page /// - /// The logout identifier. - /// [HttpGet] - [Route("logout")] - public async Task Logout(String logoutId) + public async Task Logout(string logoutId) { // build a model so the logout page knows what to display - var vm = await this.BuildLogoutViewModelAsync(logoutId); + var vm = await BuildLogoutViewModelAsync(logoutId); if (vm.ShowLogoutPrompt == false) { // if the request for logout was properly authenticated from IdentityServer, then // we don't need to show the prompt and can just log the user out directly. - return await this.Logout(vm); + return await Logout(vm); } - return this.View(vm); + return View(vm); } /// /// Handle logout page postback /// - /// The model. - /// [HttpPost] [ValidateAntiForgeryToken] - [Route("logout")] public async Task Logout(LogoutInputModel model) { // build a model so the logged out page knows what to display - var vm = await this.BuildLoggedOutViewModelAsync(model.LogoutId); + var vm = await BuildLoggedOutViewModelAsync(model.LogoutId); - if (this.User?.Identity.IsAuthenticated == true) + if (User?.Identity.IsAuthenticated == true) { // delete local authentication cookie - await this.HttpContext.SignOutAsync(); + await _signInManager.SignOutAsync(); // raise the logout event - await this._events.RaiseAsync(new UserLogoutSuccessEvent(this.User.GetSubjectId(), this.User.GetDisplayName())); + await _events.RaiseAsync(new UserLogoutSuccessEvent(User.GetSubjectId(), User.GetDisplayName())); } // check if we need to trigger sign-out at an upstream identity provider @@ -297,115 +194,71 @@ public async Task Logout(LogoutInputModel model) // build a return URL so the upstream provider will redirect back // to us after the user has logged out. this allows us to then // complete our single sign-out processing. - String url = this.Url.Action("Logout", - new - { - logoutId = vm.LogoutId - }); + string url = Url.Action("Logout", new { logoutId = vm.LogoutId }); // this triggers a redirect to the external provider for sign-out - return this.SignOut(new AuthenticationProperties - { - RedirectUri = url - }, - vm.ExternalAuthenticationScheme); + return SignOut(new AuthenticationProperties { RedirectUri = url }, vm.ExternalAuthenticationScheme); } - return this.View("LoggedOut", vm); + return View("LoggedOut", vm); } - /// - /// Builds the logged out view model asynchronous. - /// - /// The logout identifier. - /// - private async Task BuildLoggedOutViewModelAsync(String logoutId) + [HttpGet] + public IActionResult AccessDenied() { - // get context information (client name, post logout redirect URI and iframe for federated signout) - var logout = await this._interaction.GetLogoutContextAsync(logoutId); - - var vm = new LoggedOutViewModel - { - AutomaticRedirectAfterSignOut = AccountOptions.AutomaticRedirectAfterSignOut, - PostLogoutRedirectUri = logout?.PostLogoutRedirectUri, - ClientName = string.IsNullOrEmpty(logout?.ClientName) ? logout?.ClientId : logout?.ClientName, - SignOutIframeUrl = logout?.SignOutIFrameUrl, - LogoutId = logoutId - }; - - if (this.User?.Identity.IsAuthenticated == true) - { - var idp = this.User.FindFirst(JwtClaimTypes.IdentityProvider)?.Value; - if (idp != null && idp != IdentityServerConstants.LocalIdentityProvider) - { - var providerSupportsSignout = await this.HttpContext.GetSchemeSupportsSignOutAsync(idp); - if (providerSupportsSignout) - { - if (vm.LogoutId == null) - { - // if there's no current logout context, we need to create one - // this captures necessary info from the current logged in user - // before we signout and redirect away to the external IdP for signout - vm.LogoutId = await this._interaction.CreateLogoutContextAsync(); - } - - vm.ExternalAuthenticationScheme = idp; - } - } - } - - return vm; + return View(); } + /*****************************************/ /* helper APIs for the AccountController */ /*****************************************/ - /// - /// Builds the login view model asynchronous. - /// - /// The return URL. - /// - private async Task BuildLoginViewModelAsync(String returnUrl) + private async Task BuildLoginViewModelAsync(string returnUrl) { - var context = await this._interaction.GetAuthorizationContextAsync(returnUrl); - if (context?.IdP != null && await this._schemeProvider.GetSchemeAsync(context.IdP) != null) + var context = await _interaction.GetAuthorizationContextAsync(returnUrl); + if (context?.IdP != null && await _schemeProvider.GetSchemeAsync(context.IdP) != null) { - var local = context.IdP == IdentityServerConstants.LocalIdentityProvider; + var local = context.IdP == Duende.IdentityServer.IdentityServerConstants.LocalIdentityProvider; // this is meant to short circuit the UI and only trigger the one external IdP var vm = new LoginViewModel - { - EnableLocalLogin = local, - ReturnUrl = returnUrl, - Username = context?.LoginHint, - }; + { + EnableLocalLogin = local, + ReturnUrl = returnUrl, + Username = context?.LoginHint, + }; if (!local) { - vm.ExternalProviders = new[] - { - new ExternalProvider - { - AuthenticationScheme = context.IdP - } - }; + vm.ExternalProviders = new[] { new ExternalProvider { AuthenticationScheme = context.IdP } }; } return vm; } - var schemes = await this._schemeProvider.GetAllSchemesAsync(); + var schemes = await _schemeProvider.GetAllSchemesAsync(); + + var providers = schemes + .Where(x => x.DisplayName != null) + .Select(x => new ExternalProvider + { + DisplayName = x.DisplayName ?? x.Name, + AuthenticationScheme = x.Name + }).ToList(); - var providers = schemes.Where(x => x.DisplayName != null).Select(x => new ExternalProvider - { - DisplayName = x.DisplayName ?? x.Name, - AuthenticationScheme = x.Name - }).ToList(); + var dyanmicSchemes = (await _identityProviderStore.GetAllSchemeNamesAsync()) + .Where(x => x.Enabled) + .Select(x => new ExternalProvider + { + AuthenticationScheme = x.Scheme, + DisplayName = x.DisplayName + }); + providers.AddRange(dyanmicSchemes); var allowLocal = true; if (context?.Client.ClientId != null) { - var client = await this._clientStore.FindEnabledClientByIdAsync(context.Client.ClientId); + var client = await _clientStore.FindEnabledClientByIdAsync(context.Client.ClientId); if (client != null) { allowLocal = client.EnableLocalLogin; @@ -418,49 +271,35 @@ private async Task BuildLoginViewModelAsync(String returnUrl) } return new LoginViewModel - { - AllowRememberLogin = AccountOptions.AllowRememberLogin, - EnableLocalLogin = allowLocal && AccountOptions.AllowLocalLogin, - ReturnUrl = returnUrl, - Username = context?.LoginHint, - ExternalProviders = providers.ToArray() - }; + { + AllowRememberLogin = AccountOptions.AllowRememberLogin, + EnableLocalLogin = allowLocal && AccountOptions.AllowLocalLogin, + ReturnUrl = returnUrl, + Username = context?.LoginHint, + ExternalProviders = providers.ToArray() + }; } - /// - /// Builds the login view model asynchronous. - /// - /// The model. - /// private async Task BuildLoginViewModelAsync(LoginInputModel model) { - var vm = await this.BuildLoginViewModelAsync(model.ReturnUrl); + var vm = await BuildLoginViewModelAsync(model.ReturnUrl); vm.Username = model.Username; vm.RememberLogin = model.RememberLogin; return vm; } - /// - /// Builds the logout view model asynchronous. - /// - /// The logout identifier. - /// - private async Task BuildLogoutViewModelAsync(String logoutId) + private async Task BuildLogoutViewModelAsync(string logoutId) { - var vm = new LogoutViewModel - { - LogoutId = logoutId, - ShowLogoutPrompt = AccountOptions.ShowLogoutPrompt - }; + var vm = new LogoutViewModel { LogoutId = logoutId, ShowLogoutPrompt = AccountOptions.ShowLogoutPrompt }; - if (this.User?.Identity.IsAuthenticated != true) + if (User?.Identity.IsAuthenticated != true) { // if the user is not authenticated, then just show logged out page vm.ShowLogoutPrompt = false; return vm; } - var context = await this._interaction.GetLogoutContextAsync(logoutId); + var context = await _interaction.GetLogoutContextAsync(logoutId); if (context?.ShowSignoutPrompt == false) { // it's safe to automatically sign-out @@ -473,20 +312,42 @@ private async Task BuildLogoutViewModelAsync(String logoutId) return vm; } - #endregion - - #region Others + private async Task BuildLoggedOutViewModelAsync(string logoutId) + { + // get context information (client name, post logout redirect URI and iframe for federated signout) + var logout = await _interaction.GetLogoutContextAsync(logoutId); - /// - /// The controller name - /// - public const String ControllerName = "account"; + var vm = new LoggedOutViewModel + { + AutomaticRedirectAfterSignOut = AccountOptions.AutomaticRedirectAfterSignOut, + PostLogoutRedirectUri = logout?.PostLogoutRedirectUri, + ClientName = string.IsNullOrEmpty(logout?.ClientName) ? logout?.ClientId : logout?.ClientName, + SignOutIframeUrl = logout?.SignOutIFrameUrl, + LogoutId = logoutId + }; + + if (User?.Identity.IsAuthenticated == true) + { + var idp = User.FindFirst(JwtClaimTypes.IdentityProvider)?.Value; + if (idp != null && idp != Duende.IdentityServer.IdentityServerConstants.LocalIdentityProvider) + { + var providerSupportsSignout = await HttpContext.GetSchemeSupportsSignOutAsync(idp); + if (providerSupportsSignout) + { + if (vm.LogoutId == null) + { + // if there's no current logout context, we need to create one + // this captures necessary info from the current logged in user + // before we signout and redirect away to the external IdP for signout + vm.LogoutId = await _interaction.CreateLogoutContextAsync(); + } - /// - /// The controller route - /// - private const String ControllerRoute = AccountController.ControllerName; + vm.ExternalAuthenticationScheme = idp; + } + } + } - #endregion + return vm; + } } } \ No newline at end of file diff --git a/SecurityService/Controllers/Account/ExternalController.cs b/SecurityService/Controllers/Account/ExternalController.cs index c921ea68..8af119b8 100644 --- a/SecurityService/Controllers/Account/ExternalController.cs +++ b/SecurityService/Controllers/Account/ExternalController.cs @@ -1,126 +1,110 @@ -namespace SecurityService.Controllers.Account +// Copyright (c) Duende Software. All rights reserved. +// See LICENSE in the project root for license information. + + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Security.Claims; +using System.Threading.Tasks; +using Duende.IdentityServer; +using Duende.IdentityServer.Events; +using Duende.IdentityServer.Services; +using Duende.IdentityServer.Stores; +using IdentityModel; +using Microsoft.AspNetCore.Authentication; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Identity; +using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.Logging; + +namespace IdentityServerHost.Quickstart.UI { - using System; - using System.Collections.Generic; - using System.Diagnostics.CodeAnalysis; - using System.Linq; - using System.Security.Claims; - using System.Threading.Tasks; - using IdentityModel; - using IdentityServer4; - using IdentityServer4.Events; - using IdentityServer4.Services; - using IdentityServer4.Stores; - using IdentityServer4.Test; - using Manager; - using Microsoft.AspNetCore.Authentication; - using Microsoft.AspNetCore.Authorization; - using Microsoft.AspNetCore.Http; - using Microsoft.AspNetCore.Mvc; - using Microsoft.Extensions.Logging; - - /// - /// - /// - /// - [Route(ExternalController.ControllerRoute)] - [ExcludeFromCodeCoverage] [SecurityHeaders] [AllowAnonymous] - [ApiExplorerSettings(IgnoreApi = true)] public class ExternalController : Controller { - #region Fields - - /// - /// The client store - /// + private readonly UserManager _userManager; + private readonly SignInManager _signInManager; + private readonly IIdentityServerInteractionService _interaction; private readonly IClientStore _clientStore; - - /// - /// The events - /// private readonly IEventService _events; - - /// - /// The interaction - /// - private readonly IIdentityServerInteractionService _interaction; - - /// - /// The logger - /// private readonly ILogger _logger; - /// - /// The security service manager - /// - private readonly ISecurityServiceManager _securityServiceManager; - - /// - /// The users - /// - private readonly TestUserStore _users; - - #endregion - - #region Constructors + public ExternalController( + UserManager userManager, + SignInManager signInManager, + IIdentityServerInteractionService interaction, + IClientStore clientStore, + IEventService events, + ILogger logger) + { + _userManager = userManager; + _signInManager = signInManager; + _interaction = interaction; + _clientStore = clientStore; + _events = events; + _logger = logger; + } /// - /// Initializes a new instance of the class. + /// initiate roundtrip to external authentication provider /// - /// The interaction. - /// The client store. - /// The events. - /// The logger. - /// The security service manager. - public ExternalController(IIdentityServerInteractionService interaction, - IClientStore clientStore, - IEventService events, - ILogger logger, - ISecurityServiceManager securityServiceManager) + [HttpGet] + public IActionResult Challenge(string scheme, string returnUrl) { - this._interaction = interaction; - this._clientStore = clientStore; - this._logger = logger; - this._securityServiceManager = securityServiceManager; - this._events = events; - } + if (string.IsNullOrEmpty(returnUrl)) returnUrl = "~/"; - #endregion + // validate returnUrl - either it is a valid OIDC URL or back to a local page + if (Url.IsLocalUrl(returnUrl) == false && _interaction.IsValidReturnUrl(returnUrl) == false) + { + // user might have clicked on a malicious link - should be logged + throw new Exception("invalid return URL"); + } + + // start challenge and roundtrip the return URL and scheme + var props = new AuthenticationProperties + { + RedirectUri = Url.Action(nameof(Callback)), + Items = + { + { "returnUrl", returnUrl }, + { "scheme", scheme }, + } + }; - #region Methods + return Challenge(props, scheme); + + } /// /// Post processing of external authentication /// - /// - /// External authentication error [HttpGet] - [Route("callback")] public async Task Callback() { // read external identity from the temporary cookie - var result = await this.HttpContext.AuthenticateAsync(IdentityServerConstants.ExternalCookieAuthenticationScheme); + var result = await HttpContext.AuthenticateAsync(IdentityServerConstants.ExternalCookieAuthenticationScheme); if (result?.Succeeded != true) { throw new Exception("External authentication error"); } - if (this._logger.IsEnabled(LogLevel.Debug)) + if (_logger.IsEnabled(LogLevel.Debug)) { var externalClaims = result.Principal.Claims.Select(c => $"{c.Type}: {c.Value}"); - this._logger.LogDebug("External claims: {@claims}", externalClaims); + _logger.LogDebug("External claims: {@claims}", externalClaims); } // lookup our user and external provider info - var (user, provider, providerUserId, claims) = this.FindUserFromExternalProvider(result); + var (user, provider, providerUserId, claims) = await FindUserFromExternalProviderAsync(result); if (user == null) { // this might be where you might initiate a custom workflow for user registration // in this sample we don't show how that would be done, as our sample implementation // simply auto-provisions new external user - user = this.AutoProvisionUser(provider, providerUserId, claims); + user = await AutoProvisionUserAsync(provider, providerUserId, claims); } // this allows us to collect any additional claims or properties @@ -128,27 +112,33 @@ public async Task Callback() // this is typically used to store data needed for signout from those protocols. var additionalLocalClaims = new List(); var localSignInProps = new AuthenticationProperties(); - this.ProcessLoginCallback(result, additionalLocalClaims, localSignInProps); - + ProcessLoginCallback(result, additionalLocalClaims, localSignInProps); + // issue authentication cookie for user - var isuser = new IdentityServerUser(user.SubjectId) - { - DisplayName = user.Username, - IdentityProvider = provider, - AdditionalClaims = additionalLocalClaims - }; + // we must issue the cookie maually, and can't use the SignInManager because + // it doesn't expose an API to issue additional claims from the login workflow + var principal = await _signInManager.CreateUserPrincipalAsync(user); + additionalLocalClaims.AddRange(principal.Claims); + var name = principal.FindFirst(JwtClaimTypes.Name)?.Value ?? user.Id; + + var isuser = new IdentityServerUser(user.Id) + { + DisplayName = name, + IdentityProvider = provider, + AdditionalClaims = additionalLocalClaims + }; - await this.HttpContext.SignInAsync(isuser, localSignInProps); + await HttpContext.SignInAsync(isuser, localSignInProps); // delete temporary cookie used during external authentication - await this.HttpContext.SignOutAsync(IdentityServerConstants.ExternalCookieAuthenticationScheme); + await HttpContext.SignOutAsync(IdentityServerConstants.ExternalCookieAuthenticationScheme); // retrieve return URL var returnUrl = result.Properties.Items["returnUrl"] ?? "~/"; // check if external login is in the context of an OIDC request - var context = await this._interaction.GetAuthorizationContextAsync(returnUrl); - await this._events.RaiseAsync(new UserLoginSuccessEvent(provider, providerUserId, user.SubjectId, user.Username, true, context?.Client.ClientId)); + var context = await _interaction.GetAuthorizationContextAsync(returnUrl); + await _events.RaiseAsync(new UserLoginSuccessEvent(provider, providerUserId, user.Id, name, true, context?.Client.ClientId)); if (context != null) { @@ -160,73 +150,20 @@ public async Task Callback() } } - return this.Redirect(returnUrl); + return Redirect(returnUrl); } - /// - /// initiate roundtrip to external authentication provider - /// - /// The scheme. - /// The return URL. - /// - /// invalid return URL - [HttpGet] - [Route("challenge")] - public IActionResult Challenge(String scheme, - String returnUrl) - { - if (string.IsNullOrEmpty(returnUrl)) returnUrl = "~/"; - - // validate returnUrl - either it is a valid OIDC URL or back to a local page - if (this.Url.IsLocalUrl(returnUrl) == false && this._interaction.IsValidReturnUrl(returnUrl) == false) - { - // user might have clicked on a malicious link - should be logged - throw new Exception("invalid return URL"); - } - - // start challenge and roundtrip the return URL and scheme - var props = new AuthenticationProperties - { - RedirectUri = this.Url.Action(nameof(this.Callback)), - Items = - { - {"returnUrl", returnUrl}, - {"scheme", scheme}, - } - }; - - return this.Challenge(props, scheme); - } - - /// - /// Automatics the provision user. - /// - /// The provider. - /// The provider user identifier. - /// The claims. - /// - private TestUser AutoProvisionUser(String provider, - String providerUserId, - IEnumerable claims) - { - var user = this._users.AutoProvisionUser(provider, providerUserId, claims.ToList()); - return user; - } - - /// - /// Finds the user from external provider. - /// - /// The result. - /// - /// Unknown userid - private (TestUser user, String provider, String providerUserId, IEnumerable claims) FindUserFromExternalProvider(AuthenticateResult result) + private async Task<(IdentityUser user, string provider, string providerUserId, IEnumerable claims)> + FindUserFromExternalProviderAsync(AuthenticateResult result) { var externalUser = result.Principal; // try to determine the unique id of the external user (issued by the provider) // the most common claim type for that are the sub claim and the NameIdentifier // depending on the external provider, some other claim type might be used - var userIdClaim = externalUser.FindFirst(JwtClaimTypes.Subject) ?? externalUser.FindFirst(ClaimTypes.NameIdentifier) ?? throw new Exception("Unknown userid"); + var userIdClaim = externalUser.FindFirst(JwtClaimTypes.Subject) ?? + externalUser.FindFirst(ClaimTypes.NameIdentifier) ?? + throw new Exception("Unknown userid"); // remove the user id claim so we don't include it as an extra claim if/when we provision the user var claims = externalUser.Claims.ToList(); @@ -236,22 +173,73 @@ private TestUser AutoProvisionUser(String provider, var providerUserId = userIdClaim.Value; // find external user - var user = this._users.FindByExternalProvider(provider, providerUserId); + var user = await _userManager.FindByLoginAsync(provider, providerUserId); return (user, provider, providerUserId, claims); } + private async Task AutoProvisionUserAsync(string provider, string providerUserId, IEnumerable claims) + { + // create a list of claims that we want to transfer into our store + var filtered = new List(); + + // user's display name + var name = claims.FirstOrDefault(x => x.Type == JwtClaimTypes.Name)?.Value ?? + claims.FirstOrDefault(x => x.Type == ClaimTypes.Name)?.Value; + if (name != null) + { + filtered.Add(new Claim(JwtClaimTypes.Name, name)); + } + else + { + var first = claims.FirstOrDefault(x => x.Type == JwtClaimTypes.GivenName)?.Value ?? + claims.FirstOrDefault(x => x.Type == ClaimTypes.GivenName)?.Value; + var last = claims.FirstOrDefault(x => x.Type == JwtClaimTypes.FamilyName)?.Value ?? + claims.FirstOrDefault(x => x.Type == ClaimTypes.Surname)?.Value; + if (first != null && last != null) + { + filtered.Add(new Claim(JwtClaimTypes.Name, first + " " + last)); + } + else if (first != null) + { + filtered.Add(new Claim(JwtClaimTypes.Name, first)); + } + else if (last != null) + { + filtered.Add(new Claim(JwtClaimTypes.Name, last)); + } + } + + // email + var email = claims.FirstOrDefault(x => x.Type == JwtClaimTypes.Email)?.Value ?? + claims.FirstOrDefault(x => x.Type == ClaimTypes.Email)?.Value; + if (email != null) + { + filtered.Add(new Claim(JwtClaimTypes.Email, email)); + } + + var user = new IdentityUser + { + UserName = Guid.NewGuid().ToString(), + }; + var identityResult = await _userManager.CreateAsync(user); + if (!identityResult.Succeeded) throw new Exception(identityResult.Errors.First().Description); + + if (filtered.Any()) + { + identityResult = await _userManager.AddClaimsAsync(user, filtered); + if (!identityResult.Succeeded) throw new Exception(identityResult.Errors.First().Description); + } + + identityResult = await _userManager.AddLoginAsync(user, new UserLoginInfo(provider, providerUserId, provider)); + if (!identityResult.Succeeded) throw new Exception(identityResult.Errors.First().Description); + + return user; + } + // if the external login is OIDC-based, there are certain things we need to preserve to make logout work // this will be different for WS-Fed, SAML2p or other protocols - /// - /// Processes the login callback. - /// - /// The external result. - /// The local claims. - /// The local sign in props. - private void ProcessLoginCallback(AuthenticateResult externalResult, - List localClaims, - AuthenticationProperties localSignInProps) + private void ProcessLoginCallback(AuthenticateResult externalResult, List localClaims, AuthenticationProperties localSignInProps) { // if the external system sent a session id claim, copy it over // so we can use it for single sign-out @@ -265,31 +253,8 @@ private void ProcessLoginCallback(AuthenticateResult externalResult, var idToken = externalResult.Properties.GetTokenValue("id_token"); if (idToken != null) { - localSignInProps.StoreTokens(new[] - { - new AuthenticationToken - { - Name = "id_token", - Value = idToken - } - }); + localSignInProps.StoreTokens(new[] { new AuthenticationToken { Name = "id_token", Value = idToken } }); } } - - #endregion - - #region Others - - /// - /// The controller name - /// - public const String ControllerName = "external"; - - /// - /// The controller route - /// - private const String ControllerRoute = ExternalController.ControllerName; - - #endregion } } \ No newline at end of file diff --git a/SecurityService/Controllers/ApiResourceController.cs b/SecurityService/Controllers/ApiResourceController.cs index e8ffe815..6daee7d5 100644 --- a/SecurityService/Controllers/ApiResourceController.cs +++ b/SecurityService/Controllers/ApiResourceController.cs @@ -11,10 +11,10 @@ namespace SecurityService.Controllers using DataTransferObjects; using DataTransferObjects.Requests; using DataTransferObjects.Responses; + using Duende.IdentityServer.Models; using Factories; - using IdentityServer4.Models; - using Manager; using Microsoft.AspNetCore.Mvc; + using SecurityService.BusinessLogic; using Swashbuckle.AspNetCore.Annotations; using Swashbuckle.AspNetCore.Filters; diff --git a/SecurityService/Controllers/ApiScopeController.cs b/SecurityService/Controllers/ApiScopeController.cs index 842f30c1..81072175 100644 --- a/SecurityService/Controllers/ApiScopeController.cs +++ b/SecurityService/Controllers/ApiScopeController.cs @@ -5,12 +5,12 @@ using System.Diagnostics.CodeAnalysis; using System.Threading; using System.Threading.Tasks; + using BusinessLogic; using Common.Examples; using DataTransferObjects.Requests; using DataTransferObjects.Responses; + using Duende.IdentityServer.Models; using Factories; - using IdentityServer4.Models; - using Manager; using Microsoft.AspNetCore.Mvc; using Swashbuckle.AspNetCore.Annotations; using Swashbuckle.AspNetCore.Filters; diff --git a/SecurityService/Controllers/ClientController.cs b/SecurityService/Controllers/ClientController.cs index c104ef41..268cd4a5 100644 --- a/SecurityService/Controllers/ClientController.cs +++ b/SecurityService/Controllers/ClientController.cs @@ -5,13 +5,13 @@ using System.Diagnostics.CodeAnalysis; using System.Threading; using System.Threading.Tasks; + using BusinessLogic; using Common.Examples; using DataTransferObjects; using DataTransferObjects.Requests; using DataTransferObjects.Responses; + using Duende.IdentityServer.Models; using Factories; - using IdentityServer4.Models; - using Manager; using Microsoft.AspNetCore.Mvc; using Swashbuckle.AspNetCore.Annotations; using Swashbuckle.AspNetCore.Filters; diff --git a/SecurityService/Controllers/Consent/ConsentController.cs b/SecurityService/Controllers/Consent/ConsentController.cs index 51a7cd46..649a4f58 100644 --- a/SecurityService/Controllers/Consent/ConsentController.cs +++ b/SecurityService/Controllers/Consent/ConsentController.cs @@ -1,134 +1,73 @@ -namespace SecurityService.Controllers.Consent +// Copyright (c) Duende Software. All rights reserved. +// See LICENSE in the project root for license information. + + +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.Logging; +using System.Linq; +using System.Threading.Tasks; +using System.Collections.Generic; +using System; +using Duende.IdentityServer.Events; +using Duende.IdentityServer.Extensions; +using Duende.IdentityServer.Models; +using Duende.IdentityServer.Services; +using Duende.IdentityServer.Validation; +using IdentityModel; + +namespace IdentityServerHost.Quickstart.UI { - using System; - using System.Collections.Generic; - using System.Diagnostics.CodeAnalysis; - using System.Linq; - using System.Threading.Tasks; - using IdentityServer4; - using IdentityServer4.Events; - using IdentityServer4.Extensions; - using IdentityServer4.Models; - using IdentityServer4.Services; - using IdentityServer4.Validation; - using Microsoft.AspNetCore.Authorization; - using Microsoft.AspNetCore.Mvc; - using Microsoft.Extensions.Logging; - using Models; - using ViewModels; - /// /// This controller processes the consent UI /// - /// - [Route(ConsentController.ControllerRoute)] - [ExcludeFromCodeCoverage] [SecurityHeaders] [Authorize] - [ApiExplorerSettings(IgnoreApi = true)] public class ConsentController : Controller { - #region Fields - - /// - /// The events - /// - private readonly IEventService _events; - - /// - /// The interaction - /// private readonly IIdentityServerInteractionService _interaction; - - /// - /// The logger - /// + private readonly IEventService _events; private readonly ILogger _logger; - #endregion - - #region Constructors - - /// - /// Initializes a new instance of the class. - /// - /// The interaction. - /// The events. - /// The logger. - public ConsentController(IIdentityServerInteractionService interaction, - IEventService events, - ILogger logger) + public ConsentController( + IIdentityServerInteractionService interaction, + IEventService events, + ILogger logger) { - this._interaction = interaction; - this._events = events; - this._logger = logger; - } - - #endregion - - #region Methods - - /// - /// Creates the scope view model. - /// - /// The parsed scope value. - /// The API scope. - /// if set to true [check]. - /// - public ScopeViewModel CreateScopeViewModel(ParsedScopeValue parsedScopeValue, - ApiScope apiScope, - Boolean check) - { - var displayName = apiScope.DisplayName ?? apiScope.Name; - if (!string.IsNullOrWhiteSpace(parsedScopeValue.ParsedParameter)) - { - displayName += ":" + parsedScopeValue.ParsedParameter; - } - - return new ScopeViewModel - { - Value = parsedScopeValue.RawValue, - DisplayName = displayName, - Description = apiScope.Description, - Emphasize = apiScope.Emphasize, - Required = apiScope.Required, - Checked = check || apiScope.Required - }; + _interaction = interaction; + _events = events; + _logger = logger; } /// /// Shows the consent screen /// - /// The return URL. + /// /// [HttpGet] - [Route("index")] - public async Task Index(String returnUrl) + public async Task Index(string returnUrl) { - var vm = await this.BuildViewModelAsync(returnUrl); + var vm = await BuildViewModelAsync(returnUrl); if (vm != null) { - return this.View("Index", vm); + return View("Index", vm); } - return this.View("Error"); + return View("Error"); } /// /// Handles the consent screen postback /// - /// The model. - /// [HttpPost] [ValidateAntiForgeryToken] - [Route("index")] public async Task Index(ConsentInputModel model) { - var result = await this.ProcessConsent(model); + var result = await ProcessConsent(model); if (result.IsRedirect) { - var context = await this._interaction.GetAuthorizationContextAsync(model.ReturnUrl); + var context = await _interaction.GetAuthorizationContextAsync(model.ReturnUrl); if (context?.IsNativeClient() == true) { // The client is native, so this change in how to @@ -136,142 +75,31 @@ public async Task Index(ConsentInputModel model) return this.LoadingPage("Redirect", result.RedirectUri); } - return this.Redirect(result.RedirectUri); + return Redirect(result.RedirectUri); } if (result.HasValidationError) { - this.ModelState.AddModelError(string.Empty, result.ValidationError); + ModelState.AddModelError(string.Empty, result.ValidationError); } if (result.ShowView) { - return this.View("Index", result.ViewModel); + return View("Index", result.ViewModel); } - return this.View("Error"); - } - - /// - /// Builds the view model asynchronous. - /// - /// The return URL. - /// The model. - /// - private async Task BuildViewModelAsync(String returnUrl, - ConsentInputModel model = null) - { - var request = await this._interaction.GetAuthorizationContextAsync(returnUrl); - if (request != null) - { - return this.CreateConsentViewModel(model, returnUrl, request); - } - - this._logger.LogError("No consent request matching request: {0}", returnUrl); - - return null; - } - - /// - /// Creates the consent view model. - /// - /// The model. - /// The return URL. - /// The request. - /// - private ConsentViewModel CreateConsentViewModel(ConsentInputModel model, - String returnUrl, - AuthorizationRequest request) - { - var vm = new ConsentViewModel - { - RememberConsent = model?.RememberConsent ?? true, - ScopesConsented = model?.ScopesConsented ?? Enumerable.Empty(), - Description = model?.Description, - - ReturnUrl = returnUrl, - - ClientName = request.Client.ClientName ?? request.Client.ClientId, - ClientUrl = request.Client.ClientUri, - ClientLogoUrl = request.Client.LogoUri, - AllowRememberConsent = request.Client.AllowRememberConsent - }; - - vm.IdentityScopes = request.ValidatedResources.Resources.IdentityResources - .Select(x => this.CreateScopeViewModel(x, vm.ScopesConsented.Contains(x.Name) || model == null)).ToArray(); - - var apiScopes = new List(); - foreach (var parsedScope in request.ValidatedResources.ParsedScopes) - { - var apiScope = request.ValidatedResources.Resources.FindApiScope(parsedScope.ParsedName); - if (apiScope != null) - { - var scopeVm = this.CreateScopeViewModel(parsedScope, apiScope, vm.ScopesConsented.Contains(parsedScope.RawValue) || model == null); - apiScopes.Add(scopeVm); - } - } - - if (ConsentOptions.EnableOfflineAccess && request.ValidatedResources.Resources.OfflineAccess) - { - apiScopes.Add(this.GetOfflineAccessScope(vm.ScopesConsented.Contains(IdentityServerConstants.StandardScopes.OfflineAccess) || model == null)); - } - - vm.ApiScopes = apiScopes; - - return vm; - } - - /// - /// Creates the scope view model. - /// - /// The identity. - /// if set to true [check]. - /// - private ScopeViewModel CreateScopeViewModel(IdentityResource identity, - Boolean check) - { - return new ScopeViewModel - { - Value = identity.Name, - DisplayName = identity.DisplayName ?? identity.Name, - Description = identity.Description, - Emphasize = identity.Emphasize, - Required = identity.Required, - Checked = check || identity.Required - }; - } - - /// - /// Gets the offline access scope. - /// - /// if set to true [check]. - /// - private ScopeViewModel GetOfflineAccessScope(Boolean check) - { - return new ScopeViewModel - { - Value = IdentityServerConstants.StandardScopes.OfflineAccess, - DisplayName = ConsentOptions.OfflineAccessDisplayName, - Description = ConsentOptions.OfflineAccessDescription, - Emphasize = true, - Checked = check - }; + return View("Error"); } /*****************************************/ /* helper APIs for the ConsentController */ /*****************************************/ - /// - /// Processes the consent. - /// - /// The model. - /// private async Task ProcessConsent(ConsentInputModel model) { var result = new ProcessConsentResult(); // validate return url is still valid - var request = await this._interaction.GetAuthorizationContextAsync(model.ReturnUrl); + var request = await _interaction.GetAuthorizationContextAsync(model.ReturnUrl); if (request == null) return result; ConsentResponse grantedConsent = null; @@ -279,13 +107,10 @@ private async Task ProcessConsent(ConsentInputModel model) // user clicked 'no' - send back the standard 'access_denied' response if (model?.Button == "no") { - grantedConsent = new ConsentResponse - { - Error = AuthorizationError.AccessDenied - }; + grantedConsent = new ConsentResponse { Error = AuthorizationError.AccessDenied }; // emit event - await this._events.RaiseAsync(new ConsentDeniedEvent(this.User.GetSubjectId(), request.Client.ClientId, request.ValidatedResources.RawScopeValues)); + await _events.RaiseAsync(new ConsentDeniedEvent(User.GetSubjectId(), request.Client.ClientId, request.ValidatedResources.RawScopeValues)); } // user clicked 'yes' - validate the data else if (model?.Button == "yes") @@ -296,22 +121,18 @@ private async Task ProcessConsent(ConsentInputModel model) var scopes = model.ScopesConsented; if (ConsentOptions.EnableOfflineAccess == false) { - scopes = scopes.Where(x => x != IdentityServerConstants.StandardScopes.OfflineAccess); + scopes = scopes.Where(x => x != Duende.IdentityServer.IdentityServerConstants.StandardScopes.OfflineAccess); } grantedConsent = new ConsentResponse - { - RememberConsent = model.RememberConsent, - ScopesValuesConsented = scopes.ToArray(), - Description = model.Description - }; + { + RememberConsent = model.RememberConsent, + ScopesValuesConsented = scopes.ToArray(), + Description = model.Description + }; // emit event - await this._events.RaiseAsync(new ConsentGrantedEvent(this.User.GetSubjectId(), - request.Client.ClientId, - request.ValidatedResources.RawScopeValues, - grantedConsent.ScopesValuesConsented, - grantedConsent.RememberConsent)); + await _events.RaiseAsync(new ConsentGrantedEvent(User.GetSubjectId(), request.Client.ClientId, request.ValidatedResources.RawScopeValues, grantedConsent.ScopesValuesConsented, grantedConsent.RememberConsent)); } else { @@ -326,7 +147,7 @@ await this._events.RaiseAsync(new ConsentGrantedEvent(this.User.GetSubjectId(), if (grantedConsent != null) { // communicate outcome of consent back to identityserver - await this._interaction.GrantConsentAsync(request, grantedConsent); + await _interaction.GrantConsentAsync(request, grantedConsent); // indicate that's it ok to redirect back to authorization endpoint result.RedirectUri = model.ReturnUrl; @@ -335,26 +156,121 @@ await this._events.RaiseAsync(new ConsentGrantedEvent(this.User.GetSubjectId(), else { // we need to redisplay the consent UI - result.ViewModel = await this.BuildViewModelAsync(model.ReturnUrl, model); + result.ViewModel = await BuildViewModelAsync(model.ReturnUrl, model); } return result; } - #endregion + private async Task BuildViewModelAsync(string returnUrl, ConsentInputModel model = null) + { + var request = await _interaction.GetAuthorizationContextAsync(returnUrl); + if (request != null) + { + return CreateConsentViewModel(model, returnUrl, request); + } + else + { + _logger.LogError("No consent request matching request: {0}", returnUrl); + } - #region Others + return null; + } - /// - /// The controller name - /// - public const String ControllerName = "consent"; + private ConsentViewModel CreateConsentViewModel( + ConsentInputModel model, string returnUrl, + AuthorizationRequest request) + { + var vm = new ConsentViewModel + { + RememberConsent = model?.RememberConsent ?? true, + ScopesConsented = model?.ScopesConsented ?? Enumerable.Empty(), + Description = model?.Description, - /// - /// The controller route - /// - private const String ControllerRoute = ConsentController.ControllerName; + ReturnUrl = returnUrl, + + ClientName = request.Client.ClientName ?? request.Client.ClientId, + ClientUrl = request.Client.ClientUri, + ClientLogoUrl = request.Client.LogoUri, + AllowRememberConsent = request.Client.AllowRememberConsent + }; + + vm.IdentityScopes = request.ValidatedResources.Resources.IdentityResources + .Select(x => CreateScopeViewModel(x, vm.ScopesConsented.Contains(x.Name) || model == null)) + .ToArray(); + + var resourceIndicators = request.Parameters.GetValues(OidcConstants.AuthorizeRequest.Resource) ?? Enumerable.Empty(); + var apiResources = request.ValidatedResources.Resources.ApiResources.Where(x => resourceIndicators.Contains(x.Name)); - #endregion + var apiScopes = new List(); + foreach (var parsedScope in request.ValidatedResources.ParsedScopes) + { + var apiScope = request.ValidatedResources.Resources.FindApiScope(parsedScope.ParsedName); + if (apiScope != null) + { + var scopeVm = CreateScopeViewModel(parsedScope, apiScope, vm.ScopesConsented.Contains(parsedScope.RawValue) || model == null); + scopeVm.Resources = apiResources.Where(x => x.Scopes.Contains(parsedScope.ParsedName)) + .Select(x=> new ResourceViewModel + { + Name = x.Name, + DisplayName = x.DisplayName ?? x.Name, + }).ToArray(); + apiScopes.Add(scopeVm); + } + } + if (ConsentOptions.EnableOfflineAccess && request.ValidatedResources.Resources.OfflineAccess) + { + apiScopes.Add(GetOfflineAccessScope(vm.ScopesConsented.Contains(Duende.IdentityServer.IdentityServerConstants.StandardScopes.OfflineAccess) || model == null)); + } + vm.ApiScopes = apiScopes; + + return vm; + } + + private ScopeViewModel CreateScopeViewModel(IdentityResource identity, bool check) + { + return new ScopeViewModel + { + Name = identity.Name, + Value = identity.Name, + DisplayName = identity.DisplayName ?? identity.Name, + Description = identity.Description, + Emphasize = identity.Emphasize, + Required = identity.Required, + Checked = check || identity.Required + }; + } + + public ScopeViewModel CreateScopeViewModel(ParsedScopeValue parsedScopeValue, ApiScope apiScope, bool check) + { + var displayName = apiScope.DisplayName ?? apiScope.Name; + if (!String.IsNullOrWhiteSpace(parsedScopeValue.ParsedParameter)) + { + displayName += ":" + parsedScopeValue.ParsedParameter; + } + + return new ScopeViewModel + { + Name = parsedScopeValue.ParsedName, + Value = parsedScopeValue.RawValue, + DisplayName = displayName, + Description = apiScope.Description, + Emphasize = apiScope.Emphasize, + Required = apiScope.Required, + Checked = check || apiScope.Required + }; + } + + private ScopeViewModel GetOfflineAccessScope(bool check) + { + return new ScopeViewModel + { + Value = Duende.IdentityServer.IdentityServerConstants.StandardScopes.OfflineAccess, + DisplayName = ConsentOptions.OfflineAccessDisplayName, + Description = ConsentOptions.OfflineAccessDescription, + Emphasize = true, + Checked = check + }; + } } } \ No newline at end of file diff --git a/SecurityService/Controllers/Device/DeviceController.cs b/SecurityService/Controllers/Device/DeviceController.cs index aecf5ecb..9e69aee6 100644 --- a/SecurityService/Controllers/Device/DeviceController.cs +++ b/SecurityService/Controllers/Device/DeviceController.cs @@ -1,274 +1,86 @@ -namespace SecurityService.Controllers.Device +// Copyright (c) Duende Software. All rights reserved. +// See LICENSE in the project root for license information. + + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Duende.IdentityServer.Configuration; +using Duende.IdentityServer.Events; +using Duende.IdentityServer.Extensions; +using Duende.IdentityServer.Models; +using Duende.IdentityServer.Services; +using Duende.IdentityServer.Validation; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; + +namespace IdentityServerHost.Quickstart.UI { - using System; - using System.Collections.Generic; - using System.Diagnostics.CodeAnalysis; - using System.Linq; - using System.Threading.Tasks; - using IdentityServer4; - using IdentityServer4.Configuration; - using IdentityServer4.Events; - using IdentityServer4.Extensions; - using IdentityServer4.Models; - using IdentityServer4.Services; - using IdentityServer4.Validation; - using Microsoft.AspNetCore.Authorization; - using Microsoft.AspNetCore.Mvc; - using Microsoft.Extensions.Logging; - using Microsoft.Extensions.Options; - using Models; - using ViewModels; - - /// - /// - /// - /// - [Route(DeviceController.ControllerRoute)] - [ExcludeFromCodeCoverage] [Authorize] [SecurityHeaders] - [ApiExplorerSettings(IgnoreApi = true)] public class DeviceController : Controller { - #region Fields - - /// - /// The events - /// - private readonly IEventService _events; - - /// - /// The interaction - /// private readonly IDeviceFlowInteractionService _interaction; - - /// - /// The logger - /// - private readonly ILogger _logger; - - /// - /// The options - /// + private readonly IEventService _events; private readonly IOptions _options; + private readonly ILogger _logger; - #endregion - - #region Constructors - - /// - /// Initializes a new instance of the class. - /// - /// The interaction. - /// The event service. - /// The options. - /// The logger. - public DeviceController(IDeviceFlowInteractionService interaction, - IEventService eventService, - IOptions options, - ILogger logger) - { - this._interaction = interaction; - this._events = eventService; - this._options = options; - this._logger = logger; - } - - #endregion - - #region Methods - - /// - /// Callbacks the specified model. - /// - /// The model. - /// - /// model - [HttpPost] - [ValidateAntiForgeryToken] - [Route("callback")] - public async Task Callback(DeviceAuthorizationInputModel model) - { - if (model == null) throw new ArgumentNullException(nameof(model)); - - var result = await this.ProcessConsent(model); - if (result.HasValidationError) return this.View("Error"); - - return this.View("Success"); - } - - /// - /// Creates the scope view model. - /// - /// The parsed scope value. - /// The API scope. - /// if set to true [check]. - /// - public ScopeViewModel CreateScopeViewModel(ParsedScopeValue parsedScopeValue, - ApiScope apiScope, - Boolean check) + public DeviceController( + IDeviceFlowInteractionService interaction, + IEventService eventService, + IOptions options, + ILogger logger) { - return new ScopeViewModel - { - Value = parsedScopeValue.RawValue, - // todo: use the parsed scope value in the display? - DisplayName = apiScope.DisplayName ?? apiScope.Name, - Description = apiScope.Description, - Emphasize = apiScope.Emphasize, - Required = apiScope.Required, - Checked = check || apiScope.Required - }; + _interaction = interaction; + _events = eventService; + _options = options; + _logger = logger; } - /// - /// Indexes this instance. - /// - /// [HttpGet] - [Route("index")] public async Task Index() { - String userCodeParamName = this._options.Value.UserInteraction.DeviceVerificationUserCodeParameter; - String userCode = this.Request.Query[userCodeParamName]; - if (string.IsNullOrWhiteSpace(userCode)) return this.View("UserCodeCapture"); + string userCodeParamName = _options.Value.UserInteraction.DeviceVerificationUserCodeParameter; + string userCode = Request.Query[userCodeParamName]; + if (string.IsNullOrWhiteSpace(userCode)) return View("UserCodeCapture"); - var vm = await this.BuildViewModelAsync(userCode); - if (vm == null) return this.View("Error"); + var vm = await BuildViewModelAsync(userCode); + if (vm == null) return View("Error"); vm.ConfirmUserCode = true; - return this.View("UserCodeConfirmation", vm); + return View("UserCodeConfirmation", vm); } - /// - /// Users the code capture. - /// - /// The user code. - /// [HttpPost] [ValidateAntiForgeryToken] - [Route("usercodecapture")] - public async Task UserCodeCapture(String userCode) + public async Task UserCodeCapture(string userCode) { - var vm = await this.BuildViewModelAsync(userCode); - if (vm == null) return this.View("Error"); + var vm = await BuildViewModelAsync(userCode); + if (vm == null) return View("Error"); - return this.View("UserCodeConfirmation", vm); + return View("UserCodeConfirmation", vm); } - /// - /// Builds the view model asynchronous. - /// - /// The user code. - /// The model. - /// - private async Task BuildViewModelAsync(String userCode, - DeviceAuthorizationInputModel model = null) - { - var request = await this._interaction.GetAuthorizationContextAsync(userCode); - if (request != null) - { - return this.CreateConsentViewModel(userCode, model, request); - } - - return null; - } - - /// - /// Creates the consent view model. - /// - /// The user code. - /// The model. - /// The request. - /// - private DeviceAuthorizationViewModel CreateConsentViewModel(String userCode, - DeviceAuthorizationInputModel model, - DeviceFlowAuthorizationRequest request) + [HttpPost] + [ValidateAntiForgeryToken] + public async Task Callback(DeviceAuthorizationInputModel model) { - var vm = new DeviceAuthorizationViewModel - { - UserCode = userCode, - Description = model?.Description, - - RememberConsent = model?.RememberConsent ?? true, - ScopesConsented = model?.ScopesConsented ?? Enumerable.Empty(), - - ClientName = request.Client.ClientName ?? request.Client.ClientId, - ClientUrl = request.Client.ClientUri, - ClientLogoUrl = request.Client.LogoUri, - AllowRememberConsent = request.Client.AllowRememberConsent - }; - - vm.IdentityScopes = request.ValidatedResources.Resources.IdentityResources - .Select(x => this.CreateScopeViewModel(x, vm.ScopesConsented.Contains(x.Name) || model == null)).ToArray(); - - var apiScopes = new List(); - foreach (var parsedScope in request.ValidatedResources.ParsedScopes) - { - var apiScope = request.ValidatedResources.Resources.FindApiScope(parsedScope.ParsedName); - if (apiScope != null) - { - var scopeVm = this.CreateScopeViewModel(parsedScope, apiScope, vm.ScopesConsented.Contains(parsedScope.RawValue) || model == null); - apiScopes.Add(scopeVm); - } - } - - if (ConsentOptions.EnableOfflineAccess && request.ValidatedResources.Resources.OfflineAccess) - { - apiScopes.Add(this.GetOfflineAccessScope(vm.ScopesConsented.Contains(IdentityServerConstants.StandardScopes.OfflineAccess) || model == null)); - } - - vm.ApiScopes = apiScopes; + if (model == null) throw new ArgumentNullException(nameof(model)); - return vm; - } + var result = await ProcessConsent(model); + if (result.HasValidationError) return View("Error"); - /// - /// Creates the scope view model. - /// - /// The identity. - /// if set to true [check]. - /// - private ScopeViewModel CreateScopeViewModel(IdentityResource identity, - Boolean check) - { - return new ScopeViewModel - { - Value = identity.Name, - DisplayName = identity.DisplayName ?? identity.Name, - Description = identity.Description, - Emphasize = identity.Emphasize, - Required = identity.Required, - Checked = check || identity.Required - }; + return View("Success"); } - /// - /// Gets the offline access scope. - /// - /// if set to true [check]. - /// - private ScopeViewModel GetOfflineAccessScope(Boolean check) - { - return new ScopeViewModel - { - Value = IdentityServerConstants.StandardScopes.OfflineAccess, - DisplayName = ConsentOptions.OfflineAccessDisplayName, - Description = ConsentOptions.OfflineAccessDescription, - Emphasize = true, - Checked = check - }; - } - - /// - /// Processes the consent. - /// - /// The model. - /// private async Task ProcessConsent(DeviceAuthorizationInputModel model) { var result = new ProcessConsentResult(); - var request = await this._interaction.GetAuthorizationContextAsync(model.UserCode); + var request = await _interaction.GetAuthorizationContextAsync(model.UserCode); if (request == null) return result; ConsentResponse grantedConsent = null; @@ -276,13 +88,10 @@ private async Task ProcessConsent(DeviceAuthorizationInput // user clicked 'no' - send back the standard 'access_denied' response if (model.Button == "no") { - grantedConsent = new ConsentResponse - { - Error = AuthorizationError.AccessDenied - }; + grantedConsent = new ConsentResponse { Error = AuthorizationError.AccessDenied }; // emit event - await this._events.RaiseAsync(new ConsentDeniedEvent(this.User.GetSubjectId(), request.Client.ClientId, request.ValidatedResources.RawScopeValues)); + await _events.RaiseAsync(new ConsentDeniedEvent(User.GetSubjectId(), request.Client.ClientId, request.ValidatedResources.RawScopeValues)); } // user clicked 'yes' - validate the data else if (model.Button == "yes") @@ -293,22 +102,18 @@ private async Task ProcessConsent(DeviceAuthorizationInput var scopes = model.ScopesConsented; if (ConsentOptions.EnableOfflineAccess == false) { - scopes = scopes.Where(x => x != IdentityServerConstants.StandardScopes.OfflineAccess); + scopes = scopes.Where(x => x != Duende.IdentityServer.IdentityServerConstants.StandardScopes.OfflineAccess); } grantedConsent = new ConsentResponse - { - RememberConsent = model.RememberConsent, - ScopesValuesConsented = scopes.ToArray(), - Description = model.Description - }; + { + RememberConsent = model.RememberConsent, + ScopesValuesConsented = scopes.ToArray(), + Description = model.Description + }; // emit event - await this._events.RaiseAsync(new ConsentGrantedEvent(this.User.GetSubjectId(), - request.Client.ClientId, - request.ValidatedResources.RawScopeValues, - grantedConsent.ScopesValuesConsented, - grantedConsent.RememberConsent)); + await _events.RaiseAsync(new ConsentGrantedEvent(User.GetSubjectId(), request.Client.ClientId, request.ValidatedResources.RawScopeValues, grantedConsent.ScopesValuesConsented, grantedConsent.RememberConsent)); } else { @@ -323,7 +128,7 @@ await this._events.RaiseAsync(new ConsentGrantedEvent(this.User.GetSubjectId(), if (grantedConsent != null) { // communicate outcome of consent back to identityserver - await this._interaction.HandleRequestAsync(model.UserCode, grantedConsent); + await _interaction.HandleRequestAsync(model.UserCode, grantedConsent); // indicate that's it ok to redirect back to authorization endpoint result.RedirectUri = model.ReturnUrl; @@ -332,26 +137,96 @@ await this._events.RaiseAsync(new ConsentGrantedEvent(this.User.GetSubjectId(), else { // we need to redisplay the consent UI - result.ViewModel = await this.BuildViewModelAsync(model.UserCode, model); + result.ViewModel = await BuildViewModelAsync(model.UserCode, model); } return result; } - #endregion + private async Task BuildViewModelAsync(string userCode, DeviceAuthorizationInputModel model = null) + { + var request = await _interaction.GetAuthorizationContextAsync(userCode); + if (request != null) + { + return CreateConsentViewModel(userCode, model, request); + } + + return null; + } + + private DeviceAuthorizationViewModel CreateConsentViewModel(string userCode, DeviceAuthorizationInputModel model, DeviceFlowAuthorizationRequest request) + { + var vm = new DeviceAuthorizationViewModel + { + UserCode = userCode, + Description = model?.Description, + + RememberConsent = model?.RememberConsent ?? true, + ScopesConsented = model?.ScopesConsented ?? Enumerable.Empty(), - #region Others + ClientName = request.Client.ClientName ?? request.Client.ClientId, + ClientUrl = request.Client.ClientUri, + ClientLogoUrl = request.Client.LogoUri, + AllowRememberConsent = request.Client.AllowRememberConsent + }; + + vm.IdentityScopes = request.ValidatedResources.Resources.IdentityResources.Select(x => CreateScopeViewModel(x, vm.ScopesConsented.Contains(x.Name) || model == null)).ToArray(); + + var apiScopes = new List(); + foreach (var parsedScope in request.ValidatedResources.ParsedScopes) + { + var apiScope = request.ValidatedResources.Resources.FindApiScope(parsedScope.ParsedName); + if (apiScope != null) + { + var scopeVm = CreateScopeViewModel(parsedScope, apiScope, vm.ScopesConsented.Contains(parsedScope.RawValue) || model == null); + apiScopes.Add(scopeVm); + } + } + if (ConsentOptions.EnableOfflineAccess && request.ValidatedResources.Resources.OfflineAccess) + { + apiScopes.Add(GetOfflineAccessScope(vm.ScopesConsented.Contains(Duende.IdentityServer.IdentityServerConstants.StandardScopes.OfflineAccess) || model == null)); + } + vm.ApiScopes = apiScopes; - /// - /// The controller name - /// - public const String ControllerName = "device"; + return vm; + } - /// - /// The controller route - /// - private const String ControllerRoute = DeviceController.ControllerName; + private ScopeViewModel CreateScopeViewModel(IdentityResource identity, bool check) + { + return new ScopeViewModel + { + Value = identity.Name, + DisplayName = identity.DisplayName ?? identity.Name, + Description = identity.Description, + Emphasize = identity.Emphasize, + Required = identity.Required, + Checked = check || identity.Required + }; + } - #endregion + public ScopeViewModel CreateScopeViewModel(ParsedScopeValue parsedScopeValue, ApiScope apiScope, bool check) + { + return new ScopeViewModel + { + Value = parsedScopeValue.RawValue, + // todo: use the parsed scope value in the display? + DisplayName = apiScope.DisplayName ?? apiScope.Name, + Description = apiScope.Description, + Emphasize = apiScope.Emphasize, + Required = apiScope.Required, + Checked = check || apiScope.Required + }; + } + private ScopeViewModel GetOfflineAccessScope(bool check) + { + return new ScopeViewModel + { + Value = Duende.IdentityServer.IdentityServerConstants.StandardScopes.OfflineAccess, + DisplayName = ConsentOptions.OfflineAccessDisplayName, + Description = ConsentOptions.OfflineAccessDescription, + Emphasize = true, + Checked = check + }; + } } } \ No newline at end of file diff --git a/SecurityService/Controllers/Diagnostics/DiagnosticsController.cs b/SecurityService/Controllers/Diagnostics/DiagnosticsController.cs index 29fb6fe3..07c82e70 100644 --- a/SecurityService/Controllers/Diagnostics/DiagnosticsController.cs +++ b/SecurityService/Controllers/Diagnostics/DiagnosticsController.cs @@ -1,58 +1,29 @@ -namespace SecurityService.Controllers.Diagnostics -{ - using System; - using System.Diagnostics.CodeAnalysis; - using System.Linq; - using System.Threading.Tasks; - using Microsoft.AspNetCore.Authentication; - using Microsoft.AspNetCore.Authorization; - using Microsoft.AspNetCore.Mvc; - using ViewModels; +// Copyright (c) Duende Software. All rights reserved. +// See LICENSE in the project root for license information. + + +using System.Linq; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Authentication; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Mvc; - /// - /// - /// - /// - [Route(DiagnosticsController.ControllerRoute)] - [ExcludeFromCodeCoverage] +namespace IdentityServerHost.Quickstart.UI +{ [SecurityHeaders] [Authorize] - [ApiExplorerSettings(IgnoreApi = true)] public class DiagnosticsController : Controller { - #region Methods - - /// - /// Indexes this instance. - /// - /// - [Route("index")] public async Task Index() { - var localAddresses = new[] {"127.0.0.1", "::1", this.HttpContext.Connection.LocalIpAddress.ToString()}; - if (!localAddresses.Contains(this.HttpContext.Connection.RemoteIpAddress.ToString())) + var localAddresses = new string[] { "127.0.0.1", "::1", HttpContext.Connection.LocalIpAddress.ToString() }; + if (!localAddresses.Contains(HttpContext.Connection.RemoteIpAddress.ToString())) { - return this.NotFound(); + return NotFound(); } - var model = new DiagnosticsViewModel(await this.HttpContext.AuthenticateAsync()); - return this.View(model); + var model = new DiagnosticsViewModel(await HttpContext.AuthenticateAsync()); + return View(model); } - - #endregion - - #region Others - - /// - /// The controller name - /// - public const String ControllerName = "diagnostics"; - - /// - /// The controller route - /// - private const String ControllerRoute = DiagnosticsController.ControllerName; - - #endregion } } \ No newline at end of file diff --git a/SecurityService/Controllers/Extensions.cs b/SecurityService/Controllers/Extensions.cs index 7e99cee7..1f58d59a 100644 --- a/SecurityService/Controllers/Extensions.cs +++ b/SecurityService/Controllers/Extensions.cs @@ -2,10 +2,10 @@ namespace SecurityService.Controllers { using System; using System.Diagnostics.CodeAnalysis; - using IdentityServer4.Models; + using Duende.IdentityServer.Models; + using IdentityServerHost.Quickstart.UI; using Microsoft.AspNetCore.Mvc; - using ViewModels; - + [ExcludeFromCodeCoverage] public static class Extensions { diff --git a/SecurityService/Controllers/Grants/GrantsController.cs b/SecurityService/Controllers/Grants/GrantsController.cs index 2b256472..db95dfa1 100644 --- a/SecurityService/Controllers/Grants/GrantsController.cs +++ b/SecurityService/Controllers/Grants/GrantsController.cs @@ -1,157 +1,97 @@ -namespace SecurityService.Controllers.Grants -{ - using System; - using System.Collections.Generic; - using System.Diagnostics.CodeAnalysis; - using System.Linq; - using System.Threading.Tasks; - using IdentityServer4.Events; - using IdentityServer4.Extensions; - using IdentityServer4.Services; - using IdentityServer4.Stores; - using Microsoft.AspNetCore.Authorization; - using Microsoft.AspNetCore.Mvc; - using ViewModels; +// Copyright (c) Duende Software. All rights reserved. +// See LICENSE in the project root for license information. + + +using Microsoft.AspNetCore.Mvc; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Duende.IdentityServer.Events; +using Duende.IdentityServer.Extensions; +using Duende.IdentityServer.Services; +using Duende.IdentityServer.Stores; +using Microsoft.AspNetCore.Authorization; +namespace IdentityServerHost.Quickstart.UI +{ /// /// This sample controller allows a user to revoke grants given to clients /// - /// - [Route(GrantsController.ControllerRoute)] - [ExcludeFromCodeCoverage] [SecurityHeaders] [Authorize] - [ApiExplorerSettings(IgnoreApi = true)] public class GrantsController : Controller { - #region Fields - - /// - /// The clients - /// - private readonly IClientStore _clients; - - /// - /// The events - /// - private readonly IEventService _events; - - /// - /// The interaction - /// private readonly IIdentityServerInteractionService _interaction; - - /// - /// The resources - /// + private readonly IClientStore _clients; private readonly IResourceStore _resources; + private readonly IEventService _events; - #endregion - - #region Constructors - - /// - /// Initializes a new instance of the class. - /// - /// The interaction. - /// The clients. - /// The resources. - /// The events. public GrantsController(IIdentityServerInteractionService interaction, - IClientStore clients, - IResourceStore resources, - IEventService events) + IClientStore clients, + IResourceStore resources, + IEventService events) { - this._interaction = interaction; - this._clients = clients; - this._resources = resources; - this._events = events; + _interaction = interaction; + _clients = clients; + _resources = resources; + _events = events; } - #endregion - - #region Methods - /// /// Show list of grants /// - /// [HttpGet] - [Route("index")] public async Task Index() { - return this.View("Index", await this.BuildViewModelAsync()); + return View("Index", await BuildViewModelAsync()); } /// /// Handle postback to revoke a client /// - /// The client identifier. - /// [HttpPost] [ValidateAntiForgeryToken] - [Route("revoke")] - public async Task Revoke(String clientId) + public async Task Revoke(string clientId) { - await this._interaction.RevokeUserConsentAsync(clientId); - await this._events.RaiseAsync(new GrantsRevokedEvent(this.User.GetSubjectId(), clientId)); + await _interaction.RevokeUserConsentAsync(clientId); + await _events.RaiseAsync(new GrantsRevokedEvent(User.GetSubjectId(), clientId)); - return this.RedirectToAction("Index"); + return RedirectToAction("Index"); } - /// - /// Builds the view model asynchronous. - /// - /// private async Task BuildViewModelAsync() { - var grants = await this._interaction.GetAllUserGrantsAsync(); + var grants = await _interaction.GetAllUserGrantsAsync(); var list = new List(); - foreach (var grant in grants) + foreach(var grant in grants) { - var client = await this._clients.FindClientByIdAsync(grant.ClientId); + var client = await _clients.FindClientByIdAsync(grant.ClientId); if (client != null) { - var resources = await this._resources.FindResourcesByScopeAsync(grant.Scopes); - - var item = new GrantViewModel - { - ClientId = client.ClientId, - ClientName = client.ClientName ?? client.ClientId, - ClientLogoUrl = client.LogoUri, - ClientUrl = client.ClientUri, - Description = grant.Description, - Created = grant.CreationTime, - Expires = grant.Expiration, - IdentityGrantNames = resources.IdentityResources.Select(x => x.DisplayName ?? x.Name).ToArray(), - ApiGrantNames = resources.ApiScopes.Select(x => x.DisplayName ?? x.Name).ToArray() - }; + var resources = await _resources.FindResourcesByScopeAsync(grant.Scopes); + + var item = new GrantViewModel() + { + ClientId = client.ClientId, + ClientName = client.ClientName ?? client.ClientId, + ClientLogoUrl = client.LogoUri, + ClientUrl = client.ClientUri, + Description = grant.Description, + Created = grant.CreationTime, + Expires = grant.Expiration, + IdentityGrantNames = resources.IdentityResources.Select(x => x.DisplayName ?? x.Name).ToArray(), + ApiGrantNames = resources.ApiScopes.Select(x => x.DisplayName ?? x.Name).ToArray() + }; list.Add(item); } } return new GrantsViewModel - { - Grants = list - }; + { + Grants = list + }; } - - #endregion - - #region Others - - /// - /// The controller name - /// - public const String ControllerName = "grants"; - - /// - /// The controller route - /// - private const String ControllerRoute = GrantsController.ControllerName; - - #endregion } } \ No newline at end of file diff --git a/SecurityService/Controllers/Home/HomeController.cs b/SecurityService/Controllers/Home/HomeController.cs index 47a47818..d2d99910 100644 --- a/SecurityService/Controllers/Home/HomeController.cs +++ b/SecurityService/Controllers/Home/HomeController.cs @@ -1,75 +1,58 @@ -// Copyright (c) Brock Allen & Dominick Baier. All rights reserved. -// Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information. +// Copyright (c) Duende Software. All rights reserved. +// See LICENSE in the project root for license information. -namespace SecurityService.Controllers.Home -{ - using System; - using System.Diagnostics.CodeAnalysis; - using System.Threading.Tasks; - using IdentityServer4.Services; - using Microsoft.AspNetCore.Authorization; - using Microsoft.AspNetCore.Hosting; - using Microsoft.AspNetCore.Mvc; - using Microsoft.Extensions.Hosting; - using Microsoft.Extensions.Logging; - using ViewModels; - [Route(HomeController.ControllerRoute)] - [ExcludeFromCodeCoverage] +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Hosting; +using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.Hosting; +using Microsoft.Extensions.Logging; +using System.Threading.Tasks; +using Duende.IdentityServer.Services; + +namespace IdentityServerHost.Quickstart.UI +{ [SecurityHeaders] [AllowAnonymous] - [ApiExplorerSettings(IgnoreApi = true)] public class HomeController : Controller { private readonly IIdentityServerInteractionService _interaction; private readonly IWebHostEnvironment _environment; private readonly ILogger _logger; - /// - /// The controller name - /// - public const String ControllerName = "home"; - - /// - /// The controller route - /// - private const String ControllerRoute = HomeController.ControllerName; - public HomeController(IIdentityServerInteractionService interaction, IWebHostEnvironment environment, ILogger logger) { - this._interaction = interaction; - this._environment = environment; - this._logger = logger; + _interaction = interaction; + _environment = environment; + _logger = logger; } - [Route("index")] public IActionResult Index() { - if (this._environment.IsDevelopment()) + if (_environment.IsDevelopment()) { // only show in development - return this.View(); + return View(); } - this._logger.LogInformation("Homepage is disabled in production. Returning 404."); - return this.NotFound(); + _logger.LogInformation("Homepage is disabled in production. Returning 404."); + return NotFound(); } /// /// Shows the error page /// - [Route("error")] public async Task Error(string errorId) { var vm = new ErrorViewModel(); // retrieve error details from identityserver - var message = await this._interaction.GetErrorContextAsync(errorId); + var message = await _interaction.GetErrorContextAsync(errorId); if (message != null) { vm.Error = message; - if (!this._environment.IsDevelopment()) + if (!_environment.IsDevelopment()) { // only show in development message.ErrorDescription = null; diff --git a/SecurityService/Controllers/IdentityResourceController.cs b/SecurityService/Controllers/IdentityResourceController.cs index 5a2e4a66..a9aef46f 100644 --- a/SecurityService/Controllers/IdentityResourceController.cs +++ b/SecurityService/Controllers/IdentityResourceController.cs @@ -5,12 +5,12 @@ using System.Diagnostics.CodeAnalysis; using System.Threading; using System.Threading.Tasks; + using BusinessLogic; using Common.Examples; using DataTransferObjects.Requests; using DataTransferObjects.Responses; + using Duende.IdentityServer.Models; using Factories; - using IdentityServer4.Models; - using Manager; using Microsoft.AspNetCore.Mvc; using Swashbuckle.AspNetCore.Annotations; using Swashbuckle.AspNetCore.Filters; diff --git a/SecurityService/Controllers/RoleController.cs b/SecurityService/Controllers/RoleController.cs index ebfa4032..dc1edd53 100644 --- a/SecurityService/Controllers/RoleController.cs +++ b/SecurityService/Controllers/RoleController.cs @@ -7,11 +7,11 @@ namespace SecurityService.Controllers { using System.Threading; + using BusinessLogic; using Common.Examples; using DataTransferObjects.Requests; using DataTransferObjects.Responses; using Factories; - using Manager; using Microsoft.AspNetCore.Mvc; using Swashbuckle.AspNetCore.Annotations; using Swashbuckle.AspNetCore.Filters; diff --git a/SecurityService/Controllers/UserController.cs b/SecurityService/Controllers/UserController.cs index 496ea347..7f4f3dba 100644 --- a/SecurityService/Controllers/UserController.cs +++ b/SecurityService/Controllers/UserController.cs @@ -5,11 +5,11 @@ using System.Diagnostics.CodeAnalysis; using System.Threading; using System.Threading.Tasks; + using BusinessLogic; using Common.Examples; using DataTransferObjects; using DataTransferObjects.Responses; using Factories; - using Manager; using Microsoft.AspNetCore.Mvc; using Swashbuckle.AspNetCore.Annotations; using Swashbuckle.AspNetCore.Filters; diff --git a/SecurityService/Dockerfile b/SecurityService/Dockerfile index 4d12589c..3ea9447f 100644 --- a/SecurityService/Dockerfile +++ b/SecurityService/Dockerfile @@ -5,7 +5,7 @@ FROM mcr.microsoft.com/dotnet/sdk:5.0 AS build WORKDIR /src COPY ["SecurityService/NuGet.Config", "."] COPY ["SecurityService/SecurityService.csproj", "SecurityService/"] -COPY ["SecurityService.Manager/SecurityService.Manager.csproj", "SecurityService.Manager/"] +COPY ["SecurityService.BusinessLogic/SecurityService.BusinessLogic.csproj", "SecurityService.BusinessLogic/"] COPY ["SecurityService.DataTransferObjects/SecurityService.DataTransferObjects.csproj", "SecurityService.DataTransferObjects/"] RUN dotnet restore "SecurityService/SecurityService.csproj" diff --git a/SecurityService/DockerfileWindows b/SecurityService/DockerfileWindows index 4d12589c..3ea9447f 100644 --- a/SecurityService/DockerfileWindows +++ b/SecurityService/DockerfileWindows @@ -5,7 +5,7 @@ FROM mcr.microsoft.com/dotnet/sdk:5.0 AS build WORKDIR /src COPY ["SecurityService/NuGet.Config", "."] COPY ["SecurityService/SecurityService.csproj", "SecurityService/"] -COPY ["SecurityService.Manager/SecurityService.Manager.csproj", "SecurityService.Manager/"] +COPY ["SecurityService.BusinessLogic/SecurityService.BusinessLogic.csproj", "SecurityService.BusinessLogic/"] COPY ["SecurityService.DataTransferObjects/SecurityService.DataTransferObjects.csproj", "SecurityService.DataTransferObjects/"] RUN dotnet restore "SecurityService/SecurityService.csproj" diff --git a/SecurityService/Extensions.cs b/SecurityService/Extensions.cs new file mode 100644 index 00000000..8ed5ab91 --- /dev/null +++ b/SecurityService/Extensions.cs @@ -0,0 +1,31 @@ +// Copyright (c) Duende Software. All rights reserved. +// See LICENSE in the project root for license information. + + +using System; +using Duende.IdentityServer.Models; +using Microsoft.AspNetCore.Mvc; + +namespace IdentityServerHost.Quickstart.UI +{ + public static class Extensions + { + /// + /// Checks if the redirect URI is for a native client. + /// + /// + public static bool IsNativeClient(this AuthorizationRequest context) + { + return !context.RedirectUri.StartsWith("https", StringComparison.Ordinal) + && !context.RedirectUri.StartsWith("http", StringComparison.Ordinal); + } + + public static IActionResult LoadingPage(this Controller controller, string viewName, string redirectUri) + { + controller.HttpContext.Response.StatusCode = 200; + controller.HttpContext.Response.Headers["Location"] = ""; + + return controller.View(viewName, new RedirectViewModel { RedirectUrl = redirectUri }); + } + } +} diff --git a/SecurityService/Extensions/Extensions.cs b/SecurityService/Extensions/Extensions.cs deleted file mode 100644 index ed57378d..00000000 --- a/SecurityService/Extensions/Extensions.cs +++ /dev/null @@ -1,28 +0,0 @@ -namespace SecurityService.Extensions -{ - using System.Diagnostics.CodeAnalysis; - using System.Threading.Tasks; - using IdentityServer4.Models; - using IdentityServer4.Stores; - - [ExcludeFromCodeCoverage] - public static class Extensions - { - /// - /// Determines whether the client is configured to use PKCE. - /// - /// The store. - /// The client identifier. - /// - public static async Task IsPkceClientAsync(this IClientStore store, string client_id) - { - if (!string.IsNullOrWhiteSpace(client_id)) - { - Client client = await store.FindEnabledClientByIdAsync(client_id); - return client?.RequirePkce == true; - } - - return false; - } - } -} diff --git a/SecurityService/Factories/IModelFactory.cs b/SecurityService/Factories/IModelFactory.cs index 17d4ad0d..e5376cd7 100644 --- a/SecurityService/Factories/IModelFactory.cs +++ b/SecurityService/Factories/IModelFactory.cs @@ -7,7 +7,7 @@ namespace SecurityService.Factories { using System.Collections.Generic; using DataTransferObjects.Responses; - using IdentityServer4.Models; + using Duende.IdentityServer.Models; /// /// diff --git a/SecurityService/Factories/ModelFactory.cs b/SecurityService/Factories/ModelFactory.cs index ee375374..08dd0197 100644 --- a/SecurityService/Factories/ModelFactory.cs +++ b/SecurityService/Factories/ModelFactory.cs @@ -3,7 +3,7 @@ using System.Collections.Generic; using System.Linq; using DataTransferObjects.Responses; - using IdentityServer4.Models; + using Duende.IdentityServer.Models; /// /// diff --git a/SecurityService/Program.cs b/SecurityService/Program.cs index 193352c1..f368bc8b 100644 --- a/SecurityService/Program.cs +++ b/SecurityService/Program.cs @@ -1,40 +1,60 @@ -namespace SecurityService +// Copyright (c) Duende Software. All rights reserved. +// See LICENSE in the project root for license information. + + +using Microsoft.AspNetCore.Hosting; +using Microsoft.Extensions.Hosting; +using Serilog; +using Serilog.Events; +using Serilog.Sinks.SystemConsole.Themes; +using System; + +namespace SecurityService { - using System; - using System.Diagnostics.CodeAnalysis; using System.IO; - using Microsoft.AspNetCore.Hosting; + using System.Security.Cryptography.X509Certificates; using Microsoft.Extensions.Configuration; - using Microsoft.Extensions.Hosting; - [ExcludeFromCodeCoverage] public class Program { - #region Methods - public static IHostBuilder CreateHostBuilder(String[] args) { Console.Title = "Security Service"; //At this stage, we only need our hosting file for ip and ports - IConfigurationRoot config = new ConfigurationBuilder().SetBasePath(Directory.GetCurrentDirectory()).AddJsonFile("hosting.json", optional:true) - .AddJsonFile("hosting.development.json", optional:true).AddEnvironmentVariables().Build(); + IConfigurationRoot config = new ConfigurationBuilder().SetBasePath(Directory.GetCurrentDirectory()).AddJsonFile("hosting.json", optional: true) + .AddJsonFile("hosting.development.json", optional: true).AddEnvironmentVariables().Build(); IHostBuilder hostBuilder = Host.CreateDefaultBuilder(args); hostBuilder.ConfigureWebHostDefaults(webBuilder => - { - webBuilder.UseStartup(); - webBuilder.UseConfiguration(config); - webBuilder.UseKestrel(); - }); + { + webBuilder.UseStartup(); + webBuilder.UseConfiguration(config); + webBuilder.UseKestrel(); + }); return hostBuilder; } public static void Main(String[] args) { + Log.Logger = new LoggerConfiguration() + .MinimumLevel.Verbose() + .MinimumLevel.Override("Microsoft", LogEventLevel.Warning) + .MinimumLevel.Override("Microsoft.Hosting.Lifetime", LogEventLevel.Information) + .MinimumLevel.Override("System", LogEventLevel.Warning) + .MinimumLevel.Override("Microsoft.AspNetCore.Authentication", LogEventLevel.Information) + .Enrich.FromLogContext() + // uncomment to write to Azure diagnostics stream + //.WriteTo.File( + // @"D:\home\LogFiles\Application\identityserver.txt", + // fileSizeLimitBytes: 1_000_000, + // rollOnFileSizeLimit: true, + // shared: true, + // flushToDiskInterval: TimeSpan.FromSeconds(1)) + .WriteTo.Console(outputTemplate: "[{Timestamp:HH:mm:ss} {Level}] {SourceContext}{NewLine}{Message:lj}{NewLine}{Exception}{NewLine}", theme: AnsiConsoleTheme.Code) + .CreateLogger(); + Program.CreateHostBuilder(args).Build().Run(); } - - #endregion } } \ No newline at end of file diff --git a/SecurityService/SecurityHeadersAttribute.cs b/SecurityService/SecurityHeadersAttribute.cs new file mode 100644 index 00000000..e198d7f0 --- /dev/null +++ b/SecurityService/SecurityHeadersAttribute.cs @@ -0,0 +1,56 @@ +// Copyright (c) Duende Software. All rights reserved. +// See LICENSE in the project root for license information. + + +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Mvc.Filters; + +namespace IdentityServerHost.Quickstart.UI +{ + public class SecurityHeadersAttribute : ActionFilterAttribute + { + public override void OnResultExecuting(ResultExecutingContext context) + { + var result = context.Result; + if (result is ViewResult) + { + // https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Content-Type-Options + if (!context.HttpContext.Response.Headers.ContainsKey("X-Content-Type-Options")) + { + context.HttpContext.Response.Headers.Add("X-Content-Type-Options", "nosniff"); + } + + // https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Frame-Options + if (!context.HttpContext.Response.Headers.ContainsKey("X-Frame-Options")) + { + context.HttpContext.Response.Headers.Add("X-Frame-Options", "SAMEORIGIN"); + } + + // https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy + var csp = "default-src 'self'; object-src 'none'; frame-ancestors 'none'; sandbox allow-forms allow-same-origin allow-scripts; base-uri 'self';"; + // also consider adding upgrade-insecure-requests once you have HTTPS in place for production + //csp += "upgrade-insecure-requests;"; + // also an example if you need client images to be displayed from twitter + // csp += "img-src 'self' https://pbs.twimg.com;"; + + // once for standards compliant browsers + if (!context.HttpContext.Response.Headers.ContainsKey("Content-Security-Policy")) + { + context.HttpContext.Response.Headers.Add("Content-Security-Policy", csp); + } + // and once again for IE + if (!context.HttpContext.Response.Headers.ContainsKey("X-Content-Security-Policy")) + { + context.HttpContext.Response.Headers.Add("X-Content-Security-Policy", csp); + } + + // https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Referrer-Policy + var referrer_policy = "no-referrer"; + if (!context.HttpContext.Response.Headers.ContainsKey("Referrer-Policy")) + { + context.HttpContext.Response.Headers.Add("Referrer-Policy", referrer_policy); + } + } + } + } +} diff --git a/SecurityService/SecurityService.csproj b/SecurityService/SecurityService.csproj index 95029326..c1818c0e 100644 --- a/SecurityService/SecurityService.csproj +++ b/SecurityService/SecurityService.csproj @@ -1,88 +1,56 @@  - net5.0 + netcoreapp5.0 + 5e9b93dd-258d-47d7-a6d3-42e86a745857 Linux - - - D:\Projects\StuartFerguson\SecurityService\SecurityService\SecurityService.xml - - + - - - - - - - all - runtime; build; native; contentfiles; analyzers - - + + + + + + + + + + all runtime; build; native; contentfiles; analyzers; buildtransitive - - - - - - + - - - - - - - - + - + - - - - Always - - - Always - - - Always - - - Always - - - Always - - - Always - - - - - - - + + - - - + - - dockerfile + + Always + + + Always + + + Always + + + Always diff --git a/SecurityService/SecurityService.xml b/SecurityService/SecurityService.xml deleted file mode 100644 index f2e6bac9..00000000 --- a/SecurityService/SecurityService.xml +++ /dev/null @@ -1,1672 +0,0 @@ - - - - SecurityService - - - - - - - - - - - Gets the examples. - - - - - - - - - - - - Gets the examples. - - - - - - - - - - - - Gets the examples. - - - - - - - - - - - - Gets the examples. - - - - - - - - - - - - Gets the examples. - - - - - - - - - - - - Gets the examples. - - - - - - - - - - - - Gets the examples. - - - - - - - - - - - - Gets the examples. - - - - - - - - - - - - Gets the examples. - - - - - - - - - - - - Gets the examples. - - - - - - - - - - - - Gets the examples. - - - - - - - - - - - - Gets the examples. - - - - - - - - - - - - Gets the examples. - - - - - - - - - - - - Gets the examples. - - - - - - - - - - - - Gets the examples. - - - - - - - - - - - - Gets the examples. - - - - - - - - - - - - Gets the examples. - - - - - - - - - - - - Gets the examples. - - - - - - - - - - - The API resource description - - - - - The API resource display name - - - - - The API resource enabled - - - - - The API resource name - - - - - The API resource scope1 - - - - - The API resource scope2 - - - - - The API resource secret - - - - - The API resource user claim1 - - - - - The API resource user claim2 - - - - - The API scope description - - - - - The API scope display name - - - - - The API scope enabled - - - - - The API scope name - - - - - The client allowed grant type1 - - - - - The client allowed grant type2 - - - - - The client allowed scope1 - - - - - The client allowed scope2 - - - - - The client allow offline access - - - - - The client description - - - - - The client enabled - - - - - The client identifier - - - - - The client name - - - - - The client post logout redirect URI - - - - - The client redirect URI - - - - - The client require consent - - - - - The client secret - - - - - The identity resource claim1 - - - - - The identity resource claim2 - - - - - The identity resource description - - - - - The identity resource display name - - - - - The identity resource emphasize - - - - - The identity resource name - - - - - The identity resource required - - - - - The identity resource show in discovery document - - - - - The role identifier - - - - - The role name - - - - - The user claim1 name - - - - - The user claim1 value - - - - - The user claim2 name - - - - - The user claim2 value - - - - - The user email address - - - - - The user family name - - - - - The user given name - - - - - The user identifier - - - - - The user middle name - - - - - The user name - - - - - The user password - - - - - The user phone number - - - - - - - - - - - Gets the examples. - - - - - - - - - - - - Gets the examples. - - - - - - - - - - - - Gets the examples. - - - - - - - - - - - - Gets the examples. - - - - - - - - - - - - Gets the examples. - - - - - - - - - - - - Gets the examples. - - - - - - Applies the filter to the specified operation using the given context. - - The operation to apply the filter to. - The current operation filter context. - - - - Gets a value indicating whether this can read JSON. - - - true if this can read JSON; otherwise, false. - - - - - Determines whether this instance can convert the specified object type. - - Type of the object. - - true if this instance can convert the specified object type; otherwise, false. - - - - - Reads the JSON representation of the object. - - The to read from. - Type of the object. - The existing value of object being read. - The calling serializer. - - The object value. - - - - - - - Writes the JSON representation of the object. - - The to write to. - The value. - The calling serializer. - - - - This sample controller implements a typical login/logout/provision workflow for local and external accounts. - The login service encapsulates the interactions with the user data store. This data store is in-memory only and cannot be used for production! - The interaction service provides a way for the UI to communicate with identityserver for validation and context retrieval - - - - - - The client store - - - - - The events - - - - - The interaction - - - - - The scheme provider - - - - - The security service manager - - - - - Initializes a new instance of the class. - - The interaction. - The client store. - The scheme provider. - The events. - The security service manager. - - - - Accesses the denied. - - - - - - Entry point into the login workflow - - The return URL. - - - - - Handle postback from username/password login - - The model. - The button. - The cancellation token. - - No user found with Username [{model.Username}] - invalid return URL - - - - Show logout page - - The logout identifier. - - - - - Handle logout page postback - - The model. - - - - - Builds the logged out view model asynchronous. - - The logout identifier. - - - - - Builds the login view model asynchronous. - - The return URL. - - - - - Builds the login view model asynchronous. - - The model. - - - - - Builds the logout view model asynchronous. - - The logout identifier. - - - - - The controller name - - - - - The controller route - - - - - - - - - - - The client store - - - - - The events - - - - - The interaction - - - - - The logger - - - - - The security service manager - - - - - The users - - - - - Initializes a new instance of the class. - - The interaction. - The client store. - The events. - The logger. - The security service manager. - - - - Post processing of external authentication - - - External authentication error - - - - initiate roundtrip to external authentication provider - - The scheme. - The return URL. - - invalid return URL - - - - Automatics the provision user. - - The provider. - The provider user identifier. - The claims. - - - - - Finds the user from external provider. - - The result. - - Unknown userid - - - - Processes the login callback. - - The external result. - The local claims. - The local sign in props. - - - - The controller name - - - - - The controller route - - - - - - - - - - - The manager - - - - - The model factory - - - - - Initializes a new instance of the class. - - The manager. - The model factory. - - - - Creates the API resource. - - The create API resource request. - The cancellation token. - - - - - Gets the API resource. - - Name of the API resource. - The cancellation token. - - - - - Gets the API resources. - - The cancellation token. - - - - - The controller name - - - - - The controller route - - - - - - - - - - - The manager - - - - - The model factory - - - - - Initializes a new instance of the class. - - The manager. - The model factory. - - - - Gets the API scope. - - Name of the API scope. - The cancellation token. - - - - - Gets the api scopes. - - The cancellation token. - - - - - The controller name - - - - - The controller route - - - - - - - - - - - The manager - - - - - The model factory - - - - - Initializes a new instance of the class. - - The manager. - The model factory. - - - - Creates the client. - - The create client request. - The cancellation token. - - - - - Gets the client. - - The client identifier. - The cancellation token. - - - - - Gets the clients. - - The cancellation token. - - - - - The controller name - - - - - The controller route - - - - - This controller processes the consent UI - - - - - - The events - - - - - The interaction - - - - - The logger - - - - - Initializes a new instance of the class. - - The interaction. - The events. - The logger. - - - - Creates the scope view model. - - The parsed scope value. - The API scope. - if set to true [check]. - - - - - Shows the consent screen - - The return URL. - - - - - Handles the consent screen postback - - The model. - - - - - Builds the view model asynchronous. - - The return URL. - The model. - - - - - Creates the consent view model. - - The model. - The return URL. - The request. - - - - - Creates the scope view model. - - The identity. - if set to true [check]. - - - - - Gets the offline access scope. - - if set to true [check]. - - - - - Processes the consent. - - The model. - - - - - The controller name - - - - - The controller route - - - - - - - - - - - The events - - - - - The interaction - - - - - The logger - - - - - The options - - - - - Initializes a new instance of the class. - - The interaction. - The event service. - The options. - The logger. - - - - Callbacks the specified model. - - The model. - - model - - - - Creates the scope view model. - - The parsed scope value. - The API scope. - if set to true [check]. - - - - - Indexes this instance. - - - - - - Users the code capture. - - The user code. - - - - - Builds the view model asynchronous. - - The user code. - The model. - - - - - Creates the consent view model. - - The user code. - The model. - The request. - - - - - Creates the scope view model. - - The identity. - if set to true [check]. - - - - - Gets the offline access scope. - - if set to true [check]. - - - - - Processes the consent. - - The model. - - - - - The controller name - - - - - The controller route - - - - - - - - - - - Indexes this instance. - - - - - - The controller name - - - - - The controller route - - - - - Checks if the redirect URI is for a native client. - - - - - - This sample controller allows a user to revoke grants given to clients - - - - - - The clients - - - - - The events - - - - - The interaction - - - - - The resources - - - - - Initializes a new instance of the class. - - The interaction. - The clients. - The resources. - The events. - - - - Show list of grants - - - - - - Handle postback to revoke a client - - The client identifier. - - - - - Builds the view model asynchronous. - - - - - - The controller name - - - - - The controller route - - - - - The controller name - - - - - The controller route - - - - - Shows the error page - - - - - - - - - - - The manager - - - - - The model factory - - - - - Initializes a new instance of the class. - - The manager. - The model factory. - - - - Creates the identity resource. - - The create identity resource request. - The cancellation token. - - - - - Gets the identity resource. - - Name of the identity resource. - The cancellation token. - - - - - Gets the identity resources. - - The cancellation token. - - - - - The controller name - - - - - The controller route - - - - - The manager - - - - - Initializes a new instance of the class. - - The manager. - The model factory. - - - - Creates the role. - - The create role request. - The cancellation token. - - - - - Gets the role. - - The role identifier. - The cancellation token. - - - - - Gets the roles. - - The role identifier. - The cancellation token. - - - - - The controller name - - - - - The controller route - - - - - - - - - - - The manager - - - - - Initializes a new instance of the class. - - The manager. - The model factory. - - - - Creates the user. - - The create user request. - The cancellation token. - - - - - Gets the user. - - The user identifier. - The cancellation token. - - - - - Gets the users. - - Name of the user. - The cancellation token. - - - - - The controller name - - - - - The controller route - - - - - Determines whether the client is configured to use PKCE. - - The store. - The client identifier. - - - - - - - - - - Converts from. - - The model. - - - - - Converts from. - - The model. - - - - - Converts from. - - The model. - - - - - Converts from. - - The model. - - - - - Converts from. - - The model. - - - - - Converts from. - - The model. - - - - - Converts from. - - The model. - - - - - Converts from. - - The model. - - - - - Converts from. - - The model. - - - - - Converts from. - - The model. - - - - - Converts from. - - The model. - - - - - Converts from. - - The model. - - - - - - - - - - - Converts from. - - The model. - - - - - Converts from. - - The model. - - - - - Converts from. - - The model. - - - - - Converts from. - - The model. - - - - - Converts from. - - The model. - - - - - Converts from. - - The model. - - - - - Converts from. - - The model. - - - - - Converts from. - - The model. - - - - - Converts from. - - The model. - - - - - Converts from. - - The model. - - - - - Converts from. - - The model. - - - - - Converts from. - - The model. - - - - - The authentication conenction string - - - - - The configuration connection string - - - - - The persisted grant store conenction string - - - - - Initializes a new instance of the class. - - The env. - - - - Gets or sets the configuration. - - - The configuration. - - - - - Gets or sets the hosting environment. - - - The hosting environment. - - - - - Configures the specified application. - - The application. - The env. - The logger factory. - The provider. - - - diff --git a/SecurityService/Startup.cs b/SecurityService/Startup.cs index ba15f909..6e809a1e 100644 --- a/SecurityService/Startup.cs +++ b/SecurityService/Startup.cs @@ -1,41 +1,44 @@ -namespace SecurityService +// Copyright (c) Duende Software. All rights reserved. +// See LICENSE in the project root for license information. + +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Hosting; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; + +namespace SecurityService { using System; - using System.Diagnostics.CodeAnalysis; using System.IO; + using System.Linq; using System.Net.Http; using System.Reflection; - using System.Threading.Tasks; - using Database.DbContexts; - using Database.Seeding; + using System.Security.Claims; + using BusinessLogic; + using Duende.IdentityServer.EntityFramework.DbContexts; + using Duende.IdentityServer.EntityFramework.Mappers; + using Duende.IdentityServer.Models; using Factories; using HealthChecks.UI.Client; - using IdentityServer4.EntityFramework.DbContexts; - using IdentityServer4.Extensions; - using Manager; - using Microsoft.AspNetCore.Builder; + using IdentityModel; using Microsoft.AspNetCore.Diagnostics.HealthChecks; - using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.HttpOverrides; using Microsoft.AspNetCore.Identity; + using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Configuration; - using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Diagnostics.HealthChecks; - using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; - using Microsoft.Extensions.Options; using Microsoft.OpenApi.Models; using Newtonsoft.Json; using Newtonsoft.Json.Serialization; using NLog.Extensions.Logging; + using SecurityService.Database.DbContexts; using Shared.Extensions; using Shared.General; using Shared.Logger; using Swashbuckle.AspNetCore.Filters; - using Swashbuckle.AspNetCore.SwaggerGen; using ILogger = Microsoft.Extensions.Logging.ILogger; - [ExcludeFromCodeCoverage] public class Startup { #region Fields @@ -57,30 +60,6 @@ public class Startup #endregion - #region Constructors - - /// - /// Initializes a new instance of the class. - /// - /// The env. - public Startup(IWebHostEnvironment webHostEnvironment) - { - IConfigurationBuilder builder = new ConfigurationBuilder().SetBasePath(webHostEnvironment.ContentRootPath) - .AddJsonFile("appsettings.json", optional:true, reloadOnChange:true) - .AddJsonFile($"appsettings.{webHostEnvironment.EnvironmentName}.json", optional:true) - .AddEnvironmentVariables(); - - Startup.Configuration = builder.Build(); - Startup.WebHostEnvironment = webHostEnvironment; - - // Get the DB Connection Strings - Startup.PersistedGrantStoreConenctionString = Startup.Configuration.GetConnectionString(nameof(PersistedGrantDbContext)); - Startup.ConfigurationConnectionString = Startup.Configuration.GetConnectionString(nameof(ConfigurationDbContext)); - Startup.AuthenticationConenctionString = Startup.Configuration.GetConnectionString(nameof(AuthenticationDbContext)); - } - - #endregion - #region Properties /// @@ -101,83 +80,38 @@ public Startup(IWebHostEnvironment webHostEnvironment) #endregion - #region Methods - - /// - /// Configures the specified application. - /// - /// The application. - /// The env. - /// The logger factory. - /// The provider. - public void Configure(IApplicationBuilder app, - IWebHostEnvironment env, - ILoggerFactory loggerFactory) + public Startup(IWebHostEnvironment webHostEnvironment) { - app.Use(async (ctx, next) => - { - var gimp = Configuration.GetValue("ServiceOptions:PublicOrigin"); - ctx.SetIdentityServerOrigin(gimp); - await next(); - }); - - String nlogConfigFilename = "nlog.config"; - if (env.IsDevelopment()) - { - nlogConfigFilename = $"nlog.{env.EnvironmentName}.config"; - app.UseDeveloperExceptionPage(); - } - - loggerFactory.ConfigureNLog(Path.Combine(Startup.WebHostEnvironment.ContentRootPath, nlogConfigFilename)); - loggerFactory.AddNLog(); - - ILogger logger = loggerFactory.CreateLogger("Security Service"); - - Logger.Initialise(logger); - - app.AddRequestLogging(); - app.AddResponseLogging(); - app.AddExceptionHandler(); - - app.UseRouting(); - // Block 4: - // UseIdentityServer include a call to UseAuthentication - app.UseIdentityServer(); - app.UseAuthorization(); - - app.UseStaticFiles(); - - app.UseForwardedHeaders(new ForwardedHeadersOptions - { - ForwardedHeaders = ForwardedHeaders.XForwardedProto - }); - - app.UseIdentityServer(); - - // Setup the database - this.InitialiseDatabase(app).Wait(); - - app.UseEndpoints(endpoints => - { - endpoints.MapControllers(); - endpoints.MapHealthChecks("health", new HealthCheckOptions() - { - Predicate = _ => true, - ResponseWriter = UIResponseWriter.WriteHealthCheckUIResponse - }); - }); + IConfigurationBuilder builder = new ConfigurationBuilder().SetBasePath(webHostEnvironment.ContentRootPath) + .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true) + .AddJsonFile($"appsettings.{webHostEnvironment.EnvironmentName}.json", optional: true) + .AddEnvironmentVariables(); - app.UseSwagger(); + Startup.Configuration = builder.Build(); + Startup.WebHostEnvironment = webHostEnvironment; - app.UseSwaggerUI(); + // Get the DB Connection Strings + Startup.PersistedGrantStoreConenctionString = Startup.Configuration.GetConnectionString(nameof(PersistedGrantDbContext)); + Startup.ConfigurationConnectionString = Startup.Configuration.GetConnectionString(nameof(ConfigurationDbContext)); + Startup.AuthenticationConenctionString = Startup.Configuration.GetConnectionString(nameof(AuthenticationDbContext)); } public void ConfigureServices(IServiceCollection services) { ConfigurationReader.Initialise(Startup.Configuration); + + services.AddScoped(); + services.AddSingleton(); - this.ConfigureMiddlewareServices(services); + this.ConfigureIdentityServer(services); + this.ConfigureMVC(services); + this.ConfigureSwagger(services); + this.ConfigureHealthChecks(services); + } + + private void ConfigureMVC(IServiceCollection services) + { services.AddControllersWithViews().AddNewtonsoftJson(options => { options.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore; @@ -186,55 +120,55 @@ public void ConfigureServices(IServiceCollection services) options.SerializerSettings.DateTimeZoneHandling = DateTimeZoneHandling.Utc; options.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver(); }); - - services.AddScoped(); - services.AddSingleton(); } - - private void ConfigureMiddlewareServices(IServiceCollection services) + + private void ConfigureHealthChecks(IServiceCollection services) { services.AddHealthChecks() - .AddSqlServer(connectionString:ConfigurationReader.GetConnectionString("PersistedGrantDbContext"), - healthQuery:"SELECT 1;", - name:"Persisted Grant DB", - failureStatus:HealthStatus.Unhealthy, - tags:new string[] {"db", "sql", "sqlserver", "persistedgrant"}) - .AddSqlServer(connectionString:ConfigurationReader.GetConnectionString("ConfigurationDbContext"), - healthQuery:"SELECT 1;", - name:"Configuration DB", - failureStatus:HealthStatus.Unhealthy, - tags:new string[] {"db", "sql", "sqlserver", "configuration"}) - .AddSqlServer(connectionString:ConfigurationReader.GetConnectionString("AuthenticationDbContext"), - healthQuery:"SELECT 1;", - name:"Authentication DB", - failureStatus:HealthStatus.Unhealthy, - tags:new string[] {"db", "sql", "sqlserver", "authentication"}) + .AddSqlServer(connectionString: ConfigurationReader.GetConnectionString("PersistedGrantDbContext"), + healthQuery: "SELECT 1;", + name: "Persisted Grant DB", + failureStatus: HealthStatus.Unhealthy, + tags: new string[] { "db", "sql", "sqlserver", "persistedgrant" }) + .AddSqlServer(connectionString: ConfigurationReader.GetConnectionString("ConfigurationDbContext"), + healthQuery: "SELECT 1;", + name: "Configuration DB", + failureStatus: HealthStatus.Unhealthy, + tags: new string[] { "db", "sql", "sqlserver", "configuration" }) + .AddSqlServer(connectionString: ConfigurationReader.GetConnectionString("AuthenticationDbContext"), + healthQuery: "SELECT 1;", + name: "Authentication DB", + failureStatus: HealthStatus.Unhealthy, + tags: new string[] { "db", "sql", "sqlserver", "authentication" }) .AddUrlGroup(new Uri($"{ConfigurationReader.GetValue("ServiceAddresses", "MessagingService")}/health"), name: "Messaging Service", httpMethod: HttpMethod.Get, failureStatus: HealthStatus.Unhealthy, tags: new string[] { "application", "messaging" }); + } + private void ConfigureSwagger(IServiceCollection services) + { services.AddSwaggerGen(c => { c.SwaggerDoc("v1", new OpenApiInfo - { - Title = "Authentication API", - Version = "1.0", - Description = "A REST Api to provide authentication services including management of user/client and api details.", - Contact = new OpenApiContact - { - Name = "Stuart Ferguson", - Email = "golfhandicapping@btinternet.com" - } - }); + { + Title = "Authentication API", + Version = "1.0", + Description = "A REST Api to provide authentication services including management of user/client and api details.", + Contact = new OpenApiContact + { + Name = "Stuart Ferguson", + Email = "golfhandicapping@btinternet.com" + } + }); // add a custom operation filter which sets default values c.OperationFilter(); c.ExampleFilters(); //Locate the XML files being generated by ASP.NET... - var directory = new DirectoryInfo(AppContext.BaseDirectory); - var xmlFiles = directory.GetFiles("*.xml"); + DirectoryInfo directory = new DirectoryInfo(AppContext.BaseDirectory); + FileInfo[] xmlFiles = directory.GetFiles("*.xml"); //... and tell Swagger to use those XML comments. foreach (FileInfo fileInfo in xmlFiles) @@ -244,34 +178,27 @@ private void ConfigureMiddlewareServices(IServiceCollection services) }); services.AddSwaggerExamplesFromAssemblyOf(); + } - services.AddIdentity(o => - { - o.Password.RequireDigit = - Startup.Configuration.GetValue("IdentityOptions:PasswordOptions:RequireDigit"); - o.Password.RequireLowercase = - Startup.Configuration.GetValue("IdentityOptions:PasswordOptions:RequireLowercase"); - o.Password.RequireUppercase = - Startup.Configuration.GetValue("IdentityOptions:PasswordOptions:RequireUppercase"); - o.Password.RequireNonAlphanumeric = - Startup.Configuration.GetValue("IdentityOptions:PasswordOptions:RequireNonAlphanumeric"); - o.Password.RequiredLength = - Startup.Configuration.GetValue("IdentityOptions:PasswordOptions:RequiredLength"); - }).AddEntityFrameworkStores().AddDefaultTokenProviders(); + private void ConfigureIdentityServer(IServiceCollection services) + { + services.AddIdentity() + .AddEntityFrameworkStores() + .AddDefaultTokenProviders(); IIdentityServerBuilder identityServerBuilder = services.AddIdentityServer(options => - { - options.Events.RaiseSuccessEvents = true; - options.Events.RaiseFailureEvents = true; - options.Events.RaiseErrorEvents = true; - // TODO: Investigate - https://github.com/IdentityServer/IdentityServer4/issues/4631 - //options.PublicOrigin = Startup.Configuration.GetValue("ServiceOptions:PublicOrigin"); - options.IssuerUri = - Startup.Configuration.GetValue("ServiceOptions:IssuerUrl"); - }) - .AddAspNetIdentity() - .AddJwtBearerClientAuthentication() - .AddDeveloperSigningCredential(); + { + // https://docs.duendesoftware.com/identityserver/v5/fundamentals/resources/ + options.EmitStaticAudienceClaim = true; + + options.Events.RaiseSuccessEvents = true; + options.Events.RaiseFailureEvents = true; + options.Events.RaiseErrorEvents = true; + + options.IssuerUri = Startup.Configuration.GetValue("ServiceOptions:IssuerUrl"); + }); + + identityServerBuilder.AddAspNetIdentity(); if (Startup.WebHostEnvironment.IsEnvironment("IntegrationTest") || Startup.Configuration.GetValue("ServiceOptions:UseInMemoryDatabase") == true) { @@ -285,26 +212,88 @@ private void ConfigureMiddlewareServices(IServiceCollection services) Startup.AuthenticationConenctionString, migrationsAssembly); } - - services.AddCors(); } - private async Task InitialiseDatabase(IApplicationBuilder app) + public void Configure(IApplicationBuilder app, + IWebHostEnvironment env, + ILoggerFactory loggerFactory) { - using(IServiceScope scope = app.ApplicationServices.GetService().CreateScope()) + String nlogConfigFilename = "nlog.config"; + if (env.IsDevelopment()) { - PersistedGrantDbContext persistedGrantDbContext = scope.ServiceProvider.GetRequiredService(); - ConfigurationDbContext configurationDbContext = scope.ServiceProvider.GetRequiredService(); - AuthenticationDbContext authenticationDbContext = scope.ServiceProvider.GetRequiredService(); + nlogConfigFilename = $"nlog.{env.EnvironmentName}.config"; + app.UseDeveloperExceptionPage(); + } + + loggerFactory.ConfigureNLog(Path.Combine(Startup.WebHostEnvironment.ContentRootPath, nlogConfigFilename)); + loggerFactory.AddNLog(); + + ILogger logger = loggerFactory.CreateLogger("Security Service"); - SeedingType seedingType = Startup.Configuration.GetValue("SeedingType"); + Logger.Initialise(logger); - DatabaseSeeding.InitialiseAuthenticationDatabase(authenticationDbContext, seedingType); - DatabaseSeeding.InitialiseConfigurationDatabase(configurationDbContext, seedingType); - DatabaseSeeding.InitialisePersistedGrantDatabase(persistedGrantDbContext, seedingType); + app.AddRequestLogging(); + app.AddResponseLogging(); + app.AddExceptionHandler(); + + if (env.IsDevelopment()) + { + app.UseDeveloperExceptionPage(); } + + + app.UseRouting(); + + app.UseIdentityServer(); + + app.UseAuthorization(); + app.UseHttpsRedirection(); + app.UseStaticFiles(); + + app.UseForwardedHeaders(new ForwardedHeadersOptions + { + ForwardedHeaders = ForwardedHeaders.XForwardedProto + }); + + app.UseEndpoints(endpoints => + { + endpoints.MapDefaultControllerRoute(); + endpoints.MapHealthChecks("health", new HealthCheckOptions() + { + Predicate = _ => true, + ResponseWriter = UIResponseWriter.WriteHealthCheckUIResponse + }); + }); + + app.UseSwagger(); + + app.UseSwaggerUI(); + + // this will do the initial DB population + this.InitializeDatabase(app); } - #endregion + private void InitializeDatabase(IApplicationBuilder app) + { + using (var serviceScope = app.ApplicationServices.GetService().CreateScope()) + { + var persistedGrantDbContext = serviceScope.ServiceProvider.GetRequiredService(); + if (persistedGrantDbContext.Database.IsRelational()) + { + persistedGrantDbContext.Database.Migrate(); + } + var configurationDbContext = serviceScope.ServiceProvider.GetRequiredService(); + if (configurationDbContext.Database.IsRelational()) + { + configurationDbContext.Database.Migrate(); + } + + var authenticationContext = serviceScope.ServiceProvider.GetRequiredService(); + if (authenticationContext.Database.IsRelational()) + { + authenticationContext.Database.Migrate(); + } + } + } } -} \ No newline at end of file +} diff --git a/SecurityService/UpdateUI.ps1 b/SecurityService/UpdateUI.ps1 new file mode 100644 index 00000000..e7323d04 --- /dev/null +++ b/SecurityService/UpdateUI.ps1 @@ -0,0 +1,40 @@ +$source = "https://github.com/DuendeSoftware/IdentityServer.Quickstart.UI.AspNetIdentity/archive/main.zip" +[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 +Invoke-WebRequest $source -OutFile ui.zip + +Expand-Archive ui.zip + +if (!(Test-Path -Path QuickStart)) { mkdir QuickStart } +if (!(Test-Path -Path Views)) { mkdir Views } +if (!(Test-Path -Path wwwroot)) { mkdir wwwroot } + +copy .\ui\IdentityServer.Quickstart.UI.AspNetIdentity-main\Quickstart\* QuickStart -recurse -force +copy .\ui\IdentityServer.Quickstart.UI.AspNetIdentity-main\Views\* Views -recurse -force +copy .\ui\IdentityServer.Quickstart.UI.AspNetIdentity-main\wwwroot\* wwwroot -recurse -force + +# Now split the Quickstart into Controllers and View models +if (!(Test-Path -Path Controllers)) { mkdir Controllers } +if (!(Test-Path -Path ViewModels)) { mkdir ViewModels } + +$controllerDir = Join-Path $PSScriptRoot "\Controllers" +$viewModelDir = Join-Path $PSScriptRoot "\ViewModels\" + +foreach ($d in $dir){ + $controllerFilter = @('*Controller*.cs') + if (!(Test-Path -Path $controllerDir\$d)) { mkdir Controllers\$d } + if (!(Test-Path -Path $viewModelDir\$d)) { mkdir ViewModels\$d } + + Get-ChildItem -Path QuickStart\$d -Include *Controller*.cs -Recurse | ForEach-Object { + Copy-Item -Path $_.FullName -Destination $controllerDir\$d + } + + if (!(Test-Path -Path $controllerDir\$d)) { mkdir ViewModels\$d } + Get-ChildItem -Path QuickStart\$d -Exclude *Controller*.cs -Recurse | ForEach-Object { + Copy-Item -Path $_.FullName -Destination $viewModelDir\$d + } +} +copy .\ui\IdentityServer.Quickstart.UI.AspNetIdentity-main\Quickstart\*.cs -force + +del ui.zip +del ui -recurse +del QuickStart -recurse \ No newline at end of file diff --git a/SecurityService/ViewModels/Account/AccountOptions.cs b/SecurityService/ViewModels/Account/AccountOptions.cs new file mode 100644 index 00000000..4997d184 --- /dev/null +++ b/SecurityService/ViewModels/Account/AccountOptions.cs @@ -0,0 +1,20 @@ +// Copyright (c) Duende Software. All rights reserved. +// See LICENSE in the project root for license information. + + +using System; + +namespace IdentityServerHost.Quickstart.UI +{ + public class AccountOptions + { + public static bool AllowLocalLogin = true; + public static bool AllowRememberLogin = true; + public static TimeSpan RememberMeLoginDuration = TimeSpan.FromDays(30); + + public static bool ShowLogoutPrompt = true; + public static bool AutomaticRedirectAfterSignOut = false; + + public static string InvalidCredentialsErrorMessage = "Invalid username or password"; + } +} diff --git a/SecurityService/ViewModels/Account/ExternalProvider.cs b/SecurityService/ViewModels/Account/ExternalProvider.cs new file mode 100644 index 00000000..72a64c38 --- /dev/null +++ b/SecurityService/ViewModels/Account/ExternalProvider.cs @@ -0,0 +1,12 @@ +// Copyright (c) Duende Software. All rights reserved. +// See LICENSE in the project root for license information. + + +namespace IdentityServerHost.Quickstart.UI +{ + public class ExternalProvider + { + public string DisplayName { get; set; } + public string AuthenticationScheme { get; set; } + } +} \ No newline at end of file diff --git a/SecurityService/ViewModels/LoggedOutViewModel.cs b/SecurityService/ViewModels/Account/LoggedOutViewModel.cs similarity index 50% rename from SecurityService/ViewModels/LoggedOutViewModel.cs rename to SecurityService/ViewModels/Account/LoggedOutViewModel.cs index c6b0fd3c..347180f5 100644 --- a/SecurityService/ViewModels/LoggedOutViewModel.cs +++ b/SecurityService/ViewModels/Account/LoggedOutViewModel.cs @@ -1,12 +1,9 @@ -// Copyright (c) Brock Allen & Dominick Baier. All rights reserved. -// Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information. +// Copyright (c) Duende Software. All rights reserved. +// See LICENSE in the project root for license information. -namespace SecurityService.ViewModels +namespace IdentityServerHost.Quickstart.UI { - using System.Diagnostics.CodeAnalysis; - - [ExcludeFromCodeCoverage] public class LoggedOutViewModel { public string PostLogoutRedirectUri { get; set; } @@ -16,7 +13,7 @@ public class LoggedOutViewModel public bool AutomaticRedirectAfterSignOut { get; set; } public string LogoutId { get; set; } - public bool TriggerExternalSignout => this.ExternalAuthenticationScheme != null; + public bool TriggerExternalSignout => ExternalAuthenticationScheme != null; public string ExternalAuthenticationScheme { get; set; } } } \ No newline at end of file diff --git a/SecurityService/ViewModels/Account/LoginInputModel.cs b/SecurityService/ViewModels/Account/LoginInputModel.cs new file mode 100644 index 00000000..36f5e4d3 --- /dev/null +++ b/SecurityService/ViewModels/Account/LoginInputModel.cs @@ -0,0 +1,18 @@ +// Copyright (c) Duende Software. All rights reserved. +// See LICENSE in the project root for license information. + + +using System.ComponentModel.DataAnnotations; + +namespace IdentityServerHost.Quickstart.UI +{ + public class LoginInputModel + { + [Required] + public string Username { get; set; } + [Required] + public string Password { get; set; } + public bool RememberLogin { get; set; } + public string ReturnUrl { get; set; } + } +} \ No newline at end of file diff --git a/SecurityService/ViewModels/Account/LoginViewModel.cs b/SecurityService/ViewModels/Account/LoginViewModel.cs new file mode 100644 index 00000000..bd1ae4ae --- /dev/null +++ b/SecurityService/ViewModels/Account/LoginViewModel.cs @@ -0,0 +1,22 @@ +// Copyright (c) Duende Software. All rights reserved. +// See LICENSE in the project root for license information. + + +using System; +using System.Collections.Generic; +using System.Linq; + +namespace IdentityServerHost.Quickstart.UI +{ + public class LoginViewModel : LoginInputModel + { + public bool AllowRememberLogin { get; set; } = true; + public bool EnableLocalLogin { get; set; } = true; + + public IEnumerable ExternalProviders { get; set; } = Enumerable.Empty(); + public IEnumerable VisibleExternalProviders => ExternalProviders.Where(x => !String.IsNullOrWhiteSpace(x.DisplayName)); + + public bool IsExternalLoginOnly => EnableLocalLogin == false && ExternalProviders?.Count() == 1; + public string ExternalLoginScheme => IsExternalLoginOnly ? ExternalProviders?.SingleOrDefault()?.AuthenticationScheme : null; + } +} \ No newline at end of file diff --git a/SecurityService/ViewModels/Account/LogoutInputModel.cs b/SecurityService/ViewModels/Account/LogoutInputModel.cs new file mode 100644 index 00000000..debc4e6f --- /dev/null +++ b/SecurityService/ViewModels/Account/LogoutInputModel.cs @@ -0,0 +1,11 @@ +// Copyright (c) Duende Software. All rights reserved. +// See LICENSE in the project root for license information. + + +namespace IdentityServerHost.Quickstart.UI +{ + public class LogoutInputModel + { + public string LogoutId { get; set; } + } +} diff --git a/SecurityService/ViewModels/Account/LogoutViewModel.cs b/SecurityService/ViewModels/Account/LogoutViewModel.cs new file mode 100644 index 00000000..fd713fff --- /dev/null +++ b/SecurityService/ViewModels/Account/LogoutViewModel.cs @@ -0,0 +1,11 @@ +// Copyright (c) Duende Software. All rights reserved. +// See LICENSE in the project root for license information. + + +namespace IdentityServerHost.Quickstart.UI +{ + public class LogoutViewModel : LogoutInputModel + { + public bool ShowLogoutPrompt { get; set; } = true; + } +} diff --git a/SecurityService/ViewModels/Account/RedirectViewModel.cs b/SecurityService/ViewModels/Account/RedirectViewModel.cs new file mode 100644 index 00000000..7f16b421 --- /dev/null +++ b/SecurityService/ViewModels/Account/RedirectViewModel.cs @@ -0,0 +1,12 @@ +// Copyright (c) Duende Software. All rights reserved. +// See LICENSE in the project root for license information. + + + +namespace IdentityServerHost.Quickstart.UI +{ + public class RedirectViewModel + { + public string RedirectUrl { get; set; } + } +} \ No newline at end of file diff --git a/SecurityService/ViewModels/Consent/ConsentInputModel.cs b/SecurityService/ViewModels/Consent/ConsentInputModel.cs new file mode 100644 index 00000000..10d7f479 --- /dev/null +++ b/SecurityService/ViewModels/Consent/ConsentInputModel.cs @@ -0,0 +1,17 @@ +// Copyright (c) Duende Software. All rights reserved. +// See LICENSE in the project root for license information. + + +using System.Collections.Generic; + +namespace IdentityServerHost.Quickstart.UI +{ + public class ConsentInputModel + { + public string Button { get; set; } + public IEnumerable ScopesConsented { get; set; } + public bool RememberConsent { get; set; } + public string ReturnUrl { get; set; } + public string Description { get; set; } + } +} \ No newline at end of file diff --git a/SecurityService/ViewModels/Consent/ConsentOptions.cs b/SecurityService/ViewModels/Consent/ConsentOptions.cs new file mode 100644 index 00000000..d436d9c9 --- /dev/null +++ b/SecurityService/ViewModels/Consent/ConsentOptions.cs @@ -0,0 +1,16 @@ +// Copyright (c) Duende Software. All rights reserved. +// See LICENSE in the project root for license information. + + +namespace IdentityServerHost.Quickstart.UI +{ + public class ConsentOptions + { + public static bool EnableOfflineAccess = true; + public static string OfflineAccessDisplayName = "Offline Access"; + public static string OfflineAccessDescription = "Access to your applications and resources, even when you are offline"; + + public static readonly string MustChooseOneErrorMessage = "You must pick at least one permission"; + public static readonly string InvalidSelectionErrorMessage = "Invalid selection"; + } +} diff --git a/SecurityService/ViewModels/ConsentViewModel.cs b/SecurityService/ViewModels/Consent/ConsentViewModel.cs similarity index 55% rename from SecurityService/ViewModels/ConsentViewModel.cs rename to SecurityService/ViewModels/Consent/ConsentViewModel.cs index f4d6c07c..cb110983 100644 --- a/SecurityService/ViewModels/ConsentViewModel.cs +++ b/SecurityService/ViewModels/Consent/ConsentViewModel.cs @@ -1,12 +1,11 @@ -// Copyright (c) Brock Allen & Dominick Baier. All rights reserved. -// Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information. +// Copyright (c) Duende Software. All rights reserved. +// See LICENSE in the project root for license information. -namespace SecurityService.ViewModels -{ - using System.Collections.Generic; - using System.Diagnostics.CodeAnalysis; - [ExcludeFromCodeCoverage] +using System.Collections.Generic; + +namespace IdentityServerHost.Quickstart.UI +{ public class ConsentViewModel : ConsentInputModel { public string ClientName { get; set; } diff --git a/SecurityService/ViewModels/ProcessConsentResult.cs b/SecurityService/ViewModels/Consent/ProcessConsentResult.cs similarity index 57% rename from SecurityService/ViewModels/ProcessConsentResult.cs rename to SecurityService/ViewModels/Consent/ProcessConsentResult.cs index 23a640cc..da501941 100644 --- a/SecurityService/ViewModels/ProcessConsentResult.cs +++ b/SecurityService/ViewModels/Consent/ProcessConsentResult.cs @@ -1,13 +1,11 @@ -// Copyright (c) Brock Allen & Dominick Baier. All rights reserved. -// Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information. +// Copyright (c) Duende Software. All rights reserved. +// See LICENSE in the project root for license information. -namespace SecurityService.ViewModels -{ - using System.Diagnostics.CodeAnalysis; - using IdentityServer4.Models; +using Duende.IdentityServer.Models; - [ExcludeFromCodeCoverage] +namespace IdentityServerHost.Quickstart.UI +{ public class ProcessConsentResult { public bool IsRedirect => RedirectUri != null; diff --git a/SecurityService/ViewModels/Consent/ResourceViewModel.cs b/SecurityService/ViewModels/Consent/ResourceViewModel.cs new file mode 100644 index 00000000..1ae6a8e4 --- /dev/null +++ b/SecurityService/ViewModels/Consent/ResourceViewModel.cs @@ -0,0 +1,12 @@ +// Copyright (c) Duende Software. All rights reserved. +// See LICENSE in the project root for license information. + + +namespace IdentityServerHost.Quickstart.UI +{ + public class ResourceViewModel + { + public string Name { get; set; } + public string DisplayName { get; set; } + } +} diff --git a/SecurityService/ViewModels/ScopeViewModel.cs b/SecurityService/ViewModels/Consent/ScopeViewModel.cs similarity index 51% rename from SecurityService/ViewModels/ScopeViewModel.cs rename to SecurityService/ViewModels/Consent/ScopeViewModel.cs index b5415fad..e76b189f 100644 --- a/SecurityService/ViewModels/ScopeViewModel.cs +++ b/SecurityService/ViewModels/Consent/ScopeViewModel.cs @@ -1,19 +1,20 @@ -// Copyright (c) Brock Allen & Dominick Baier. All rights reserved. -// Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information. +// Copyright (c) Duende Software. All rights reserved. +// See LICENSE in the project root for license information. -namespace SecurityService.ViewModels -{ - using System.Diagnostics.CodeAnalysis; +using System.Collections.Generic; - [ExcludeFromCodeCoverage] +namespace IdentityServerHost.Quickstart.UI +{ public class ScopeViewModel { + public string Name { get; set; } public string Value { get; set; } public string DisplayName { get; set; } public string Description { get; set; } public bool Emphasize { get; set; } public bool Required { get; set; } public bool Checked { get; set; } + public IEnumerable Resources { get; set; } } } diff --git a/SecurityService/ViewModels/ConsentInputModel.cs b/SecurityService/ViewModels/ConsentInputModel.cs deleted file mode 100644 index 547a199e..00000000 --- a/SecurityService/ViewModels/ConsentInputModel.cs +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright (c) Brock Allen & Dominick Baier. All rights reserved. -// Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information. - -namespace SecurityService.ViewModels -{ - using System.Collections.Generic; - using System.Diagnostics.CodeAnalysis; - - [ExcludeFromCodeCoverage] - public class ConsentInputModel - { - public string Button { get; set; } - public IEnumerable ScopesConsented { get; set; } - public bool RememberConsent { get; set; } - public string ReturnUrl { get; set; } - public string Description { get; set; } - } -} \ No newline at end of file diff --git a/SecurityService/ViewModels/Device/DeviceAuthorizationInputModel.cs b/SecurityService/ViewModels/Device/DeviceAuthorizationInputModel.cs new file mode 100644 index 00000000..272442ad --- /dev/null +++ b/SecurityService/ViewModels/Device/DeviceAuthorizationInputModel.cs @@ -0,0 +1,11 @@ +// Copyright (c) Duende Software. All rights reserved. +// See LICENSE in the project root for license information. + + +namespace IdentityServerHost.Quickstart.UI +{ + public class DeviceAuthorizationInputModel : ConsentInputModel + { + public string UserCode { get; set; } + } +} \ No newline at end of file diff --git a/SecurityService/ViewModels/Device/DeviceAuthorizationViewModel.cs b/SecurityService/ViewModels/Device/DeviceAuthorizationViewModel.cs new file mode 100644 index 00000000..8cf030c9 --- /dev/null +++ b/SecurityService/ViewModels/Device/DeviceAuthorizationViewModel.cs @@ -0,0 +1,12 @@ +// Copyright (c) Duende Software. All rights reserved. +// See LICENSE in the project root for license information. + + +namespace IdentityServerHost.Quickstart.UI +{ + public class DeviceAuthorizationViewModel : ConsentViewModel + { + public string UserCode { get; set; } + public bool ConfirmUserCode { get; set; } + } +} \ No newline at end of file diff --git a/SecurityService/ViewModels/DeviceAuthorizationInputModel.cs b/SecurityService/ViewModels/DeviceAuthorizationInputModel.cs deleted file mode 100644 index 6f60b13e..00000000 --- a/SecurityService/ViewModels/DeviceAuthorizationInputModel.cs +++ /dev/null @@ -1,14 +0,0 @@ -// Copyright (c) Brock Allen & Dominick Baier. All rights reserved. -// Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information. - - -namespace SecurityService.ViewModels -{ - using System.Diagnostics.CodeAnalysis; - - [ExcludeFromCodeCoverage] - public class DeviceAuthorizationInputModel : ConsentInputModel - { - public string UserCode { get; set; } - } -} \ No newline at end of file diff --git a/SecurityService/ViewModels/DeviceAuthorizationViewModel.cs b/SecurityService/ViewModels/DeviceAuthorizationViewModel.cs deleted file mode 100644 index aa520e30..00000000 --- a/SecurityService/ViewModels/DeviceAuthorizationViewModel.cs +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright (c) Brock Allen & Dominick Baier. All rights reserved. -// Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information. - - -namespace SecurityService.ViewModels -{ - using System.Diagnostics.CodeAnalysis; - - [ExcludeFromCodeCoverage] - public class DeviceAuthorizationViewModel : ConsentViewModel - { - public string UserCode { get; set; } - public bool ConfirmUserCode { get; set; } - } -} \ No newline at end of file diff --git a/SecurityService/ViewModels/Diagnostics/DiagnosticsViewModel.cs b/SecurityService/ViewModels/Diagnostics/DiagnosticsViewModel.cs new file mode 100644 index 00000000..4bfd5cb6 --- /dev/null +++ b/SecurityService/ViewModels/Diagnostics/DiagnosticsViewModel.cs @@ -0,0 +1,32 @@ +// Copyright (c) Duende Software. All rights reserved. +// See LICENSE in the project root for license information. + + +using IdentityModel; +using Microsoft.AspNetCore.Authentication; +using System.Collections.Generic; +using System.Text; +using System.Text.Json; + +namespace IdentityServerHost.Quickstart.UI +{ + public class DiagnosticsViewModel + { + public DiagnosticsViewModel(AuthenticateResult result) + { + AuthenticateResult = result; + + if (result.Properties.Items.ContainsKey("client_list")) + { + var encoded = result.Properties.Items["client_list"]; + var bytes = Base64Url.Decode(encoded); + var value = Encoding.UTF8.GetString(bytes); + + Clients = JsonSerializer.Deserialize(value); + } + } + + public AuthenticateResult AuthenticateResult { get; } + public IEnumerable Clients { get; } = new List(); + } +} \ No newline at end of file diff --git a/SecurityService/ViewModels/DiagnosticsViewModel.cs b/SecurityService/ViewModels/DiagnosticsViewModel.cs deleted file mode 100644 index e1cd2051..00000000 --- a/SecurityService/ViewModels/DiagnosticsViewModel.cs +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright (c) Brock Allen & Dominick Baier. All rights reserved. -// Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information. - -namespace SecurityService.ViewModels -{ - using System; - using System.Collections.Generic; - using System.Diagnostics.CodeAnalysis; - using System.Text; - using IdentityModel; - using Microsoft.AspNetCore.Authentication; - using Newtonsoft.Json; - - [ExcludeFromCodeCoverage] - public class DiagnosticsViewModel - { - public DiagnosticsViewModel(AuthenticateResult result) - { - this.AuthenticateResult = result; - - if (result.Properties.Items.ContainsKey("client_list")) - { - String encoded = result.Properties.Items["client_list"]; - Byte[] bytes = Base64Url.Decode(encoded); - String value = Encoding.UTF8.GetString(bytes); - - this.Clients = JsonConvert.DeserializeObject(value); - } - } - - public AuthenticateResult AuthenticateResult { get; } - public IEnumerable Clients { get; } = new List(); - } -} \ No newline at end of file diff --git a/SecurityService/ViewModels/ErrorViewModel.cs b/SecurityService/ViewModels/ErrorViewModel.cs deleted file mode 100644 index 2af403c9..00000000 --- a/SecurityService/ViewModels/ErrorViewModel.cs +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright (c) Brock Allen & Dominick Baier. All rights reserved. -// Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information. - -namespace SecurityService.ViewModels -{ - using System.Diagnostics.CodeAnalysis; - using IdentityServer4.Models; - - [ExcludeFromCodeCoverage] - public class ErrorViewModel - { - public ErrorViewModel() - { - } - - public ErrorViewModel(string error) - { - this.Error = new ErrorMessage { Error = error }; - } - - public ErrorMessage Error { get; set; } - } -} \ No newline at end of file diff --git a/SecurityService/ViewModels/ExternalProvider.cs b/SecurityService/ViewModels/ExternalProvider.cs deleted file mode 100644 index 11b85e8d..00000000 --- a/SecurityService/ViewModels/ExternalProvider.cs +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright (c) Brock Allen & Dominick Baier. All rights reserved. -// Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information. - - -namespace SecurityService.ViewModels -{ - using System.Diagnostics.CodeAnalysis; - - [ExcludeFromCodeCoverage] - public class ExternalProvider - { - public string DisplayName { get; set; } - public string AuthenticationScheme { get; set; } - } -} \ No newline at end of file diff --git a/SecurityService/ViewModels/GrantViewModel.cs b/SecurityService/ViewModels/Grants/GrantsViewModel.cs similarity index 61% rename from SecurityService/ViewModels/GrantViewModel.cs rename to SecurityService/ViewModels/Grants/GrantsViewModel.cs index 40412164..d7b40091 100644 --- a/SecurityService/ViewModels/GrantViewModel.cs +++ b/SecurityService/ViewModels/Grants/GrantsViewModel.cs @@ -1,10 +1,17 @@ -namespace SecurityService.ViewModels +// Copyright (c) Duende Software. All rights reserved. +// See LICENSE in the project root for license information. + + +using System; +using System.Collections.Generic; + +namespace IdentityServerHost.Quickstart.UI { - using System; - using System.Collections.Generic; - using System.Diagnostics.CodeAnalysis; + public class GrantsViewModel + { + public IEnumerable Grants { get; set; } + } - [ExcludeFromCodeCoverage] public class GrantViewModel { public string ClientId { get; set; } diff --git a/SecurityService/ViewModels/GrantsViewModel.cs b/SecurityService/ViewModels/GrantsViewModel.cs deleted file mode 100644 index e000c627..00000000 --- a/SecurityService/ViewModels/GrantsViewModel.cs +++ /dev/null @@ -1,14 +0,0 @@ -// Copyright (c) Brock Allen & Dominick Baier. All rights reserved. -// Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information. - -namespace SecurityService.ViewModels -{ - using System.Collections.Generic; - using System.Diagnostics.CodeAnalysis; - - [ExcludeFromCodeCoverage] - public class GrantsViewModel - { - public IEnumerable Grants { get; set; } - } -} \ No newline at end of file diff --git a/SecurityService/ViewModels/Home/ErrorViewModel.cs b/SecurityService/ViewModels/Home/ErrorViewModel.cs new file mode 100644 index 00000000..349bd503 --- /dev/null +++ b/SecurityService/ViewModels/Home/ErrorViewModel.cs @@ -0,0 +1,22 @@ +// Copyright (c) Duende Software. All rights reserved. +// See LICENSE in the project root for license information. + + +using Duende.IdentityServer.Models; + +namespace IdentityServerHost.Quickstart.UI +{ + public class ErrorViewModel + { + public ErrorViewModel() + { + } + + public ErrorViewModel(string error) + { + Error = new ErrorMessage { Error = error }; + } + + public ErrorMessage Error { get; set; } + } +} \ No newline at end of file diff --git a/SecurityService/ViewModels/LoginInputModel.cs b/SecurityService/ViewModels/LoginInputModel.cs deleted file mode 100644 index dcab53dd..00000000 --- a/SecurityService/ViewModels/LoginInputModel.cs +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright (c) Brock Allen & Dominick Baier. All rights reserved. -// Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information. - -namespace SecurityService.ViewModels -{ - using System.ComponentModel.DataAnnotations; - using System.Diagnostics.CodeAnalysis; - - [ExcludeFromCodeCoverage] - public class LoginInputModel - { - [Required] - public string Username { get; set; } - [Required] - public string Password { get; set; } - public bool RememberLogin { get; set; } - public string ReturnUrl { get; set; } - } -} \ No newline at end of file diff --git a/SecurityService/ViewModels/LoginViewModel.cs b/SecurityService/ViewModels/LoginViewModel.cs deleted file mode 100644 index b429f5f0..00000000 --- a/SecurityService/ViewModels/LoginViewModel.cs +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright (c) Brock Allen & Dominick Baier. All rights reserved. -// Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information. - -namespace SecurityService.ViewModels -{ - using System; - using System.Collections.Generic; - using System.Diagnostics.CodeAnalysis; - using System.Linq; - - [ExcludeFromCodeCoverage] - public class LoginViewModel : LoginInputModel - { - public bool AllowRememberLogin { get; set; } = true; - public bool EnableLocalLogin { get; set; } = true; - - public IEnumerable ExternalProviders { get; set; } = Enumerable.Empty(); - public IEnumerable VisibleExternalProviders => this.ExternalProviders.Where(x => !String.IsNullOrWhiteSpace(x.DisplayName)); - - public bool IsExternalLoginOnly => this.EnableLocalLogin == false && this.ExternalProviders?.Count() == 1; - public string ExternalLoginScheme => this.IsExternalLoginOnly ? this.ExternalProviders?.SingleOrDefault()?.AuthenticationScheme : null; - } -} \ No newline at end of file diff --git a/SecurityService/ViewModels/LogoutInputModel.cs b/SecurityService/ViewModels/LogoutInputModel.cs deleted file mode 100644 index 6205156b..00000000 --- a/SecurityService/ViewModels/LogoutInputModel.cs +++ /dev/null @@ -1,14 +0,0 @@ -// Copyright (c) Brock Allen & Dominick Baier. All rights reserved. -// Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information. - - -namespace SecurityService.ViewModels -{ - using System.Diagnostics.CodeAnalysis; - - [ExcludeFromCodeCoverage] - public class LogoutInputModel - { - public string LogoutId { get; set; } - } -} diff --git a/SecurityService/ViewModels/LogoutViewModel.cs b/SecurityService/ViewModels/LogoutViewModel.cs deleted file mode 100644 index 9b68c0e6..00000000 --- a/SecurityService/ViewModels/LogoutViewModel.cs +++ /dev/null @@ -1,14 +0,0 @@ -// Copyright (c) Brock Allen & Dominick Baier. All rights reserved. -// Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information. - - -namespace SecurityService.ViewModels -{ - using System.Diagnostics.CodeAnalysis; - - [ExcludeFromCodeCoverage] - public class LogoutViewModel : LogoutInputModel - { - public bool ShowLogoutPrompt { get; set; } = true; - } -} diff --git a/SecurityService/ViewModels/RedirectViewModel.cs b/SecurityService/ViewModels/RedirectViewModel.cs deleted file mode 100644 index 68e4d9d3..00000000 --- a/SecurityService/ViewModels/RedirectViewModel.cs +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright (c) Brock Allen & Dominick Baier. All rights reserved. -// Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information. - - - -namespace SecurityService.ViewModels -{ - using System.Diagnostics.CodeAnalysis; - - [ExcludeFromCodeCoverage] - public class RedirectViewModel - { - public string RedirectUrl { get; set; } - } -} \ No newline at end of file diff --git a/SecurityService/Views/Account/LoggedOut.cshtml b/SecurityService/Views/Account/LoggedOut.cshtml index c3bac3a9..dc9fbf7a 100644 --- a/SecurityService/Views/Account/LoggedOut.cshtml +++ b/SecurityService/Views/Account/LoggedOut.cshtml @@ -1,4 +1,4 @@ -@model SecurityService.ViewModels.LoggedOutViewModel +@model LoggedOutViewModel @{ // set this so the layout rendering sees an anonymous user diff --git a/SecurityService/Views/Account/Login.cshtml b/SecurityService/Views/Account/Login.cshtml index ff9689f2..e4ccb1d8 100644 --- a/SecurityService/Views/Account/Login.cshtml +++ b/SecurityService/Views/Account/Login.cshtml @@ -1,4 +1,4 @@ -@model SecurityService.ViewModels.LoginViewModel +@model LoginViewModel