├── .gitignore ├── IdentityServerAngularImplicitFlow.sln ├── README.md ├── docker-compose.ci.build.yml ├── docker-compose.dcproj ├── docker-compose.override.yml ├── docker-compose.vs.debug.yml ├── docker-compose.vs.release.yml ├── docker-compose.yml └── src ├── Angular2Client ├── .dockerignore ├── Angular2Client.csproj ├── Dockerfile ├── Properties │ └── launchSettings.json ├── Startup.cs ├── angular2App │ ├── app │ │ ├── app.component.css │ │ ├── app.component.html │ │ ├── app.component.ts │ │ ├── app.constants.ts │ │ ├── app.module.ts │ │ ├── app.routes.ts │ │ ├── dataeventrecords │ │ │ ├── DataEventRecordsService.ts │ │ │ ├── dataeventrecords-create.component.html │ │ │ ├── dataeventrecords-create.component.ts │ │ │ ├── dataeventrecords-edit.component.html │ │ │ ├── dataeventrecords-edit.component.ts │ │ │ ├── dataeventrecords-list.component.html │ │ │ ├── dataeventrecords-list.component.ts │ │ │ ├── dataeventrecords.routes.ts │ │ │ └── models │ │ │ │ └── DataEventRecord.ts │ │ ├── forbidden │ │ │ ├── forbidden.component.html │ │ │ └── forbidden.component.ts │ │ ├── home │ │ │ ├── home.component.html │ │ │ └── home.component.ts │ │ ├── securefile │ │ │ ├── SecureFileService.ts │ │ │ ├── securefiles.component.html │ │ │ └── securefiles.component.ts │ │ ├── services │ │ │ └── SecurityService.ts │ │ └── unauthorized │ │ │ ├── unauthorized.component.html │ │ │ └── unauthorized.component.ts │ ├── css │ │ ├── bootstrap-theme.css │ │ ├── bootstrap-theme.css.map │ │ ├── bootstrap-theme.min.css │ │ ├── bootstrap-theme.min.css.map │ │ ├── bootstrap.css │ │ ├── bootstrap.css.map │ │ ├── bootstrap.min.css │ │ └── bootstrap.min.css.map │ ├── fonts │ │ ├── glyphicons-halflings-regular.eot │ │ ├── glyphicons-halflings-regular.svg │ │ ├── glyphicons-halflings-regular.ttf │ │ ├── glyphicons-halflings-regular.woff │ │ └── glyphicons-halflings-regular.woff2 │ ├── images │ │ └── damienbod.jpg │ ├── index.html │ ├── main-aot.js │ ├── main-aot.ts │ ├── main.ts │ ├── polyfills.ts │ ├── style │ │ └── app.scss │ └── vendor.ts ├── appsettings.json ├── package.json ├── runtimeconfig.template.json ├── tsconfig-aot.json ├── tsconfig.json ├── tslint.json ├── web.config ├── webpack.config.js ├── webpack.dev.js ├── webpack.helpers.js └── webpack.prod.js ├── IdentityServerWithIdentitySQLite ├── .bowerrc ├── .dockerignore ├── Config.cs ├── Controllers │ ├── AccountController.cs │ ├── ConsentController.cs │ ├── HomeController.cs │ └── ManageController.cs ├── Data │ └── ApplicationDbContext.cs ├── Dockerfile ├── Filters │ └── SecurityHeadersAttribute.cs ├── IdentityServerWithIdentitySQLite.csproj ├── IdentityWithAdditionalClaimsProfileService.cs ├── Migrations │ ├── 20160913105714_identityUsers.Designer.cs │ ├── 20160913105714_identityUsers.cs │ └── ApplicationDbContextModelSnapshot.cs ├── Models │ ├── AccountViewModels │ │ ├── ExternalLoginConfirmationViewModel.cs │ │ ├── ForgotPasswordViewModel.cs │ │ ├── LoggedOutViewModel.cs │ │ ├── LoginInputModel.cs │ │ ├── LoginViewModel.cs │ │ ├── LogoutViewModel.cs │ │ ├── RegisterViewModel.cs │ │ ├── ResetPasswordViewModel.cs │ │ ├── SendCodeViewModel.cs │ │ └── VerifyCodeViewModel.cs │ ├── ApplicationUser.cs │ ├── ConsentInputModel.cs │ ├── ConsentViewModel.cs │ ├── ErrorViewModel.cs │ └── ManageViewModels │ │ ├── AddPhoneNumberViewModel.cs │ │ ├── ChangePasswordViewModel.cs │ │ ├── ConfigureTwoFactorViewModel.cs │ │ ├── FactorViewModel.cs │ │ ├── IndexViewModel.cs │ │ ├── ManageLoginsViewModel.cs │ │ ├── RemoveLoginViewModel.cs │ │ ├── SetPasswordViewModel.cs │ │ └── VerifyPhoneNumberViewModel.cs ├── Program.cs ├── Properties │ └── launchSettings.json ├── Services │ ├── IEmailSender.cs │ ├── ISmsSender.cs │ └── MessageServices.cs ├── Startup.cs ├── Views │ ├── Account │ │ ├── ConfirmEmail.cshtml │ │ ├── ExternalLoginConfirmation.cshtml │ │ ├── ExternalLoginFailure.cshtml │ │ ├── ForgotPassword.cshtml │ │ ├── ForgotPasswordConfirmation.cshtml │ │ ├── Lockout.cshtml │ │ ├── LoggedOut.cshtml │ │ ├── Login.cshtml │ │ ├── Logout.cshtml │ │ ├── Register.cshtml │ │ ├── ResetPassword.cshtml │ │ ├── ResetPasswordConfirmation.cshtml │ │ ├── SendCode.cshtml │ │ └── VerifyCode.cshtml │ ├── Consent │ │ ├── Index.cshtml │ │ └── _ScopeListItem.cshtml │ ├── Home │ │ ├── About.cshtml │ │ ├── Contact.cshtml │ │ └── Index.cshtml │ ├── Manage │ │ ├── AddPhoneNumber.cshtml │ │ ├── ChangePassword.cshtml │ │ ├── Index.cshtml │ │ ├── ManageLogins.cshtml │ │ ├── SetPassword.cshtml │ │ └── VerifyPhoneNumber.cshtml │ ├── Shared │ │ ├── Error.cshtml │ │ ├── _Layout.cshtml │ │ ├── _LoginPartial.cshtml │ │ ├── _ValidationScriptsPartial.cshtml │ │ └── _ValidationSummary.cshtml │ ├── _ViewImports.cshtml │ └── _ViewStart.cshtml ├── appsettings.json ├── bower.json ├── bundleconfig.json ├── damienbodserver.pfx ├── runtimeconfig.template.json ├── usersdatabase.sqlite ├── web.config └── wwwroot │ ├── _references.js │ ├── css │ ├── site.css │ └── site.min.css │ ├── favicon.ico │ ├── images │ ├── banner1.svg │ ├── banner2.svg │ ├── banner3.svg │ └── banner4.svg │ ├── js │ ├── site.js │ └── site.min.js │ └── lib │ ├── bootstrap │ ├── .bower.json │ ├── LICENSE │ └── dist │ │ ├── css │ │ ├── bootstrap-theme.min.css.map │ │ └── bootstrap.min.css.map │ │ ├── fonts │ │ ├── glyphicons-halflings-regular.eot │ │ ├── glyphicons-halflings-regular.svg │ │ ├── glyphicons-halflings-regular.ttf │ │ ├── glyphicons-halflings-regular.woff │ │ └── glyphicons-halflings-regular.woff2 │ │ └── js │ │ ├── bootstrap.min.js │ │ └── npm.js │ ├── jquery-validation-unobtrusive │ ├── jquery.validate.unobtrusive.js │ └── jquery.validate.unobtrusive.min.js │ ├── jquery-validation │ └── dist │ │ ├── additional-methods.js │ │ ├── additional-methods.min.js │ │ └── jquery.validate.min.js │ └── jquery │ └── dist │ ├── jquery.min.js │ └── jquery.min.map ├── ResourceFileServer ├── .dockerignore ├── Controllers │ ├── DownloadController.cs │ └── FileExplorerController.cs ├── Dockerfile ├── Properties │ └── launchSettings.json ├── Providers │ ├── ISecuredFileProvider.cs │ ├── SecureRandom.cs │ ├── SecuredFileProvider.cs │ ├── UseOnceAccessId.cs │ └── UseOnceAccessIdService.cs ├── ResourceFileServer.csproj ├── SecuredFileShare │ ├── SecureFile.txt │ ├── SecureFileAdmin.txt │ └── SecureFileTwo.txt ├── Startup.cs ├── appsettings.json ├── runtimeconfig.template.json └── web.config └── ResourceServer ├── .dockerignore ├── Controllers └── DataEventRecordController.cs ├── Dockerfile ├── Migrations ├── 20160521184959_testMigrations.Designer.cs ├── 20160521184959_testMigrations.cs └── DataEventRecordContextModelSnapshot.cs ├── Model ├── DataEventRecord.cs └── DataEventRecordContext.cs ├── Program.cs ├── Properties └── launchSettings.json ├── Repositories ├── DataEventRecordRepository.cs └── IDataEventRecordRepository.cs ├── ResourceServer.csproj ├── Startup.cs ├── config.json ├── damienbodserver.pfx ├── dataeventrecords.sqlite ├── runtimeconfig.template.json └── web.config /IdentityServerAngularImplicitFlow.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.26127.3 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{A0F6C07F-188D-4F86-B43F-4A3EAD0D2C30}" 7 | EndProject 8 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ResourceServer", "src\ResourceServer\ResourceServer.csproj", "{27CE53A6-EEEF-4CC8-A463-6915A5F3AFEA}" 9 | EndProject 10 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Angular2Client", "src\Angular2Client\Angular2Client.csproj", "{1C83BAC6-1A38-4261-8BE4-7B0FC9A286B8}" 11 | EndProject 12 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ResourceFileServer", "src\ResourceFileServer\ResourceFileServer.csproj", "{3F42D8EE-5E25-443D-8EDD-FA950E63A1D3}" 13 | EndProject 14 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "IdentityServerWithIdentitySQLite", "src\IdentityServerWithIdentitySQLite\IdentityServerWithIdentitySQLite.csproj", "{1ECB5581-FFA5-4C11-A491-C85ABD962033}" 15 | EndProject 16 | Project("{E53339B2-1760-4266-BCC7-CA923CBCF16C}") = "docker-compose", "docker-compose.dcproj", "{0A2C7E3B-C4C9-433C-B97F-184DA355B9E1}" 17 | EndProject 18 | Global 19 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 20 | Debug|Any CPU = Debug|Any CPU 21 | Release|Any CPU = Release|Any CPU 22 | EndGlobalSection 23 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 24 | {27CE53A6-EEEF-4CC8-A463-6915A5F3AFEA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 25 | {27CE53A6-EEEF-4CC8-A463-6915A5F3AFEA}.Debug|Any CPU.Build.0 = Debug|Any CPU 26 | {27CE53A6-EEEF-4CC8-A463-6915A5F3AFEA}.Release|Any CPU.ActiveCfg = Release|Any CPU 27 | {27CE53A6-EEEF-4CC8-A463-6915A5F3AFEA}.Release|Any CPU.Build.0 = Release|Any CPU 28 | {1C83BAC6-1A38-4261-8BE4-7B0FC9A286B8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 29 | {1C83BAC6-1A38-4261-8BE4-7B0FC9A286B8}.Debug|Any CPU.Build.0 = Debug|Any CPU 30 | {1C83BAC6-1A38-4261-8BE4-7B0FC9A286B8}.Release|Any CPU.ActiveCfg = Release|Any CPU 31 | {1C83BAC6-1A38-4261-8BE4-7B0FC9A286B8}.Release|Any CPU.Build.0 = Release|Any CPU 32 | {3F42D8EE-5E25-443D-8EDD-FA950E63A1D3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 33 | {3F42D8EE-5E25-443D-8EDD-FA950E63A1D3}.Debug|Any CPU.Build.0 = Debug|Any CPU 34 | {3F42D8EE-5E25-443D-8EDD-FA950E63A1D3}.Release|Any CPU.ActiveCfg = Release|Any CPU 35 | {3F42D8EE-5E25-443D-8EDD-FA950E63A1D3}.Release|Any CPU.Build.0 = Release|Any CPU 36 | {1ECB5581-FFA5-4C11-A491-C85ABD962033}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 37 | {1ECB5581-FFA5-4C11-A491-C85ABD962033}.Debug|Any CPU.Build.0 = Debug|Any CPU 38 | {1ECB5581-FFA5-4C11-A491-C85ABD962033}.Release|Any CPU.ActiveCfg = Release|Any CPU 39 | {1ECB5581-FFA5-4C11-A491-C85ABD962033}.Release|Any CPU.Build.0 = Release|Any CPU 40 | {0A2C7E3B-C4C9-433C-B97F-184DA355B9E1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 41 | {0A2C7E3B-C4C9-433C-B97F-184DA355B9E1}.Debug|Any CPU.Build.0 = Debug|Any CPU 42 | {0A2C7E3B-C4C9-433C-B97F-184DA355B9E1}.Release|Any CPU.ActiveCfg = Release|Any CPU 43 | {0A2C7E3B-C4C9-433C-B97F-184DA355B9E1}.Release|Any CPU.Build.0 = Release|Any CPU 44 | EndGlobalSection 45 | GlobalSection(SolutionProperties) = preSolution 46 | HideSolutionNode = FALSE 47 | EndGlobalSection 48 | GlobalSection(NestedProjects) = preSolution 49 | {27CE53A6-EEEF-4CC8-A463-6915A5F3AFEA} = {A0F6C07F-188D-4F86-B43F-4A3EAD0D2C30} 50 | {1C83BAC6-1A38-4261-8BE4-7B0FC9A286B8} = {A0F6C07F-188D-4F86-B43F-4A3EAD0D2C30} 51 | {3F42D8EE-5E25-443D-8EDD-FA950E63A1D3} = {A0F6C07F-188D-4F86-B43F-4A3EAD0D2C30} 52 | {1ECB5581-FFA5-4C11-A491-C85ABD962033} = {A0F6C07F-188D-4F86-B43F-4A3EAD0D2C30} 53 | EndGlobalSection 54 | EndGlobal 55 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ASP.NET Core 1.1, IdentityServer4, Angular, Visual Studio 2017 msbuild csproj 2 | -------------------------------------------------------------------------------- /docker-compose.ci.build.yml: -------------------------------------------------------------------------------- 1 | version: '2' 2 | 3 | services: 4 | ci-build: 5 | image: microsoft/aspnetcore-build:1.0.3-msbuild 6 | volumes: 7 | - .:/src 8 | working_dir: /src 9 | command: /bin/bash -c "dotnet restore && dotnet publish -c Release -o ./obj/Docker/publish" 10 | -------------------------------------------------------------------------------- /docker-compose.dcproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 0a2c7e3b-c4c9-433c-b97f-184da355b9e1 5 | 6 | 7 | 8 | 9 | docker-compose.yml 10 | 11 | 12 | docker-compose.yml 13 | 14 | 15 | docker-compose.yml 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /docker-compose.override.yml: -------------------------------------------------------------------------------- 1 | version: '2' 2 | 3 | services: 4 | identityserverwithidentitysqlite: 5 | environment: 6 | - ASPNETCORE_ENVIRONMENT=Development 7 | ports: 8 | - "80" 9 | 10 | resourcefileserver: 11 | environment: 12 | - ASPNETCORE_ENVIRONMENT=Development 13 | ports: 14 | - "80" 15 | 16 | resourceserver: 17 | environment: 18 | - ASPNETCORE_ENVIRONMENT=Development 19 | ports: 20 | - "80" 21 | 22 | angular2client: 23 | environment: 24 | - ASPNETCORE_ENVIRONMENT=Development 25 | ports: 26 | - "80" 27 | -------------------------------------------------------------------------------- /docker-compose.vs.debug.yml: -------------------------------------------------------------------------------- 1 | version: '2' 2 | 3 | services: 4 | identityserverwithidentitysqlite: 5 | image: identityserverwithidentitysqlite:dev 6 | build: 7 | args: 8 | source: ${DOCKER_BUILD_SOURCE} 9 | environment: 10 | - DOTNET_USE_POLLING_FILE_WATCHER=1 11 | volumes: 12 | - ./src/IdentityServerWithIdentitySQLite:/app 13 | - ~/.nuget/packages:/root/.nuget/packages:ro 14 | - ~/clrdbg:/clrdbg:ro 15 | entrypoint: tail -f /dev/null 16 | labels: 17 | - "com.microsoft.visualstudio.targetoperatingsystem=linux" 18 | 19 | resourcefileserver: 20 | image: resourcefileserver:dev 21 | build: 22 | args: 23 | source: ${DOCKER_BUILD_SOURCE} 24 | environment: 25 | - DOTNET_USE_POLLING_FILE_WATCHER=1 26 | volumes: 27 | - ./src/ResourceFileServer:/app 28 | - ~/.nuget/packages:/root/.nuget/packages:ro 29 | - ~/clrdbg:/clrdbg:ro 30 | entrypoint: tail -f /dev/null 31 | labels: 32 | - "com.microsoft.visualstudio.targetoperatingsystem=linux" 33 | 34 | resourceserver: 35 | image: resourceserver:dev 36 | build: 37 | args: 38 | source: ${DOCKER_BUILD_SOURCE} 39 | environment: 40 | - DOTNET_USE_POLLING_FILE_WATCHER=1 41 | volumes: 42 | - ./src/ResourceServer:/app 43 | - ~/.nuget/packages:/root/.nuget/packages:ro 44 | - ~/clrdbg:/clrdbg:ro 45 | entrypoint: tail -f /dev/null 46 | labels: 47 | - "com.microsoft.visualstudio.targetoperatingsystem=linux" 48 | 49 | angular2client: 50 | image: angular2client:dev 51 | build: 52 | args: 53 | source: ${DOCKER_BUILD_SOURCE} 54 | environment: 55 | - DOTNET_USE_POLLING_FILE_WATCHER=1 56 | volumes: 57 | - ./src/Angular2Client:/app 58 | - ~/.nuget/packages:/root/.nuget/packages:ro 59 | - ~/clrdbg:/clrdbg:ro 60 | entrypoint: tail -f /dev/null 61 | labels: 62 | - "com.microsoft.visualstudio.targetoperatingsystem=linux" 63 | -------------------------------------------------------------------------------- /docker-compose.vs.release.yml: -------------------------------------------------------------------------------- 1 | version: '2' 2 | 3 | services: 4 | identityserverwithidentitysqlite: 5 | build: 6 | args: 7 | source: ${DOCKER_BUILD_SOURCE} 8 | volumes: 9 | - ~/clrdbg:/clrdbg:ro 10 | entrypoint: tail -f /dev/null 11 | labels: 12 | - "com.microsoft.visualstudio.targetoperatingsystem=linux" 13 | 14 | resourcefileserver: 15 | build: 16 | args: 17 | source: ${DOCKER_BUILD_SOURCE} 18 | volumes: 19 | - ~/clrdbg:/clrdbg:ro 20 | entrypoint: tail -f /dev/null 21 | labels: 22 | - "com.microsoft.visualstudio.targetoperatingsystem=linux" 23 | 24 | resourceserver: 25 | build: 26 | args: 27 | source: ${DOCKER_BUILD_SOURCE} 28 | volumes: 29 | - ~/clrdbg:/clrdbg:ro 30 | entrypoint: tail -f /dev/null 31 | labels: 32 | - "com.microsoft.visualstudio.targetoperatingsystem=linux" 33 | 34 | angular2client: 35 | build: 36 | args: 37 | source: ${DOCKER_BUILD_SOURCE} 38 | volumes: 39 | - ~/clrdbg:/clrdbg:ro 40 | entrypoint: tail -f /dev/null 41 | labels: 42 | - "com.microsoft.visualstudio.targetoperatingsystem=linux" 43 | -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '2' 2 | 3 | services: 4 | identityserverwithidentitysqlite: 5 | image: identityserverwithidentitysqlite 6 | build: 7 | context: ./src/IdentityServerWithIdentitySQLite 8 | dockerfile: Dockerfile 9 | 10 | resourcefileserver: 11 | image: resourcefileserver 12 | build: 13 | context: ./src/ResourceFileServer 14 | dockerfile: Dockerfile 15 | 16 | resourceserver: 17 | image: resourceserver 18 | build: 19 | context: ./src/ResourceServer 20 | dockerfile: Dockerfile 21 | 22 | angular2client: 23 | image: angular2client 24 | build: 25 | context: ./src/Angular2Client 26 | dockerfile: Dockerfile 27 | -------------------------------------------------------------------------------- /src/Angular2Client/.dockerignore: -------------------------------------------------------------------------------- 1 | * 2 | !obj/Docker/publish/* 3 | !obj/Docker/empty/ 4 | -------------------------------------------------------------------------------- /src/Angular2Client/Angular2Client.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | netcoreapp1.1 4 | true 5 | Angular2Client 6 | Exe 7 | Angular2Client 8 | $(PackageTargetFallback);dotnet5.6;portable-net45+win8 9 | aspnet-Angular2Client-1e7bf5d8-6c32-4dd3-b77d-2d7d2e0f5091 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /src/Angular2Client/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM microsoft/aspnetcore:1.1 2 | ARG source 3 | WORKDIR /app 4 | EXPOSE 80 5 | COPY ${source:-obj/Docker/publish} . 6 | ENTRYPOINT ["dotnet", "Angular2Client.dll"] 7 | -------------------------------------------------------------------------------- /src/Angular2Client/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "iisSettings": { 3 | "windowsAuthentication": false, 4 | "anonymousAuthentication": true, 5 | "iisExpress": { 6 | "applicationUrl": "https://localhost:44311/", 7 | "sslPort": 44311 8 | } 9 | }, 10 | "profiles": { 11 | "IIS Express": { 12 | "commandName": "IISExpress", 13 | "launchBrowser": true, 14 | "environmentVariables": { 15 | "Hosting:Environment": "Development" 16 | } 17 | }, 18 | "web": { 19 | "commandName": "web", 20 | "environmentVariables": { 21 | "Hosting:Environment": "Development" 22 | } 23 | } 24 | } 25 | } -------------------------------------------------------------------------------- /src/Angular2Client/Startup.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Builder; 2 | using Microsoft.AspNetCore.Hosting; 3 | using Microsoft.Extensions.Configuration; 4 | using Microsoft.Extensions.DependencyInjection; 5 | using Microsoft.Extensions.Logging; 6 | using System.IO; 7 | using Microsoft.AspNetCore.Http; 8 | using System.Linq; 9 | using System; 10 | 11 | namespace Angular2Client 12 | { 13 | public class Startup 14 | { 15 | public Startup(IHostingEnvironment env) 16 | { 17 | var builder = new ConfigurationBuilder() 18 | .SetBasePath(env.ContentRootPath) 19 | .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true) 20 | .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true) 21 | .AddEnvironmentVariables(); 22 | Configuration = builder.Build(); 23 | } 24 | 25 | public IConfigurationRoot Configuration { get; set; } 26 | 27 | public void ConfigureServices(IServiceCollection services) 28 | { 29 | } 30 | 31 | public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory) 32 | { 33 | loggerFactory.AddConsole(Configuration.GetSection("Logging")); 34 | loggerFactory.AddDebug(); 35 | 36 | var angularRoutes = new[] { 37 | "/home", 38 | "/forbidden", 39 | "/authorized", 40 | "/authorize", 41 | "/unauthorized", 42 | "/dataeventrecords", 43 | "/dataeventrecords/create", 44 | "/dataeventrecords/edit", 45 | "/logoff", 46 | "/securefile", 47 | "/securefile/securefiles", 48 | }; 49 | 50 | app.Use(async (context, next) => 51 | { 52 | if (context.Request.Path.HasValue && null != angularRoutes.FirstOrDefault( 53 | (ar) => context.Request.Path.Value.StartsWith(ar, StringComparison.OrdinalIgnoreCase))) 54 | { 55 | context.Request.Path = new PathString("/"); 56 | } 57 | 58 | await next(); 59 | }); 60 | 61 | app.UseDefaultFiles(); 62 | app.UseStaticFiles(); 63 | 64 | app.Run(async (context) => 65 | { 66 | await context.Response.WriteAsync("This is server routing, not angular2 routing"); 67 | }); 68 | } 69 | 70 | public static void Main(string[] args) 71 | { 72 | var host = new WebHostBuilder() 73 | .UseKestrel() 74 | .UseContentRoot(Directory.GetCurrentDirectory()) 75 | .UseIISIntegration() 76 | .UseStartup() 77 | .Build(); 78 | 79 | host.Run(); 80 | } 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /src/Angular2Client/angular2App/app/app.component.css: -------------------------------------------------------------------------------- 1 | body { 2 | padding-top: 50px; 3 | } 4 | 5 | .starter-template { 6 | padding: 40px 15px; 7 | text-align: center; 8 | } 9 | 10 | .navigationLinkButton:hover { 11 | cursor: pointer; 12 | } -------------------------------------------------------------------------------- /src/Angular2Client/angular2App/app/app.component.html: -------------------------------------------------------------------------------- 1 |
2 | 3 | 27 | 28 | 29 | 30 |
31 | 32 | 33 | -------------------------------------------------------------------------------- /src/Angular2Client/angular2App/app/app.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | import { Router } from '@angular/router'; 3 | 4 | import { Configuration } from './app.constants'; 5 | 6 | import { SecurityService } from './services/SecurityService'; 7 | import { SecureFileService } from './securefile/SecureFileService'; 8 | import { DataEventRecordsService } from './dataeventrecords/DataEventRecordsService'; 9 | import { DataEventRecord } from './dataeventrecords/models/DataEventRecord'; 10 | 11 | import { ForbiddenComponent } from './forbidden/forbidden.component'; 12 | import { HomeComponent } from './home/home.component'; 13 | import { UnauthorizedComponent } from './unauthorized/unauthorized.component'; 14 | import { SecureFilesComponent } from './securefile/securefiles.component'; 15 | 16 | import { DataEventRecordsListComponent } from './dataeventrecords/dataeventrecords-list.component'; 17 | import { DataEventRecordsCreateComponent } from './dataeventrecords/dataeventrecords-create.component'; 18 | import { DataEventRecordsEditComponent } from './dataeventrecords/dataeventrecords-edit.component'; 19 | 20 | import './app.component.css'; 21 | 22 | @Component({ 23 | selector: 'my-app', 24 | templateUrl: 'app.component.html' 25 | }) 26 | 27 | export class AppComponent implements OnInit { 28 | 29 | constructor(public securityService: SecurityService) { 30 | } 31 | 32 | ngOnInit() { 33 | console.log('ngOnInit _securityService.AuthorizedCallback'); 34 | 35 | if (window.location.hash) { 36 | this.securityService.AuthorizedCallback(); 37 | } 38 | } 39 | 40 | public Login() { 41 | console.log('Do login logic'); 42 | this.securityService.Authorize(); 43 | } 44 | 45 | public Logout() { 46 | console.log('Do logout logic'); 47 | this.securityService.Logoff(); 48 | } 49 | } -------------------------------------------------------------------------------- /src/Angular2Client/angular2App/app/app.constants.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@angular/core'; 2 | 3 | @Injectable() 4 | export class Configuration { 5 | public Server = 'https://localhost:44390/'; 6 | public FileServer: string = 'https://localhost:44378/'; 7 | } -------------------------------------------------------------------------------- /src/Angular2Client/angular2App/app/app.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { FormsModule } from '@angular/forms'; 3 | import { BrowserModule } from '@angular/platform-browser'; 4 | 5 | import { AppComponent } from './app.component'; 6 | import { Configuration } from './app.constants'; 7 | import { routing } from './app.routes'; 8 | import { HttpModule, JsonpModule } from '@angular/http'; 9 | 10 | import { SecurityService } from './services/SecurityService'; 11 | import { SecureFileService } from './securefile/SecureFileService'; 12 | import { DataEventRecordsService } from './dataeventrecords/DataEventRecordsService'; 13 | import { DataEventRecord } from './dataeventrecords/models/DataEventRecord'; 14 | 15 | import { ForbiddenComponent } from './forbidden/forbidden.component'; 16 | import { HomeComponent } from './home/home.component'; 17 | import { UnauthorizedComponent } from './unauthorized/unauthorized.component'; 18 | import { SecureFilesComponent } from './securefile/securefiles.component'; 19 | 20 | import { DataEventRecordsListComponent } from './dataeventrecords/dataeventrecords-list.component'; 21 | import { DataEventRecordsCreateComponent } from './dataeventrecords/dataeventrecords-create.component'; 22 | import { DataEventRecordsEditComponent } from './dataeventrecords/dataeventrecords-edit.component'; 23 | 24 | @NgModule({ 25 | imports: [ 26 | BrowserModule, 27 | FormsModule, 28 | routing, 29 | HttpModule, 30 | JsonpModule 31 | ], 32 | declarations: [ 33 | AppComponent, 34 | ForbiddenComponent, 35 | HomeComponent, 36 | UnauthorizedComponent, 37 | SecureFilesComponent, 38 | DataEventRecordsListComponent, 39 | DataEventRecordsCreateComponent, 40 | DataEventRecordsEditComponent 41 | ], 42 | providers: [ 43 | SecurityService, 44 | SecureFileService, 45 | DataEventRecordsService, 46 | Configuration 47 | ], 48 | bootstrap: [AppComponent], 49 | }) 50 | 51 | export class AppModule {} -------------------------------------------------------------------------------- /src/Angular2Client/angular2App/app/app.routes.ts: -------------------------------------------------------------------------------- 1 | import { Routes, RouterModule } from '@angular/router'; 2 | 3 | import { ForbiddenComponent } from './forbidden/forbidden.component'; 4 | import { HomeComponent } from './home/home.component'; 5 | import { UnauthorizedComponent } from './unauthorized/unauthorized.component'; 6 | import { SecureFilesComponent } from './securefile/securefiles.component'; 7 | 8 | import { DATA_RECORDS_ROUTES } from './dataeventrecords/dataeventrecords.routes'; 9 | 10 | import { DataEventRecordsListComponent } from './dataeventrecords/dataeventrecords-list.component'; 11 | import { DataEventRecordsCreateComponent } from './dataeventrecords/dataeventrecords-create.component'; 12 | import { DataEventRecordsEditComponent } from './dataeventrecords/dataeventrecords-edit.component'; 13 | 14 | const appRoutes: Routes = [ 15 | { path: '', component: HomeComponent }, 16 | { path: 'home', component: HomeComponent }, 17 | { path: 'Forbidden', component: ForbiddenComponent }, 18 | { path: 'Unauthorized', component: UnauthorizedComponent }, 19 | { path: 'securefile/securefiles', component: SecureFilesComponent }, 20 | ...DATA_RECORDS_ROUTES, 21 | ]; 22 | 23 | export const routing = RouterModule.forRoot(appRoutes); 24 | -------------------------------------------------------------------------------- /src/Angular2Client/angular2App/app/dataeventrecords/DataEventRecordsService.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@angular/core'; 2 | import { Http, Response, Headers, RequestOptions } from '@angular/http'; 3 | import 'rxjs/add/operator/map'; 4 | import { Observable } from 'rxjs/Observable'; 5 | import { Configuration } from '../app.constants'; 6 | import { SecurityService } from '../services/SecurityService'; 7 | import { DataEventRecord } from './models/DataEventRecord'; 8 | 9 | @Injectable() 10 | export class DataEventRecordsService { 11 | 12 | private actionUrl: string; 13 | private headers: Headers; 14 | 15 | constructor(private _http: Http, private _configuration: Configuration, private _securityService: SecurityService) { 16 | this.actionUrl = `${_configuration.Server}api/DataEventRecords/`; 17 | } 18 | 19 | private setHeaders() { 20 | 21 | console.log('setHeaders started'); 22 | 23 | this.headers = new Headers(); 24 | this.headers.append('Content-Type', 'application/json'); 25 | this.headers.append('Accept', 'application/json'); 26 | 27 | let token = this._securityService.GetToken(); 28 | if (token !== '') { 29 | let tokenValue = 'Bearer ' + token; 30 | console.log('tokenValue:' + tokenValue); 31 | this.headers.append('Authorization', tokenValue); 32 | } 33 | } 34 | 35 | public GetAll = (): Observable => { 36 | this.setHeaders(); 37 | let options = new RequestOptions({ headers: this.headers, body: '' }); 38 | 39 | return this._http.get(this.actionUrl, options).map(res => res.json()); 40 | } 41 | 42 | public GetById = (id: number): Observable => { 43 | this.setHeaders(); 44 | return this._http.get(this.actionUrl + id, { 45 | headers: this.headers, 46 | body: '' 47 | }).map(res => res.json()); 48 | } 49 | 50 | public Add = (itemToAdd: any): Observable => { 51 | this.setHeaders(); 52 | return this._http.post(this.actionUrl, JSON.stringify(itemToAdd), { headers: this.headers }); 53 | } 54 | 55 | public Update = (id: number, itemToUpdate: any): Observable => { 56 | this.setHeaders(); 57 | return this._http 58 | .put(this.actionUrl + id, JSON.stringify(itemToUpdate), { headers: this.headers }); 59 | } 60 | 61 | public Delete = (id: number): Observable => { 62 | this.setHeaders(); 63 | return this._http.delete(this.actionUrl + id, { 64 | headers: this.headers 65 | }); 66 | } 67 | 68 | } -------------------------------------------------------------------------------- /src/Angular2Client/angular2App/app/dataeventrecords/dataeventrecords-create.component.html: -------------------------------------------------------------------------------- 1 |
2 |
3 | {{message}} 4 |
5 |
6 | 7 |
8 |
Id
9 |
10 |
11 | 12 |
13 |
14 |
Name
15 |
16 | 17 |
18 |
19 |
20 |
21 |
Description
22 |
23 | 24 |
25 |
26 |
27 |
28 |
29 | 30 |
31 |
32 |
33 |
34 | -------------------------------------------------------------------------------- /src/Angular2Client/angular2App/app/dataeventrecords/dataeventrecords-create.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | import { Router } from '@angular/router'; 3 | import { SecurityService } from '../services/SecurityService'; 4 | 5 | import { DataEventRecordsService } from '../dataeventrecords/DataEventRecordsService'; 6 | import { DataEventRecord } from './models/DataEventRecord'; 7 | 8 | @Component({ 9 | selector: 'dataeventrecords-create', 10 | templateUrl: 'dataeventrecords-create.component.html' 11 | }) 12 | 13 | export class DataEventRecordsCreateComponent implements OnInit { 14 | 15 | public message: string; 16 | public DataEventRecord: any; 17 | 18 | constructor(private _dataEventRecordsService: DataEventRecordsService, public securityService: SecurityService, private _router: Router) { 19 | this.message = 'DataEventRecords Create'; 20 | } 21 | 22 | ngOnInit() { 23 | this.DataEventRecord = { Id: 0, Name: '', Description: '' }; 24 | console.log('IsAuthorized:' + this.securityService.IsAuthorized); 25 | console.log('HasAdminRole:' + this.securityService.HasAdminRole); 26 | } 27 | 28 | public Create() { 29 | // router navigate to DataEventRecordsList 30 | this._dataEventRecordsService 31 | .Add(this.DataEventRecord) 32 | .subscribe((data: any) => this.DataEventRecord = data, 33 | error => this.securityService.HandleError(error), 34 | () => this._router.navigate(['/dataeventrecords'])); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/Angular2Client/angular2App/app/dataeventrecords/dataeventrecords-edit.component.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 |

{{message}}

5 |
6 |
7 |
8 |
9 |
Id
10 |
{{DataEventRecord.Id}}
11 |
12 | 13 |
14 |
15 |
Name
16 |
17 | 18 |
19 |
20 |
21 |
22 |
Description
23 |
24 | 25 |
26 |
27 |
28 |
29 |
Timestamp
30 |
{{DataEventRecord.Timestamp}}
31 |
32 |
33 |
34 |
35 | 36 |
37 |
38 |
39 |
40 |
41 |
42 | -------------------------------------------------------------------------------- /src/Angular2Client/angular2App/app/dataeventrecords/dataeventrecords-edit.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit, OnDestroy } from '@angular/core'; 2 | import { Router, ActivatedRoute } from '@angular/router'; 3 | import { SecurityService } from '../services/SecurityService'; 4 | 5 | import { DataEventRecordsService } from '../dataeventrecords/DataEventRecordsService'; 6 | import { DataEventRecord } from './models/DataEventRecord'; 7 | 8 | @Component({ 9 | selector: 'dataeventrecords-edit', 10 | templateUrl: 'dataeventrecords-edit.component.html' 11 | }) 12 | 13 | export class DataEventRecordsEditComponent implements OnInit, OnDestroy { 14 | 15 | private id: number; 16 | public message: string; 17 | private sub: any; 18 | public DataEventRecord: DataEventRecord; 19 | 20 | constructor( 21 | private _dataEventRecordsService: DataEventRecordsService, 22 | public securityService: SecurityService, 23 | private _route: ActivatedRoute, 24 | private _router: Router 25 | ) { 26 | this.message = 'DataEventRecords Edit'; 27 | } 28 | 29 | ngOnInit() { 30 | console.log('IsAuthorized:' + this.securityService.IsAuthorized); 31 | console.log('HasAdminRole:' + this.securityService.HasAdminRole); 32 | 33 | this.sub = this._route.params.subscribe(params => { 34 | let id = +params['id']; // (+) converts string 'id' to a number 35 | if (!this.DataEventRecord) { 36 | this._dataEventRecordsService.GetById(id) 37 | .subscribe(data => this.DataEventRecord = data, 38 | error => this.securityService.HandleError(error), 39 | () => console.log('DataEventRecordsEditComponent:Get by Id complete')); 40 | } 41 | }); 42 | } 43 | 44 | ngOnDestroy() { 45 | this.sub.unsubscribe(); 46 | } 47 | 48 | public Update() { 49 | // router navigate to DataEventRecordsList 50 | this._dataEventRecordsService.Update(this.id, this.DataEventRecord) 51 | .subscribe((() => console.log('subscribed')), 52 | error => this.securityService.HandleError(error), 53 | () => this._router.navigate(['/dataeventrecords'])); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/Angular2Client/angular2App/app/dataeventrecords/dataeventrecords-list.component.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 |

{{message}}

5 |
6 |
7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 20 | 21 | 22 | 23 | 24 |
NameTimestamp
17 | {{dataEventRecord.Name}} 18 | {{dataEventRecord.Name}} 19 | {{dataEventRecord.Timestamp}}
25 | 26 |
27 |
28 |
29 | -------------------------------------------------------------------------------- /src/Angular2Client/angular2App/app/dataeventrecords/dataeventrecords-list.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | import { SecurityService } from '../services/SecurityService'; 3 | import { Observable } from 'rxjs/Observable'; 4 | import { Router } from '@angular/router'; 5 | 6 | import { DataEventRecordsService } from '../dataeventrecords/DataEventRecordsService'; 7 | import { DataEventRecord } from './models/DataEventRecord'; 8 | 9 | @Component({ 10 | selector: 'dataeventrecords-list', 11 | templateUrl: 'dataeventrecords-list.component.html' 12 | }) 13 | 14 | export class DataEventRecordsListComponent implements OnInit { 15 | 16 | public message: string; 17 | public DataEventRecords: DataEventRecord[]; 18 | 19 | constructor( 20 | private _dataEventRecordsService: DataEventRecordsService, 21 | public securityService: SecurityService, 22 | private _router: Router) { 23 | this.message = 'DataEventRecords'; 24 | } 25 | 26 | ngOnInit() { 27 | this.getData(); 28 | } 29 | 30 | public Delete(id: any) { 31 | console.log('Try to delete' + id); 32 | this._dataEventRecordsService.Delete(id) 33 | .subscribe((() => console.log('subscribed')), 34 | error => this.securityService.HandleError(error), 35 | () => this.getData()); 36 | } 37 | 38 | private getData() { 39 | console.log('DataEventRecordsListComponent:getData starting...'); 40 | this._dataEventRecordsService 41 | .GetAll() 42 | .subscribe(data => this.DataEventRecords = data, 43 | error => this.securityService.HandleError(error), 44 | () => console.log('Get all completed')); 45 | } 46 | 47 | } 48 | -------------------------------------------------------------------------------- /src/Angular2Client/angular2App/app/dataeventrecords/dataeventrecords.routes.ts: -------------------------------------------------------------------------------- 1 | import { Routes, RouterModule } from '@angular/router'; 2 | import { DataEventRecordsListComponent } from './dataeventrecords-list.component'; 3 | import { DataEventRecordsCreateComponent } from './dataeventrecords-create.component'; 4 | import { DataEventRecordsEditComponent } from './dataeventrecords-edit.component'; 5 | 6 | export const DATA_RECORDS_ROUTES: Routes = [ 7 | { 8 | path: 'dataeventrecords', 9 | 10 | children: [ 11 | { path: '', redirectTo: 'list', pathMatch: 'full'}, 12 | { 13 | path: 'create', 14 | component: DataEventRecordsCreateComponent 15 | }, 16 | { 17 | path: 'edit/:id', 18 | component: DataEventRecordsEditComponent 19 | }, 20 | { 21 | path: 'list', 22 | component: DataEventRecordsListComponent, 23 | } 24 | ] 25 | } 26 | ]; -------------------------------------------------------------------------------- /src/Angular2Client/angular2App/app/dataeventrecords/models/DataEventRecord.ts: -------------------------------------------------------------------------------- 1 | export class DataEventRecord { 2 | Id: number; 3 | Name: string; 4 | Description: string; 5 | Timestamp: string; 6 | } -------------------------------------------------------------------------------- /src/Angular2Client/angular2App/app/forbidden/forbidden.component.html: -------------------------------------------------------------------------------- 1 |
403: You have no rights to access this.
-------------------------------------------------------------------------------- /src/Angular2Client/angular2App/app/forbidden/forbidden.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'forbidden', 5 | templateUrl: 'forbidden.component.html' 6 | }) 7 | 8 | export class ForbiddenComponent implements OnInit { 9 | 10 | public message: string; 11 | public values: any[]; 12 | 13 | constructor() { 14 | this.message = 'ForbiddenComponent constructor'; 15 | } 16 | 17 | ngOnInit() { 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/Angular2Client/angular2App/app/home/home.component.html: -------------------------------------------------------------------------------- 1 |
Welcome
-------------------------------------------------------------------------------- /src/Angular2Client/angular2App/app/home/home.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'home', 5 | templateUrl: 'home.component.html' 6 | }) 7 | 8 | export class HomeComponent implements OnInit { 9 | 10 | public message: string; 11 | public values: any[]; 12 | 13 | constructor() { 14 | this.message = 'HomeComponent constructor'; 15 | } 16 | 17 | ngOnInit() { 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/Angular2Client/angular2App/app/securefile/SecureFileService.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@angular/core'; 2 | import { Http, Response, Headers } from '@angular/http'; 3 | import 'rxjs/add/operator/map'; 4 | import { Observable } from 'rxjs/Observable'; 5 | import { Configuration } from '../app.constants'; 6 | import { SecurityService } from '../services/SecurityService'; 7 | 8 | @Injectable() 9 | export class SecureFileService { 10 | 11 | private actionUrl: string; 12 | private fileExplorerUrl: string; 13 | private headers: Headers; 14 | 15 | constructor(private _http: Http, private _configuration: Configuration, private _securityService: SecurityService) { 16 | this.actionUrl = `${_configuration.FileServer}api/Download/`; 17 | this.fileExplorerUrl = `${_configuration.FileServer }api/FileExplorer/`; 18 | } 19 | 20 | public DownloadFile(id: string) { 21 | this.setHeaders(); 22 | let oneTimeAccessToken = ''; 23 | this._http.get(`${this.actionUrl}GenerateOneTimeAccessToken/${id}`, { 24 | headers: this.headers, 25 | body: '' 26 | }).map( 27 | res => res.text() 28 | ).subscribe( 29 | data => { 30 | oneTimeAccessToken = data; 31 | }, 32 | error => this._securityService.HandleError(error), 33 | () => { 34 | console.log(`open DownloadFile for file ${id}: ${this.actionUrl}${oneTimeAccessToken}`); 35 | window.open(`${this.actionUrl}${oneTimeAccessToken}`); 36 | }); 37 | } 38 | 39 | public GetListOfFiles = (): Observable => { 40 | this.setHeaders(); 41 | return this._http.get(this.fileExplorerUrl, { 42 | headers: this.headers, 43 | body: '' 44 | }).map(res => res.json()); 45 | } 46 | 47 | private setHeaders() { 48 | this.headers = new Headers(); 49 | this.headers.append('Content-Type', 'application/json'); 50 | this.headers.append('Accept', 'application/json'); 51 | 52 | let token = this._securityService.GetToken(); 53 | 54 | if (token !== '') { 55 | this.headers.append('Authorization', 'Bearer ' + token); 56 | } 57 | } 58 | } -------------------------------------------------------------------------------- /src/Angular2Client/angular2App/app/securefile/securefiles.component.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 |

{{message}}

5 |
6 |
7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 |
Name
Download {{file}}
19 | 20 |
21 |
22 |
23 | -------------------------------------------------------------------------------- /src/Angular2Client/angular2App/app/securefile/securefiles.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | import { SecureFileService } from './SecureFileService'; 3 | import { SecurityService } from '../services/SecurityService'; 4 | import { Observable } from 'rxjs/Observable'; 5 | 6 | @Component({ 7 | selector: 'securefiles', 8 | templateUrl: 'securefiles.component.html', 9 | providers: [SecureFileService] 10 | }) 11 | 12 | export class SecureFilesComponent implements OnInit { 13 | 14 | public message: string; 15 | public Files: string[]; 16 | 17 | constructor(private _secureFileService: SecureFileService, public securityService: SecurityService) { 18 | this.message = 'Secure Files download'; 19 | } 20 | 21 | ngOnInit() { 22 | this.getData(); 23 | } 24 | 25 | public DownloadFileById(id: any) { 26 | this._secureFileService.DownloadFile(id); 27 | } 28 | 29 | private getData() { 30 | this._secureFileService.GetListOfFiles() 31 | .subscribe(data => this.Files = data, 32 | error => this.securityService.HandleError(error), 33 | () => console.log('Get all completed')); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/Angular2Client/angular2App/app/unauthorized/unauthorized.component.html: -------------------------------------------------------------------------------- 1 |
401: You have no rights to access this. Please Login
-------------------------------------------------------------------------------- /src/Angular2Client/angular2App/app/unauthorized/unauthorized.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'unauthorized', 5 | templateUrl: 'unauthorized.component.html' 6 | }) 7 | 8 | export class UnauthorizedComponent implements OnInit { 9 | 10 | public message: string; 11 | public values: any[]; 12 | 13 | constructor() { 14 | this.message = 'UnauthorizedComponent constructor'; 15 | } 16 | 17 | ngOnInit() { 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/Angular2Client/angular2App/css/bootstrap-theme.min.css.map: -------------------------------------------------------------------------------- 1 | {"version":3,"sources":["less/theme.less","less/mixins/vendor-prefixes.less","less/mixins/gradients.less","less/mixins/reset-filter.less"],"names":[],"mappings":";;;;AAmBA,YAAA,aAAA,UAAA,aAAA,aAAA,aAME,YAAA,EAAA,KAAA,EAAA,eC2CA,mBAAA,MAAA,EAAA,IAAA,EAAA,sBAAA,EAAA,IAAA,IAAA,iBACQ,WAAA,MAAA,EAAA,IAAA,EAAA,sBAAA,EAAA,IAAA,IAAA,iBDvCR,mBAAA,mBAAA,oBAAA,oBAAA,iBAAA,iBAAA,oBAAA,oBAAA,oBAAA,oBAAA,oBAAA,oBCsCA,mBAAA,MAAA,EAAA,IAAA,IAAA,iBACQ,WAAA,MAAA,EAAA,IAAA,IAAA,iBDlCR,qBAAA,sBAAA,sBAAA,uBAAA,mBAAA,oBAAA,sBAAA,uBAAA,sBAAA,uBAAA,sBAAA,uBAAA,+BAAA,gCAAA,6BAAA,gCAAA,gCAAA,gCCiCA,mBAAA,KACQ,WAAA,KDlDV,mBAAA,oBAAA,iBAAA,oBAAA,oBAAA,oBAuBI,YAAA,KAyCF,YAAA,YAEE,iBAAA,KAKJ,aErEI,YAAA,EAAA,IAAA,EAAA,KACA,iBAAA,iDACA,iBAAA,4CAAA,iBAAA,qEAEA,iBAAA,+CCnBF,OAAA,+GH4CA,OAAA,0DACA,kBAAA,SAuC2C,aAAA,QAA2B,aAAA,KArCtE,mBAAA,mBAEE,iBAAA,QACA,oBAAA,EAAA,MAGF,oBAAA,oBAEE,iBAAA,QACA,aAAA,QAMA,sBAAA,6BAAA,4BAAA,6BAAA,4BAAA,4BAAA,uBAAA,8BAAA,6BAAA,8BAAA,6BAAA,6BAAA,gCAAA,uCAAA,sCAAA,uCAAA,sCAAA,sCAME,iBAAA,QACA,iBAAA,KAgBN,aEtEI,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDAEA,OAAA,+GCnBF,OAAA,0DH4CA,kBAAA,SACA,aAAA,QAEA,mBAAA,mBAEE,iBAAA,QACA,oBAAA,EAAA,MAGF,oBAAA,oBAEE,iBAAA,QACA,aAAA,QAMA,sBAAA,6BAAA,4BAAA,6BAAA,4BAAA,4BAAA,uBAAA,8BAAA,6BAAA,8BAAA,6BAAA,6BAAA,gCAAA,uCAAA,sCAAA,uCAAA,sCAAA,sCAME,iBAAA,QACA,iBAAA,KAiBN,aEvEI,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDAEA,OAAA,+GCnBF,OAAA,0DH4CA,kBAAA,SACA,aAAA,QAEA,mBAAA,mBAEE,iBAAA,QACA,oBAAA,EAAA,MAGF,oBAAA,oBAEE,iBAAA,QACA,aAAA,QAMA,sBAAA,6BAAA,4BAAA,6BAAA,4BAAA,4BAAA,uBAAA,8BAAA,6BAAA,8BAAA,6BAAA,6BAAA,gCAAA,uCAAA,sCAAA,uCAAA,sCAAA,sCAME,iBAAA,QACA,iBAAA,KAkBN,UExEI,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDAEA,OAAA,+GCnBF,OAAA,0DH4CA,kBAAA,SACA,aAAA,QAEA,gBAAA,gBAEE,iBAAA,QACA,oBAAA,EAAA,MAGF,iBAAA,iBAEE,iBAAA,QACA,aAAA,QAMA,mBAAA,0BAAA,yBAAA,0BAAA,yBAAA,yBAAA,oBAAA,2BAAA,0BAAA,2BAAA,0BAAA,0BAAA,6BAAA,oCAAA,mCAAA,oCAAA,mCAAA,mCAME,iBAAA,QACA,iBAAA,KAmBN,aEzEI,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDAEA,OAAA,+GCnBF,OAAA,0DH4CA,kBAAA,SACA,aAAA,QAEA,mBAAA,mBAEE,iBAAA,QACA,oBAAA,EAAA,MAGF,oBAAA,oBAEE,iBAAA,QACA,aAAA,QAMA,sBAAA,6BAAA,4BAAA,6BAAA,4BAAA,4BAAA,uBAAA,8BAAA,6BAAA,8BAAA,6BAAA,6BAAA,gCAAA,uCAAA,sCAAA,uCAAA,sCAAA,sCAME,iBAAA,QACA,iBAAA,KAoBN,YE1EI,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDAEA,OAAA,+GCnBF,OAAA,0DH4CA,kBAAA,SACA,aAAA,QAEA,kBAAA,kBAEE,iBAAA,QACA,oBAAA,EAAA,MAGF,mBAAA,mBAEE,iBAAA,QACA,aAAA,QAMA,qBAAA,4BAAA,2BAAA,4BAAA,2BAAA,2BAAA,sBAAA,6BAAA,4BAAA,6BAAA,4BAAA,4BAAA,+BAAA,sCAAA,qCAAA,sCAAA,qCAAA,qCAME,iBAAA,QACA,iBAAA,KA2BN,eAAA,WClCE,mBAAA,EAAA,IAAA,IAAA,iBACQ,WAAA,EAAA,IAAA,IAAA,iBD2CV,0BAAA,0BE3FI,iBAAA,QACA,iBAAA,oDACA,iBAAA,+CAAA,iBAAA,wEACA,iBAAA,kDACA,OAAA,+GF0FF,kBAAA,SAEF,yBAAA,+BAAA,+BEhGI,iBAAA,QACA,iBAAA,oDACA,iBAAA,+CAAA,iBAAA,wEACA,iBAAA,kDACA,OAAA,+GFgGF,kBAAA,SASF,gBE7GI,iBAAA,iDACA,iBAAA,4CACA,iBAAA,qEAAA,iBAAA,+CACA,OAAA,+GACA,OAAA,0DCnBF,kBAAA,SH+HA,cAAA,ICjEA,mBAAA,MAAA,EAAA,IAAA,EAAA,sBAAA,EAAA,IAAA,IAAA,iBACQ,WAAA,MAAA,EAAA,IAAA,EAAA,sBAAA,EAAA,IAAA,IAAA,iBD6DV,sCAAA,oCE7GI,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDACA,OAAA,+GACA,kBAAA,SD2CF,mBAAA,MAAA,EAAA,IAAA,IAAA,iBACQ,WAAA,MAAA,EAAA,IAAA,IAAA,iBD0EV,cAAA,iBAEE,YAAA,EAAA,IAAA,EAAA,sBAIF,gBEhII,iBAAA,iDACA,iBAAA,4CACA,iBAAA,qEAAA,iBAAA,+CACA,OAAA,+GACA,OAAA,0DCnBF,kBAAA,SHkJA,cAAA,IAHF,sCAAA,oCEhII,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDACA,OAAA,+GACA,kBAAA,SD2CF,mBAAA,MAAA,EAAA,IAAA,IAAA,gBACQ,WAAA,MAAA,EAAA,IAAA,IAAA,gBDgFV,8BAAA,iCAYI,YAAA,EAAA,KAAA,EAAA,gBAKJ,qBAAA,kBAAA,mBAGE,cAAA,EAqBF,yBAfI,mDAAA,yDAAA,yDAGE,MAAA,KE7JF,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDACA,OAAA,+GACA,kBAAA,UFqKJ,OACE,YAAA,EAAA,IAAA,EAAA,qBC3HA,mBAAA,MAAA,EAAA,IAAA,EAAA,sBAAA,EAAA,IAAA,IAAA,gBACQ,WAAA,MAAA,EAAA,IAAA,EAAA,sBAAA,EAAA,IAAA,IAAA,gBDsIV,eEtLI,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDACA,OAAA,+GACA,kBAAA,SF8KF,aAAA,QAKF,YEvLI,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDACA,OAAA,+GACA,kBAAA,SF8KF,aAAA,QAMF,eExLI,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDACA,OAAA,+GACA,kBAAA,SF8KF,aAAA,QAOF,cEzLI,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDACA,OAAA,+GACA,kBAAA,SF8KF,aAAA,QAeF,UEjMI,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDACA,OAAA,+GACA,kBAAA,SFuMJ,cE3MI,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDACA,OAAA,+GACA,kBAAA,SFwMJ,sBE5MI,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDACA,OAAA,+GACA,kBAAA,SFyMJ,mBE7MI,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDACA,OAAA,+GACA,kBAAA,SF0MJ,sBE9MI,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDACA,OAAA,+GACA,kBAAA,SF2MJ,qBE/MI,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDACA,OAAA,+GACA,kBAAA,SF+MJ,sBElLI,iBAAA,yKACA,iBAAA,oKACA,iBAAA,iKFyLJ,YACE,cAAA,IC9KA,mBAAA,EAAA,IAAA,IAAA,iBACQ,WAAA,EAAA,IAAA,IAAA,iBDgLV,wBAAA,8BAAA,8BAGE,YAAA,EAAA,KAAA,EAAA,QEnOE,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDACA,OAAA,+GACA,kBAAA,SFiOF,aAAA,QALF,+BAAA,qCAAA,qCAQI,YAAA,KAUJ,OCnME,mBAAA,EAAA,IAAA,IAAA,gBACQ,WAAA,EAAA,IAAA,IAAA,gBD4MV,8BE5PI,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDACA,OAAA,+GACA,kBAAA,SFyPJ,8BE7PI,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDACA,OAAA,+GACA,kBAAA,SF0PJ,8BE9PI,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDACA,OAAA,+GACA,kBAAA,SF2PJ,2BE/PI,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDACA,OAAA,+GACA,kBAAA,SF4PJ,8BEhQI,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDACA,OAAA,+GACA,kBAAA,SF6PJ,6BEjQI,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDACA,OAAA,+GACA,kBAAA,SFoQJ,MExQI,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDACA,OAAA,+GACA,kBAAA,SFsQF,aAAA,QC3NA,mBAAA,MAAA,EAAA,IAAA,IAAA,gBAAA,EAAA,IAAA,EAAA,qBACQ,WAAA,MAAA,EAAA,IAAA,IAAA,gBAAA,EAAA,IAAA,EAAA"} -------------------------------------------------------------------------------- /src/Angular2Client/angular2App/fonts/glyphicons-halflings-regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/damienbod/AspNetCoreIdentityServer4Angular2Docker/2a9866d707945a24d27eb06d694d94f94f3467fa/src/Angular2Client/angular2App/fonts/glyphicons-halflings-regular.eot -------------------------------------------------------------------------------- /src/Angular2Client/angular2App/fonts/glyphicons-halflings-regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/damienbod/AspNetCoreIdentityServer4Angular2Docker/2a9866d707945a24d27eb06d694d94f94f3467fa/src/Angular2Client/angular2App/fonts/glyphicons-halflings-regular.ttf -------------------------------------------------------------------------------- /src/Angular2Client/angular2App/fonts/glyphicons-halflings-regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/damienbod/AspNetCoreIdentityServer4Angular2Docker/2a9866d707945a24d27eb06d694d94f94f3467fa/src/Angular2Client/angular2App/fonts/glyphicons-halflings-regular.woff -------------------------------------------------------------------------------- /src/Angular2Client/angular2App/fonts/glyphicons-halflings-regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/damienbod/AspNetCoreIdentityServer4Angular2Docker/2a9866d707945a24d27eb06d694d94f94f3467fa/src/Angular2Client/angular2App/fonts/glyphicons-halflings-regular.woff2 -------------------------------------------------------------------------------- /src/Angular2Client/angular2App/images/damienbod.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/damienbod/AspNetCoreIdentityServer4Angular2Docker/2a9866d707945a24d27eb06d694d94f94f3467fa/src/Angular2Client/angular2App/images/damienbod.jpg -------------------------------------------------------------------------------- /src/Angular2Client/angular2App/index.html: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | ASP.NET Core 1.0 Angular 2 IdentityServer4 Client 9 | 10 | 11 | 12 | Loading... 13 | 14 | 15 | -------------------------------------------------------------------------------- /src/Angular2Client/angular2App/main-aot.js: -------------------------------------------------------------------------------- 1 | export * from './polyfills'; 2 | export * from './vendor'; 3 | import { platformBrowser } from '@angular/platform-browser'; 4 | import { enableProdMode } from '@angular/core'; 5 | import { AppModuleNgFactory } from '../aot/angular2App/app/app.module.ngfactory'; 6 | enableProdMode(); 7 | platformBrowser().bootstrapModuleFactory(AppModuleNgFactory); 8 | -------------------------------------------------------------------------------- /src/Angular2Client/angular2App/main-aot.ts: -------------------------------------------------------------------------------- 1 | // Entry point for AoT compilation. 2 | export * from './polyfills'; 3 | export * from './vendor'; 4 | 5 | import { platformBrowser } from '@angular/platform-browser'; 6 | import { enableProdMode } from '@angular/core'; 7 | import { AppModuleNgFactory } from '../aot/angular2App/app/app.module.ngfactory'; 8 | 9 | enableProdMode(); 10 | 11 | platformBrowser().bootstrapModuleFactory(AppModuleNgFactory); 12 | -------------------------------------------------------------------------------- /src/Angular2Client/angular2App/main.ts: -------------------------------------------------------------------------------- 1 | // Entry point for JiT compilation. 2 | export * from './polyfills'; 3 | export * from './vendor'; 4 | 5 | import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; 6 | import { AppModule } from './app/app.module'; 7 | 8 | platformBrowserDynamic().bootstrapModule(AppModule); 9 | -------------------------------------------------------------------------------- /src/Angular2Client/angular2App/polyfills.ts: -------------------------------------------------------------------------------- 1 | import 'ie-shim'; // Internet Explorer 9 support. 2 | 3 | import 'core-js/es6/symbol'; 4 | import 'core-js/es6/object'; 5 | import 'core-js/es6/function'; 6 | import 'core-js/es6/parse-int'; 7 | import 'core-js/es6/parse-float'; 8 | import 'core-js/es6/number'; 9 | import 'core-js/es6/math'; 10 | import 'core-js/es6/string'; 11 | import 'core-js/es6/date'; 12 | import 'core-js/es6/array'; 13 | import 'core-js/es6/regexp'; 14 | import 'core-js/es6/map'; 15 | import 'core-js/es6/set'; 16 | import 'core-js/es6/weak-map'; 17 | import 'core-js/es6/weak-set'; 18 | import 'core-js/es6/typed'; 19 | import 'core-js/es6/reflect'; 20 | import 'core-js/es7/reflect'; 21 | 22 | import 'zone.js/dist/zone'; 23 | 24 | import 'ts-helpers'; 25 | -------------------------------------------------------------------------------- /src/Angular2Client/angular2App/style/app.scss: -------------------------------------------------------------------------------- 1 | a { 2 | color: #03A9F4; 3 | } -------------------------------------------------------------------------------- /src/Angular2Client/angular2App/vendor.ts: -------------------------------------------------------------------------------- 1 | import 'jquery/src/jquery'; 2 | import 'bootstrap/dist/js/bootstrap'; 3 | 4 | import './css/bootstrap.css'; 5 | import './css/bootstrap-theme.css'; 6 | 7 | -------------------------------------------------------------------------------- /src/Angular2Client/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "IncludeScopes": false, 4 | "LogLevel": { 5 | "Default": "Debug", 6 | "System": "Information", 7 | "Microsoft": "Information" 8 | } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/Angular2Client/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "angular2-webpack-visualstudio", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "wwwroot/index.html", 6 | "author": "", 7 | "license": "ISC", 8 | "scripts": { 9 | "ngc": "ngc -p ./tsconfig-aot.json", 10 | "start": "concurrently \"webpack-dev-server --hot --inline --port 8080\" \"dotnet run\" ", 11 | "webpack-dev": "set NODE_ENV=development && webpack", 12 | "webpack-production": "set NODE_ENV=production && webpack", 13 | "build-dev": "npm run webpack-dev", 14 | "build-production": "npm run ngc && npm run webpack-production", 15 | "watch-webpack-dev": "set NODE_ENV=development && webpack --watch --color", 16 | "watch-webpack-production": "npm run build-production --watch --color", 17 | "publish-for-iis": "npm run build-production && dotnet publish -c Release" 18 | }, 19 | "dependencies": { 20 | "@angular/common": "~2.4.6", 21 | "@angular/compiler": "~2.4.6", 22 | "@angular/core": "~2.4.6", 23 | "@angular/forms": "~2.4.6", 24 | "@angular/http": "~2.4.6", 25 | "@angular/platform-browser": "~2.4.6", 26 | "@angular/platform-browser-dynamic": "~2.4.6", 27 | "@angular/router": "~3.4.1", 28 | "@angular/upgrade": "~2.4.3", 29 | "angular-in-memory-web-api": "0.2.4", 30 | "core-js": "2.4.1", 31 | "reflect-metadata": "0.1.9", 32 | "rxjs": "5.0.3", 33 | "zone.js": "0.7.5", 34 | "@angular/compiler-cli": "~2.4.6", 35 | "@angular/platform-server": "~2.4.6", 36 | "bootstrap": "^3.3.7", 37 | "ie-shim": "~0.1.0" 38 | }, 39 | "devDependencies": { 40 | "@types/node": "7.0.0", 41 | "angular2-template-loader": "^0.6.0", 42 | "angular-router-loader": "^0.5.0", 43 | "awesome-typescript-loader": "^2.2.4", 44 | "clean-webpack-plugin": "^0.1.15", 45 | "concurrently": "^3.1.0", 46 | "copy-webpack-plugin": "^4.0.1", 47 | "css-loader": "^0.26.1", 48 | "file-loader": "^0.9.0", 49 | "html-webpack-plugin": "^2.26.0", 50 | "jquery": "^2.2.0", 51 | "json-loader": "^0.5.4", 52 | "node-sass": "^4.3.0", 53 | "raw-loader": "^0.5.1", 54 | "rimraf": "^2.5.4", 55 | "sass-loader": "^4.1.1", 56 | "source-map-loader": "^0.1.6", 57 | "style-loader": "^0.13.1", 58 | "ts-helpers": "^1.1.2", 59 | "tslint": "^4.3.1", 60 | "tslint-loader": "^3.3.0", 61 | "typescript": "2.0.3", 62 | "url-loader": "^0.5.7", 63 | "webpack": "^2.2.1", 64 | "webpack-dev-server": "2.2.1" 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /src/Angular2Client/runtimeconfig.template.json: -------------------------------------------------------------------------------- 1 | { 2 | "configProperties": { 3 | "System.GC.Server": true 4 | } 5 | } -------------------------------------------------------------------------------- /src/Angular2Client/tsconfig-aot.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "module": "es2015", 5 | "moduleResolution": "node", 6 | "sourceMap": false, 7 | "emitDecoratorMetadata": true, 8 | "experimentalDecorators": true, 9 | "removeComments": true, 10 | "noImplicitAny": true, 11 | "suppressImplicitAnyIndexErrors": true, 12 | "skipLibCheck": true, 13 | "lib": [ 14 | "es2015", 15 | "dom" 16 | ] 17 | }, 18 | "files": [ 19 | "angular2App/app/app.module.ts", 20 | "angular2App/main-aot.ts" 21 | ], 22 | "angularCompilerOptions": { 23 | "genDir": "aot", 24 | "skipMetadataEmit": true 25 | }, 26 | "compileOnSave": false, 27 | "buildOnSave": false 28 | } -------------------------------------------------------------------------------- /src/Angular2Client/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "module": "es2015", 5 | "moduleResolution": "node", 6 | "sourceMap": true, 7 | "emitDecoratorMetadata": true, 8 | "experimentalDecorators": true, 9 | "removeComments": true, 10 | "noImplicitAny": true, 11 | "skipLibCheck": true, 12 | "lib": [ 13 | "es2015", 14 | "dom" 15 | ], 16 | "types": [ 17 | "node" 18 | ] 19 | }, 20 | "files": [ 21 | "angular2App/app/app.module.ts", 22 | "angular2App/main.ts" 23 | ], 24 | "awesomeTypescriptLoaderOptions": { 25 | "useWebpackText": true 26 | }, 27 | "compileOnSave": false, 28 | "buildOnSave": false 29 | } 30 | -------------------------------------------------------------------------------- /src/Angular2Client/tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "rules": { 3 | "class-name": true, 4 | "comment-format": [ 5 | true 6 | ], 7 | "curly": true, 8 | "eofline": false, 9 | "forin": false, 10 | "indent": [ 11 | false, 12 | "spaces" 13 | ], 14 | "label-position": true, 15 | "max-line-length": [ 16 | true, 17 | 200 18 | ], 19 | "member-access": false, 20 | "member-ordering": [ 21 | true, 22 | "static-before-instance", 23 | "variables-before-functions" 24 | ], 25 | "no-arg": true, 26 | "no-bitwise": true, 27 | "no-console": [ 28 | true, 29 | "debug", 30 | "info", 31 | "time", 32 | "timeEnd", 33 | "trace" 34 | ], 35 | "no-construct": true, 36 | "no-debugger": true, 37 | "no-duplicate-variable": true, 38 | "no-empty": false, 39 | "no-eval": true, 40 | "no-inferrable-types": [ true ], 41 | "no-shadowed-variable": false, 42 | "no-string-literal": false, 43 | "no-switch-case-fall-through": false, 44 | "no-trailing-whitespace": true, 45 | "no-unused-expression": true, 46 | "no-use-before-declare": true, 47 | "no-var-keyword": true, 48 | "object-literal-sort-keys": false, 49 | "one-line": [ 50 | true, 51 | "check-open-brace", 52 | "check-catch", 53 | "check-else", 54 | "check-whitespace" 55 | ], 56 | "quotemark": [ 57 | true, 58 | "single" 59 | ], 60 | "radix": false, 61 | "semicolon": [ 62 | "always" 63 | ], 64 | "triple-equals": [ 65 | false, 66 | "allow-null-check" 67 | ], 68 | "typedef-whitespace": [ 69 | true, 70 | { 71 | "index-signature": "nospace", 72 | "parameter": "nospace", 73 | "property-declaration": "nospace", 74 | "variable-declaration": "nospace" 75 | } 76 | ], 77 | "variable-name": false, 78 | "whitespace": [ 79 | true, 80 | "check-branch", 81 | "check-decl", 82 | "check-operator", 83 | "check-separator", 84 | "check-type" 85 | ] 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /src/Angular2Client/web.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /src/Angular2Client/webpack.config.js: -------------------------------------------------------------------------------- 1 | var environment = (process.env.NODE_ENV || "development").trim(); 2 | 3 | if (environment === "development") { 4 | module.exports = require('./webpack.dev.js'); 5 | } else { 6 | module.exports = require('./webpack.prod.js'); 7 | } -------------------------------------------------------------------------------- /src/Angular2Client/webpack.dev.js: -------------------------------------------------------------------------------- 1 | var path = require('path'); 2 | 3 | var webpack = require('webpack'); 4 | 5 | var HtmlWebpackPlugin = require('html-webpack-plugin'); 6 | var CopyWebpackPlugin = require('copy-webpack-plugin'); 7 | var CleanWebpackPlugin = require('clean-webpack-plugin'); 8 | var helpers = require('./webpack.helpers'); 9 | 10 | console.log('@@@@@@@@@ USING DEVELOPMENT @@@@@@@@@@@@@@@'); 11 | 12 | module.exports = { 13 | 14 | devtool: 'source-map', 15 | performance: { 16 | hints: false 17 | }, 18 | entry: { 19 | 'app': './angular2App/main.ts' 20 | }, 21 | 22 | output: { 23 | path: __dirname + '/wwwroot/', 24 | filename: 'dist/[name].bundle.js', 25 | chunkFilename: 'dist/[id].chunk.js', 26 | publicPath: '/' 27 | }, 28 | 29 | resolve: { 30 | extensions: ['.ts', '.js', '.json', '.css', '.scss', '.html'] 31 | }, 32 | 33 | devServer: { 34 | historyApiFallback: true, 35 | contentBase: path.join(__dirname, '/wwwroot/'), 36 | watchOptions: { 37 | aggregateTimeout: 300, 38 | poll: 1000 39 | } 40 | }, 41 | 42 | module: { 43 | rules: [ 44 | { 45 | test: /\.ts$/, 46 | loaders: [ 47 | 'awesome-typescript-loader', 48 | 'angular-router-loader', 49 | 'angular2-template-loader', 50 | 'source-map-loader', 51 | 'tslint-loader' 52 | ] 53 | }, 54 | { 55 | test: /\.(png|jpg|gif|woff|woff2|ttf|svg|eot)$/, 56 | loader: 'file-loader?name=assets/[name]-[hash:6].[ext]' 57 | }, 58 | { 59 | test: /favicon.ico$/, 60 | loader: 'file-loader?name=/[name].[ext]' 61 | }, 62 | { 63 | test: /\.css$/, 64 | loader: 'style-loader!css-loader' 65 | }, 66 | { 67 | test: /\.scss$/, 68 | exclude: /node_modules/, 69 | loaders: ['style-loader', 'css-loader', 'sass-loader'] 70 | }, 71 | { 72 | test: /\.html$/, 73 | loader: 'raw-loader' 74 | } 75 | ], 76 | exprContextCritical: false 77 | }, 78 | plugins: [ 79 | new webpack.optimize.CommonsChunkPlugin({ name: ['app', 'polyfills']}), 80 | 81 | new CleanWebpackPlugin( 82 | [ 83 | './wwwroot/dist', 84 | './wwwroot/assets' 85 | ] 86 | ), 87 | 88 | new HtmlWebpackPlugin({ 89 | filename: 'index.html', 90 | inject: 'body', 91 | template: 'angular2App/index.html' 92 | }), 93 | 94 | new CopyWebpackPlugin([ 95 | { from: './angular2App/images/*.*', to: 'assets/', flatten: true } 96 | ]) 97 | ] 98 | 99 | }; 100 | 101 | -------------------------------------------------------------------------------- /src/Angular2Client/webpack.helpers.js: -------------------------------------------------------------------------------- 1 | var path = require('path'); 2 | 3 | module.exports = { 4 | packageSort: function (packages) { 5 | // packages = ['polyfills', 'vendor', 'app'] 6 | var len = packages.length - 1; 7 | var first = packages[0]; 8 | var last = packages[len]; 9 | return function sort(a, b) { 10 | // polyfills always first 11 | if (a.names[0] === first) { 12 | return -1; 13 | } 14 | // main always last 15 | if (a.names[0] === last) { 16 | return 1; 17 | } 18 | // vendor before app 19 | if (a.names[0] !== first && b.names[0] === last) { 20 | return -1; 21 | } else { 22 | return 1; 23 | } 24 | }; 25 | } 26 | }; -------------------------------------------------------------------------------- /src/Angular2Client/webpack.prod.js: -------------------------------------------------------------------------------- 1 | var path = require('path'); 2 | 3 | var webpack = require('webpack'); 4 | 5 | var HtmlWebpackPlugin = require('html-webpack-plugin'); 6 | var CopyWebpackPlugin = require('copy-webpack-plugin'); 7 | var CleanWebpackPlugin = require('clean-webpack-plugin'); 8 | var helpers = require('./webpack.helpers'); 9 | 10 | console.log('@@@@@@@@@ USING PRODUCTION @@@@@@@@@@@@@@@'); 11 | 12 | module.exports = { 13 | 14 | entry: { 15 | 'vendor': './angular2App/vendor.ts', 16 | 'app': './angular2App/main-aot.ts' // AoT compilation 17 | }, 18 | 19 | output: { 20 | path: './wwwroot/', 21 | filename: 'dist/[name].[hash].bundle.js', 22 | publicPath: '/' 23 | }, 24 | 25 | resolve: { 26 | extensions: ['.ts', '.js', '.json', '.css', '.scss', '.html'] 27 | }, 28 | 29 | devServer: { 30 | historyApiFallback: true, 31 | stats: 'minimal', 32 | outputPath: path.join(__dirname, 'wwwroot/') 33 | }, 34 | 35 | module: { 36 | rules: [ 37 | { 38 | test: /\.ts$/, 39 | loaders: [ 40 | 'awesome-typescript-loader' 41 | ] 42 | }, 43 | { 44 | test: /\.(png|jpg|gif|woff|woff2|ttf|svg|eot)$/, 45 | loader: 'file-loader?name=assets/[name]-[hash:6].[ext]' 46 | }, 47 | { 48 | test: /favicon.ico$/, 49 | loader: 'file-loader?name=/[name].[ext]' 50 | }, 51 | { 52 | test: /\.css$/, 53 | loader: 'style-loader!css-loader' 54 | }, 55 | { 56 | test: /\.scss$/, 57 | exclude: /node_modules/, 58 | loaders: ['style-loader', 'css-loader', 'sass-loader'] 59 | }, 60 | { 61 | test: /\.html$/, 62 | loader: 'raw-loader' 63 | } 64 | ], 65 | exprContextCritical: false 66 | }, 67 | 68 | plugins: [ 69 | new CleanWebpackPlugin( 70 | [ 71 | './wwwroot/dist', 72 | './wwwroot/assets' 73 | ] 74 | ), 75 | new webpack.NoEmitOnErrorsPlugin(), 76 | new webpack.optimize.UglifyJsPlugin({ 77 | compress: { 78 | warnings: false 79 | }, 80 | output: { 81 | comments: false 82 | }, 83 | sourceMap: false 84 | }), 85 | new webpack.optimize.CommonsChunkPlugin( 86 | { 87 | name: ['vendor'] 88 | }), 89 | 90 | new HtmlWebpackPlugin({ 91 | filename: 'index.html', 92 | inject: 'body', 93 | template: 'angular2App/index.html' 94 | }), 95 | 96 | new CopyWebpackPlugin([ 97 | { from: './angular2App/images/*.*', to: 'assets/', flatten: true } 98 | ]) 99 | ] 100 | }; 101 | 102 | -------------------------------------------------------------------------------- /src/IdentityServerWithIdentitySQLite/.bowerrc: -------------------------------------------------------------------------------- 1 | { 2 | "directory": "wwwroot/lib" 3 | } 4 | -------------------------------------------------------------------------------- /src/IdentityServerWithIdentitySQLite/.dockerignore: -------------------------------------------------------------------------------- 1 | * 2 | !obj/Docker/publish/* 3 | !obj/Docker/empty/ 4 | -------------------------------------------------------------------------------- /src/IdentityServerWithIdentitySQLite/Controllers/HomeController.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using Microsoft.AspNetCore.Mvc; 6 | using IdentityServer4.Services; 7 | using IdentityServer4.Quickstart.UI.Models; 8 | 9 | namespace IdentityServerWithAspNetIdentity.Controllers 10 | { 11 | public class HomeController : Controller 12 | { 13 | private readonly IIdentityServerInteractionService _interaction; 14 | 15 | public HomeController(IIdentityServerInteractionService interaction) 16 | { 17 | _interaction = interaction; 18 | } 19 | 20 | public IActionResult Index() 21 | { 22 | return View(); 23 | } 24 | 25 | public IActionResult About() 26 | { 27 | ViewData["Message"] = "Your application description page."; 28 | 29 | return View(); 30 | } 31 | 32 | public IActionResult Contact() 33 | { 34 | ViewData["Message"] = "Your contact page."; 35 | 36 | return View(); 37 | } 38 | 39 | /// 40 | /// Shows the error page 41 | /// 42 | public async Task Error(string errorId) 43 | { 44 | var vm = new ErrorViewModel(); 45 | 46 | // retrieve error details from identityserver 47 | var message = await _interaction.GetErrorContextAsync(errorId); 48 | if (message != null) 49 | { 50 | vm.Error = message; 51 | } 52 | 53 | return View("Error", vm); 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/IdentityServerWithIdentitySQLite/Data/ApplicationDbContext.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using Microsoft.AspNetCore.Identity.EntityFrameworkCore; 6 | using Microsoft.EntityFrameworkCore; 7 | using IdentityServerWithAspNetIdentity.Models; 8 | 9 | namespace IdentityServerWithAspNetIdentity.Data 10 | { 11 | public class ApplicationDbContext : IdentityDbContext 12 | { 13 | public ApplicationDbContext(DbContextOptions options) 14 | : base(options) 15 | { 16 | } 17 | 18 | protected override void OnModelCreating(ModelBuilder builder) 19 | { 20 | base.OnModelCreating(builder); 21 | // Customize the ASP.NET Identity model and override the defaults if needed. 22 | // For example, you can rename the ASP.NET Identity table names and more. 23 | // Add your customizations after calling base.OnModelCreating(builder); 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/IdentityServerWithIdentitySQLite/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM microsoft/aspnetcore:1.1 2 | ARG source 3 | WORKDIR /app 4 | EXPOSE 80 5 | COPY ${source:-obj/Docker/publish} . 6 | ENTRYPOINT ["dotnet", "IdentityServerWithIdentitySQLite.dll"] 7 | -------------------------------------------------------------------------------- /src/IdentityServerWithIdentitySQLite/Filters/SecurityHeadersAttribute.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Brock Allen & Dominick Baier. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information. 3 | 4 | 5 | using Microsoft.AspNetCore.Mvc; 6 | using Microsoft.AspNetCore.Mvc.Filters; 7 | 8 | namespace IdentityServerWithAspNetIdentity.Filters 9 | { 10 | public class SecurityHeadersAttribute : ActionFilterAttribute 11 | { 12 | public override void OnResultExecuting(ResultExecutingContext context) 13 | { 14 | var result = context.Result; 15 | if (result is ViewResult) 16 | { 17 | if (!context.HttpContext.Response.Headers.ContainsKey("X-Content-Type-Options")) 18 | { 19 | context.HttpContext.Response.Headers.Add("X-Content-Type-Options", "nosniff"); 20 | } 21 | if (!context.HttpContext.Response.Headers.ContainsKey("X-Frame-Options")) 22 | { 23 | context.HttpContext.Response.Headers.Add("X-Frame-Options", "SAMEORIGIN"); 24 | } 25 | 26 | var csp = "default-src 'self'"; 27 | // once for standards compliant browsers 28 | if (!context.HttpContext.Response.Headers.ContainsKey("Content-Security-Policy")) 29 | { 30 | context.HttpContext.Response.Headers.Add("Content-Security-Policy", csp); 31 | } 32 | // and once again for IE 33 | if (!context.HttpContext.Response.Headers.ContainsKey("X-Content-Security-Policy")) 34 | { 35 | context.HttpContext.Response.Headers.Add("X-Content-Security-Policy", csp); 36 | } 37 | } 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/IdentityServerWithIdentitySQLite/IdentityServerWithIdentitySQLite.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | netcoreapp1.1 4 | true 5 | IdentityServerWithIdentitySQLite 6 | Exe 7 | IdentityServerWithIdentitySQLite 8 | $(PackageTargetFallback);dotnet5.6;portable-net45+win8 9 | aspnet-IdentityServerWithIdentitySQLite-1e7bf5d8-6c32-4dd3-b77d-2d7d2e0f5092 10 | 11 | 12 | 13 | PreserveNewest 14 | 15 | 16 | 17 | 18 | 19 | 20 | All 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | All 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | -------------------------------------------------------------------------------- /src/IdentityServerWithIdentitySQLite/IdentityWithAdditionalClaimsProfileService.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Security.Claims; 5 | using System.Threading.Tasks; 6 | using IdentityModel; 7 | using IdentityServer4.Extensions; 8 | using IdentityServer4.Models; 9 | using IdentityServer4.Services; 10 | using IdentityServerWithAspNetIdentity.Models; 11 | using Microsoft.AspNetCore.Identity; 12 | 13 | namespace IdentityServerWithAspNetIdentitySqlite 14 | { 15 | using IdentityServer4; 16 | 17 | public class IdentityWithAdditionalClaimsProfileService : IProfileService 18 | { 19 | private readonly IUserClaimsPrincipalFactory _claimsFactory; 20 | private readonly UserManager _userManager; 21 | 22 | public IdentityWithAdditionalClaimsProfileService(UserManager userManager, IUserClaimsPrincipalFactory claimsFactory) 23 | { 24 | _userManager = userManager; 25 | _claimsFactory = claimsFactory; 26 | } 27 | 28 | public async Task GetProfileDataAsync(ProfileDataRequestContext context) 29 | { 30 | var sub = context.Subject.GetSubjectId(); 31 | 32 | var user = await _userManager.FindByIdAsync(sub); 33 | var principal = await _claimsFactory.CreateAsync(user); 34 | 35 | var claims = principal.Claims.ToList(); 36 | 37 | claims = claims.Where(claim => context.RequestedClaimTypes.Contains(claim.Type)).ToList(); 38 | 39 | 40 | claims.Add(new Claim(JwtClaimTypes.GivenName, user.UserName)); 41 | //new Claim(JwtClaimTypes.Role, "admin"), 42 | //new Claim(JwtClaimTypes.Role, "dataEventRecords.admin"), 43 | //new Claim(JwtClaimTypes.Role, "dataEventRecords.user"), 44 | //new Claim(JwtClaimTypes.Role, "dataEventRecords"), 45 | //new Claim(JwtClaimTypes.Role, "securedFiles.user"), 46 | //new Claim(JwtClaimTypes.Role, "securedFiles.admin"), 47 | //new Claim(JwtClaimTypes.Role, "securedFiles") 48 | 49 | if (user.IsAdmin) 50 | { 51 | claims.Add(new Claim(JwtClaimTypes.Role, "admin")); 52 | } 53 | else 54 | { 55 | claims.Add(new Claim(JwtClaimTypes.Role, "user")); 56 | } 57 | 58 | if (user.DataEventRecordsRole == "dataEventRecords.admin") 59 | { 60 | claims.Add(new Claim(JwtClaimTypes.Role, "dataEventRecords.admin")); 61 | claims.Add(new Claim(JwtClaimTypes.Role, "dataEventRecords.user")); 62 | claims.Add(new Claim(JwtClaimTypes.Role, "dataEventRecords")); 63 | claims.Add(new Claim(JwtClaimTypes.Scope, "dataEventRecords")); 64 | } 65 | else 66 | { 67 | claims.Add(new Claim(JwtClaimTypes.Role, "dataEventRecords.user")); 68 | claims.Add(new Claim(JwtClaimTypes.Role, "dataEventRecords")); 69 | claims.Add(new Claim(JwtClaimTypes.Scope, "dataEventRecords")); 70 | } 71 | 72 | if (user.SecuredFilesRole == "securedFiles.admin") 73 | { 74 | claims.Add(new Claim(JwtClaimTypes.Role, "securedFiles.admin")); 75 | claims.Add(new Claim(JwtClaimTypes.Role, "securedFiles.user")); 76 | claims.Add(new Claim(JwtClaimTypes.Role, "securedFiles")); 77 | claims.Add(new Claim(JwtClaimTypes.Scope, "securedFiles")); 78 | } 79 | else 80 | { 81 | claims.Add(new Claim(JwtClaimTypes.Role, "securedFiles.user")); 82 | claims.Add(new Claim(JwtClaimTypes.Role, "securedFiles")); 83 | claims.Add(new Claim(JwtClaimTypes.Scope, "securedFiles")); 84 | } 85 | 86 | claims.Add(new Claim(IdentityServerConstants.StandardScopes.Email, user.Email)); 87 | 88 | 89 | context.IssuedClaims = claims; 90 | } 91 | 92 | public async Task IsActiveAsync(IsActiveContext context) 93 | { 94 | var sub = context.Subject.GetSubjectId(); 95 | var user = await _userManager.FindByIdAsync(sub); 96 | context.IsActive = user != null; 97 | } 98 | } 99 | } -------------------------------------------------------------------------------- /src/IdentityServerWithIdentitySQLite/Models/AccountViewModels/ExternalLoginConfirmationViewModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel.DataAnnotations; 4 | using System.Linq; 5 | using System.Threading.Tasks; 6 | 7 | namespace IdentityServerWithAspNetIdentity.Models.AccountViewModels 8 | { 9 | public class ExternalLoginConfirmationViewModel 10 | { 11 | [Required] 12 | [EmailAddress] 13 | public string Email { get; set; } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/IdentityServerWithIdentitySQLite/Models/AccountViewModels/ForgotPasswordViewModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel.DataAnnotations; 4 | using System.Linq; 5 | using System.Threading.Tasks; 6 | 7 | namespace IdentityServerWithAspNetIdentity.Models.AccountViewModels 8 | { 9 | public class ForgotPasswordViewModel 10 | { 11 | [Required] 12 | [EmailAddress] 13 | public string Email { get; set; } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/IdentityServerWithIdentitySQLite/Models/AccountViewModels/LoggedOutViewModel.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Brock Allen & Dominick Baier. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information. 3 | 4 | 5 | namespace IdentityServer4.Quickstart.UI.Models 6 | { 7 | public class LoggedOutViewModel 8 | { 9 | public string PostLogoutRedirectUri { get; set; } 10 | public string ClientName { get; set; } 11 | public string SignOutIframeUrl { get; set; } 12 | } 13 | } -------------------------------------------------------------------------------- /src/IdentityServerWithIdentitySQLite/Models/AccountViewModels/LoginInputModel.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Brock Allen & Dominick Baier. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information. 3 | 4 | 5 | using System.ComponentModel.DataAnnotations; 6 | 7 | namespace IdentityServer4.Quickstart.UI.Models 8 | { 9 | public class LoginInputModel 10 | { 11 | [Required] 12 | public string Email { get; set; } 13 | [Required] 14 | public string Password { get; set; } 15 | public bool RememberLogin { get; set; } 16 | public string ReturnUrl { get; set; } 17 | } 18 | } -------------------------------------------------------------------------------- /src/IdentityServerWithIdentitySQLite/Models/AccountViewModels/LoginViewModel.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Brock Allen & Dominick Baier. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information. 3 | 4 | 5 | using System.Collections.Generic; 6 | 7 | namespace IdentityServer4.Quickstart.UI.Models 8 | { 9 | public class LoginViewModel : LoginInputModel 10 | { 11 | public bool EnableLocalLogin { get; set; } 12 | public IEnumerable ExternalProviders { get; set; } 13 | } 14 | 15 | public class ExternalProvider 16 | { 17 | public string DisplayName { get; set; } 18 | public string AuthenticationScheme { get; set; } 19 | } 20 | } -------------------------------------------------------------------------------- /src/IdentityServerWithIdentitySQLite/Models/AccountViewModels/LogoutViewModel.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Brock Allen & Dominick Baier. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information. 3 | 4 | 5 | namespace IdentityServer4.Quickstart.UI.Models 6 | { 7 | public class LogoutViewModel 8 | { 9 | public string LogoutId { get; set; } 10 | } 11 | } -------------------------------------------------------------------------------- /src/IdentityServerWithIdentitySQLite/Models/AccountViewModels/RegisterViewModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel.DataAnnotations; 4 | using System.Linq; 5 | using System.Threading.Tasks; 6 | 7 | namespace IdentityServerWithAspNetIdentity.Models.AccountViewModels 8 | { 9 | public class RegisterViewModel 10 | { 11 | [Required] 12 | [EmailAddress] 13 | [Display(Name = "Email")] 14 | public string Email { get; set; } 15 | 16 | [Required] 17 | [StringLength(100, ErrorMessage = "The {0} must be at least {2} and at max {1} characters long.", MinimumLength = 6)] 18 | [DataType(DataType.Password)] 19 | [Display(Name = "Password")] 20 | public string Password { get; set; } 21 | 22 | [DataType(DataType.Password)] 23 | [Display(Name = "Confirm password")] 24 | [Compare("Password", ErrorMessage = "The password and confirmation password do not match.")] 25 | public string ConfirmPassword { get; set; } 26 | 27 | [Display(Name = "IsAdmin")] 28 | public bool IsAdmin { get; set; } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/IdentityServerWithIdentitySQLite/Models/AccountViewModels/ResetPasswordViewModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel.DataAnnotations; 4 | using System.Linq; 5 | using System.Threading.Tasks; 6 | 7 | namespace IdentityServerWithAspNetIdentity.Models.AccountViewModels 8 | { 9 | public class ResetPasswordViewModel 10 | { 11 | [Required] 12 | [EmailAddress] 13 | public string Email { get; set; } 14 | 15 | [Required] 16 | [StringLength(100, ErrorMessage = "The {0} must be at least {2} and at max {1} characters long.", MinimumLength = 6)] 17 | [DataType(DataType.Password)] 18 | public string Password { get; set; } 19 | 20 | [DataType(DataType.Password)] 21 | [Display(Name = "Confirm password")] 22 | [Compare("Password", ErrorMessage = "The password and confirmation password do not match.")] 23 | public string ConfirmPassword { get; set; } 24 | 25 | public string Code { get; set; } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/IdentityServerWithIdentitySQLite/Models/AccountViewModels/SendCodeViewModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using Microsoft.AspNetCore.Mvc.Rendering; 6 | 7 | namespace IdentityServerWithAspNetIdentity.Models.AccountViewModels 8 | { 9 | public class SendCodeViewModel 10 | { 11 | public string SelectedProvider { get; set; } 12 | 13 | public ICollection Providers { get; set; } 14 | 15 | public string ReturnUrl { get; set; } 16 | 17 | public bool RememberMe { get; set; } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/IdentityServerWithIdentitySQLite/Models/AccountViewModels/VerifyCodeViewModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel.DataAnnotations; 4 | using System.Linq; 5 | using System.Threading.Tasks; 6 | 7 | namespace IdentityServerWithAspNetIdentity.Models.AccountViewModels 8 | { 9 | public class VerifyCodeViewModel 10 | { 11 | [Required] 12 | public string Provider { get; set; } 13 | 14 | [Required] 15 | public string Code { get; set; } 16 | 17 | public string ReturnUrl { get; set; } 18 | 19 | [Display(Name = "Remember this browser?")] 20 | public bool RememberBrowser { get; set; } 21 | 22 | [Display(Name = "Remember me?")] 23 | public bool RememberMe { get; set; } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/IdentityServerWithIdentitySQLite/Models/ApplicationUser.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Identity.EntityFrameworkCore; 2 | 3 | namespace IdentityServerWithAspNetIdentity.Models 4 | { 5 | // Add profile data for application users by adding properties to the ApplicationUser class 6 | public class ApplicationUser : IdentityUser 7 | { 8 | public bool IsAdmin { get; set; } 9 | public string DataEventRecordsRole { get; set; } 10 | public string SecuredFilesRole { get; set; } 11 | } 12 | } 13 | 14 | //new Claim(JwtClaimTypes.Role, "admin"), 15 | //new Claim(JwtClaimTypes.Role, "dataEventRecords.admin"), 16 | //new Claim(JwtClaimTypes.Role, "dataEventRecords.user"), 17 | //new Claim(JwtClaimTypes.Role, "dataEventRecords"), 18 | //new Claim(JwtClaimTypes.Role, "securedFiles.user"), 19 | //new Claim(JwtClaimTypes.Role, "securedFiles.admin"), 20 | //new Claim(JwtClaimTypes.Role, "securedFiles") -------------------------------------------------------------------------------- /src/IdentityServerWithIdentitySQLite/Models/ConsentInputModel.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Brock Allen & Dominick Baier. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information. 3 | 4 | 5 | using System.Collections.Generic; 6 | 7 | namespace IdentityServer4.Quickstart.UI.Models 8 | { 9 | public class ConsentInputModel 10 | { 11 | public string Button { get; set; } 12 | public IEnumerable ScopesConsented { get; set; } 13 | public bool RememberConsent { get; set; } 14 | public string ReturnUrl { get; set; } 15 | } 16 | } -------------------------------------------------------------------------------- /src/IdentityServerWithIdentitySQLite/Models/ConsentViewModel.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Brock Allen & Dominick Baier. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information. 3 | 4 | 5 | using System.Collections.Generic; 6 | using System.Linq; 7 | using IdentityServer4.Models; 8 | 9 | namespace IdentityServer4.Quickstart.UI.Models 10 | { 11 | public class ConsentViewModel : ConsentInputModel 12 | { 13 | public ConsentViewModel(ConsentInputModel model, string returnUrl, AuthorizationRequest request, Client client, Resources resources) 14 | { 15 | RememberConsent = model?.RememberConsent ?? true; 16 | ScopesConsented = model?.ScopesConsented ?? Enumerable.Empty(); 17 | 18 | ReturnUrl = returnUrl; 19 | 20 | ClientName = client.ClientName; 21 | ClientUrl = client.ClientUri; 22 | ClientLogoUrl = client.LogoUri; 23 | AllowRememberConsent = client.AllowRememberConsent; 24 | 25 | IdentityScopes = resources.IdentityResources.Select(x => new ScopeViewModel(x, ScopesConsented.Contains(x.Name) || model == null)).ToArray(); 26 | ResourceScopes = resources.ApiResources.SelectMany(x=>x.Scopes).Select(x => new ScopeViewModel(x, ScopesConsented.Contains(x.Name) || model == null)).ToArray(); 27 | if (resources.OfflineAccess) 28 | { 29 | ResourceScopes = ResourceScopes.Union(new ScopeViewModel[] { 30 | ScopeViewModel.GetOfflineAccess(ScopesConsented.Contains(IdentityServerConstants.StandardScopes.OfflineAccess) || model == null) 31 | }); 32 | } 33 | } 34 | 35 | public string ClientName { get; set; } 36 | public string ClientUrl { get; set; } 37 | public string ClientLogoUrl { get; set; } 38 | public bool AllowRememberConsent { get; set; } 39 | 40 | public IEnumerable IdentityScopes { get; set; } 41 | public IEnumerable ResourceScopes { get; set; } 42 | } 43 | 44 | public class ScopeViewModel 45 | { 46 | public static ScopeViewModel GetOfflineAccess(bool check) 47 | { 48 | return new ScopeViewModel 49 | { 50 | Name = IdentityServerConstants.StandardScopes.OfflineAccess, 51 | DisplayName = "Offline Access", 52 | Description = "Access to your applications and resources, even when you are offline", 53 | Emphasize = true, 54 | Checked = check 55 | }; 56 | } 57 | 58 | private ScopeViewModel() 59 | { 60 | } 61 | 62 | public ScopeViewModel(IdentityResource identity, bool check) 63 | { 64 | Name = identity.Name; 65 | DisplayName = identity.DisplayName; 66 | Description = identity.Description; 67 | Emphasize = identity.Emphasize; 68 | Required = identity.Required; 69 | Checked = check || identity.Required; 70 | } 71 | 72 | public ScopeViewModel(Scope scope, bool check) 73 | { 74 | Name = scope.Name; 75 | DisplayName = scope.DisplayName; 76 | Description = scope.Description; 77 | Emphasize = scope.Emphasize; 78 | Required = scope.Required; 79 | Checked = check || scope.Required; 80 | } 81 | 82 | public string Name { get; set; } 83 | public string DisplayName { get; set; } 84 | public string Description { get; set; } 85 | public bool Emphasize { get; set; } 86 | public bool Required { get; set; } 87 | public bool Checked { get; set; } 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /src/IdentityServerWithIdentitySQLite/Models/ErrorViewModel.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Brock Allen & Dominick Baier. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information. 3 | 4 | 5 | using IdentityServer4.Models; 6 | 7 | namespace IdentityServer4.Quickstart.UI.Models 8 | { 9 | public class ErrorViewModel 10 | { 11 | public ErrorMessage Error { get; set; } 12 | } 13 | } -------------------------------------------------------------------------------- /src/IdentityServerWithIdentitySQLite/Models/ManageViewModels/AddPhoneNumberViewModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel.DataAnnotations; 4 | using System.Linq; 5 | using System.Threading.Tasks; 6 | 7 | namespace IdentityServerWithAspNetIdentity.Models.ManageViewModels 8 | { 9 | public class AddPhoneNumberViewModel 10 | { 11 | [Required] 12 | [Phone] 13 | [Display(Name = "Phone number")] 14 | public string PhoneNumber { get; set; } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/IdentityServerWithIdentitySQLite/Models/ManageViewModels/ChangePasswordViewModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel.DataAnnotations; 4 | using System.Linq; 5 | using System.Threading.Tasks; 6 | 7 | namespace IdentityServerWithAspNetIdentity.Models.ManageViewModels 8 | { 9 | public class ChangePasswordViewModel 10 | { 11 | [Required] 12 | [DataType(DataType.Password)] 13 | [Display(Name = "Current password")] 14 | public string OldPassword { get; set; } 15 | 16 | [Required] 17 | [StringLength(100, ErrorMessage = "The {0} must be at least {2} and at max {1} characters long.", MinimumLength = 6)] 18 | [DataType(DataType.Password)] 19 | [Display(Name = "New password")] 20 | public string NewPassword { get; set; } 21 | 22 | [DataType(DataType.Password)] 23 | [Display(Name = "Confirm new password")] 24 | [Compare("NewPassword", ErrorMessage = "The new password and confirmation password do not match.")] 25 | public string ConfirmPassword { get; set; } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/IdentityServerWithIdentitySQLite/Models/ManageViewModels/ConfigureTwoFactorViewModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using Microsoft.AspNetCore.Mvc.Rendering; 6 | 7 | namespace IdentityServerWithAspNetIdentity.Models.ManageViewModels 8 | { 9 | public class ConfigureTwoFactorViewModel 10 | { 11 | public string SelectedProvider { get; set; } 12 | 13 | public ICollection Providers { get; set; } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/IdentityServerWithIdentitySQLite/Models/ManageViewModels/FactorViewModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | 6 | namespace IdentityServerWithAspNetIdentity.Models.ManageViewModels 7 | { 8 | public class FactorViewModel 9 | { 10 | public string Purpose { get; set; } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/IdentityServerWithIdentitySQLite/Models/ManageViewModels/IndexViewModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using Microsoft.AspNetCore.Identity; 6 | 7 | namespace IdentityServerWithAspNetIdentity.Models.ManageViewModels 8 | { 9 | public class IndexViewModel 10 | { 11 | public bool HasPassword { get; set; } 12 | 13 | public IList Logins { get; set; } 14 | 15 | public string PhoneNumber { get; set; } 16 | 17 | public bool TwoFactor { get; set; } 18 | 19 | public bool BrowserRemembered { get; set; } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/IdentityServerWithIdentitySQLite/Models/ManageViewModels/ManageLoginsViewModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using Microsoft.AspNetCore.Http.Authentication; 6 | using Microsoft.AspNetCore.Identity; 7 | 8 | namespace IdentityServerWithAspNetIdentity.Models.ManageViewModels 9 | { 10 | public class ManageLoginsViewModel 11 | { 12 | public IList CurrentLogins { get; set; } 13 | 14 | public IList OtherLogins { get; set; } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/IdentityServerWithIdentitySQLite/Models/ManageViewModels/RemoveLoginViewModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel.DataAnnotations; 4 | using System.Linq; 5 | using System.Threading.Tasks; 6 | 7 | namespace IdentityServerWithAspNetIdentity.Models.ManageViewModels 8 | { 9 | public class RemoveLoginViewModel 10 | { 11 | public string LoginProvider { get; set; } 12 | public string ProviderKey { get; set; } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/IdentityServerWithIdentitySQLite/Models/ManageViewModels/SetPasswordViewModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel.DataAnnotations; 4 | using System.Linq; 5 | using System.Threading.Tasks; 6 | 7 | namespace IdentityServerWithAspNetIdentity.Models.ManageViewModels 8 | { 9 | public class SetPasswordViewModel 10 | { 11 | [Required] 12 | [StringLength(100, ErrorMessage = "The {0} must be at least {2} and at max {1} characters long.", MinimumLength = 6)] 13 | [DataType(DataType.Password)] 14 | [Display(Name = "New password")] 15 | public string NewPassword { get; set; } 16 | 17 | [DataType(DataType.Password)] 18 | [Display(Name = "Confirm new password")] 19 | [Compare("NewPassword", ErrorMessage = "The new password and confirmation password do not match.")] 20 | public string ConfirmPassword { get; set; } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/IdentityServerWithIdentitySQLite/Models/ManageViewModels/VerifyPhoneNumberViewModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel.DataAnnotations; 4 | using System.Linq; 5 | using System.Threading.Tasks; 6 | 7 | namespace IdentityServerWithAspNetIdentity.Models.ManageViewModels 8 | { 9 | public class VerifyPhoneNumberViewModel 10 | { 11 | [Required] 12 | public string Code { get; set; } 13 | 14 | [Required] 15 | [Phone] 16 | [Display(Name = "Phone number")] 17 | public string PhoneNumber { get; set; } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/IdentityServerWithIdentitySQLite/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Linq; 5 | using System.Threading.Tasks; 6 | using Microsoft.AspNetCore.Hosting; 7 | 8 | namespace IdentityServerWithAspNetIdentitySqlite 9 | { 10 | public class Program 11 | { 12 | public static void Main(string[] args) 13 | { 14 | Console.Title = "IdentityServer"; 15 | 16 | var host = new WebHostBuilder() 17 | .UseKestrel() 18 | .UseUrls("http://localhost:5000") 19 | .UseContentRoot(Directory.GetCurrentDirectory()) 20 | .UseIISIntegration() 21 | .UseStartup() 22 | .Build(); 23 | 24 | host.Run(); 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/IdentityServerWithIdentitySQLite/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "iisSettings": { 3 | "windowsAuthentication": false, 4 | "anonymousAuthentication": true, 5 | "iisExpress": { 6 | "applicationUrl": "https://localhost:44318/", 7 | "sslPort": 44318 8 | } 9 | }, 10 | "profiles": { 11 | "IIS Express": { 12 | "commandName": "IISExpress", 13 | "launchBrowser": true, 14 | "environmentVariables": { 15 | "ASPNETCORE_ENVIRONMENT": "Development" 16 | } 17 | }, 18 | "IdentityServerWithAspNetIdentity": { 19 | "commandName": "Project", 20 | "launchBrowser": true, 21 | "launchUrl": "http://localhost:5000", 22 | "environmentVariables": { 23 | "ASPNETCORE_ENVIRONMENT": "Development" 24 | } 25 | }, 26 | "newProfile1": { 27 | "commandName": "IISExpress", 28 | "launchBrowser": true 29 | } 30 | } 31 | } -------------------------------------------------------------------------------- /src/IdentityServerWithIdentitySQLite/Services/IEmailSender.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | 6 | namespace IdentityServerWithAspNetIdentity.Services 7 | { 8 | public interface IEmailSender 9 | { 10 | Task SendEmailAsync(string email, string subject, string message); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/IdentityServerWithIdentitySQLite/Services/ISmsSender.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | 6 | namespace IdentityServerWithAspNetIdentity.Services 7 | { 8 | public interface ISmsSender 9 | { 10 | Task SendSmsAsync(string number, string message); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/IdentityServerWithIdentitySQLite/Services/MessageServices.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | 6 | namespace IdentityServerWithAspNetIdentity.Services 7 | { 8 | // This class is used by the application to send Email and SMS 9 | // when you turn on two-factor authentication in ASP.NET Identity. 10 | // For more details see this link http://go.microsoft.com/fwlink/?LinkID=532713 11 | public class AuthMessageSender : IEmailSender, ISmsSender 12 | { 13 | public Task SendEmailAsync(string email, string subject, string message) 14 | { 15 | // Plug in your email service here to send an email. 16 | return Task.FromResult(0); 17 | } 18 | 19 | public Task SendSmsAsync(string number, string message) 20 | { 21 | // Plug in your SMS service here to send a text message. 22 | return Task.FromResult(0); 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/IdentityServerWithIdentitySQLite/Startup.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Builder; 2 | using Microsoft.AspNetCore.Hosting; 3 | using Microsoft.AspNetCore.Identity.EntityFrameworkCore; 4 | using Microsoft.EntityFrameworkCore; 5 | using Microsoft.Extensions.Configuration; 6 | using Microsoft.Extensions.DependencyInjection; 7 | using Microsoft.Extensions.Logging; 8 | using IdentityServerWithAspNetIdentity.Data; 9 | using IdentityServerWithAspNetIdentity.Models; 10 | using IdentityServerWithAspNetIdentity.Services; 11 | using QuickstartIdentityServer; 12 | using IdentityServer4.Services; 13 | using System.Security.Cryptography.X509Certificates; 14 | using System.IO; 15 | 16 | namespace IdentityServerWithAspNetIdentitySqlite 17 | { 18 | public class Startup 19 | { 20 | private readonly IHostingEnvironment _environment; 21 | 22 | public Startup(IHostingEnvironment env) 23 | { 24 | var builder = new ConfigurationBuilder() 25 | .SetBasePath(env.ContentRootPath) 26 | .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true) 27 | .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true); 28 | 29 | _environment = env; 30 | 31 | builder.AddEnvironmentVariables(); 32 | Configuration = builder.Build(); 33 | } 34 | 35 | public IConfigurationRoot Configuration { get; } 36 | 37 | public void ConfigureServices(IServiceCollection services) 38 | { 39 | var cert = new X509Certificate2(Path.Combine(_environment.ContentRootPath, "damienbodserver.pfx"), ""); 40 | 41 | services.AddDbContext(options => 42 | options.UseSqlite(Configuration.GetConnectionString("DefaultConnection"))); 43 | 44 | services.AddIdentity() 45 | .AddEntityFrameworkStores() 46 | .AddDefaultTokenProviders(); 47 | 48 | services.AddMvc(); 49 | 50 | services.AddTransient(); 51 | 52 | services.AddTransient(); 53 | services.AddTransient(); 54 | 55 | services.AddIdentityServer() 56 | .AddSigningCredential(cert) 57 | .AddInMemoryIdentityResources(Config.GetIdentityResources()) 58 | .AddInMemoryApiResources(Config.GetApiResources()) 59 | .AddInMemoryClients(Config.GetClients()) 60 | .AddAspNetIdentity() 61 | .AddProfileService(); 62 | } 63 | 64 | public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory) 65 | { 66 | loggerFactory.AddConsole(Configuration.GetSection("Logging")); 67 | loggerFactory.AddDebug(); 68 | 69 | if (env.IsDevelopment()) 70 | { 71 | app.UseDeveloperExceptionPage(); 72 | app.UseDatabaseErrorPage(); 73 | } 74 | else 75 | { 76 | app.UseExceptionHandler("/Home/Error"); 77 | } 78 | 79 | app.UseStaticFiles(); 80 | 81 | app.UseIdentity(); 82 | app.UseIdentityServer(); 83 | 84 | app.UseMvc(routes => 85 | { 86 | routes.MapRoute( 87 | name: "default", 88 | template: "{controller=Home}/{action=Index}/{id?}"); 89 | }); 90 | } 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /src/IdentityServerWithIdentitySQLite/Views/Account/ConfirmEmail.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | ViewData["Title"] = "Confirm Email"; 3 | } 4 | 5 |

@ViewData["Title"].

6 |
7 |

8 | Thank you for confirming your email. Please Click here to Log in. 9 |

10 |
11 | -------------------------------------------------------------------------------- /src/IdentityServerWithIdentitySQLite/Views/Account/ExternalLoginConfirmation.cshtml: -------------------------------------------------------------------------------- 1 | @model ExternalLoginConfirmationViewModel 2 | @{ 3 | ViewData["Title"] = "Register"; 4 | } 5 | 6 |

@ViewData["Title"].

7 |

Associate your @ViewData["LoginProvider"] account.

8 | 9 |
10 |

Association Form

11 |
12 |
13 | 14 |

15 | You've successfully authenticated with @ViewData["LoginProvider"]. 16 | Please enter an email address for this site below and click the Register button to finish 17 | logging in. 18 |

19 |
20 | 21 |
22 | 23 | 24 |
25 |
26 |
27 |
28 | 29 |
30 |
31 |
32 | 33 | @section Scripts { 34 | @{ await Html.RenderPartialAsync("_ValidationScriptsPartial"); } 35 | } 36 | -------------------------------------------------------------------------------- /src/IdentityServerWithIdentitySQLite/Views/Account/ExternalLoginFailure.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | ViewData["Title"] = "Login Failure"; 3 | } 4 | 5 |
6 |

@ViewData["Title"].

7 |

Unsuccessful login with service.

8 |
9 | -------------------------------------------------------------------------------- /src/IdentityServerWithIdentitySQLite/Views/Account/ForgotPassword.cshtml: -------------------------------------------------------------------------------- 1 | @model ForgotPasswordViewModel 2 | @{ 3 | ViewData["Title"] = "Forgot your password?"; 4 | } 5 | 6 |

@ViewData["Title"]

7 |

8 | For more information on how to enable reset password please see this article. 9 |

10 | 11 | @*
12 |

Enter your email.

13 |
14 |
15 |
16 | 17 |
18 | 19 | 20 |
21 |
22 |
23 |
24 | 25 |
26 |
27 |
*@ 28 | 29 | @section Scripts { 30 | @{ await Html.RenderPartialAsync("_ValidationScriptsPartial"); } 31 | } 32 | -------------------------------------------------------------------------------- /src/IdentityServerWithIdentitySQLite/Views/Account/ForgotPasswordConfirmation.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | ViewData["Title"] = "Forgot Password Confirmation"; 3 | } 4 | 5 |

@ViewData["Title"].

6 |

7 | Please check your email to reset your password. 8 |

9 | -------------------------------------------------------------------------------- /src/IdentityServerWithIdentitySQLite/Views/Account/Lockout.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | ViewData["Title"] = "Locked out"; 3 | } 4 | 5 |
6 |

Locked out.

7 |

This account has been locked out, please try again later.

8 |
9 | -------------------------------------------------------------------------------- /src/IdentityServerWithIdentitySQLite/Views/Account/LoggedOut.cshtml: -------------------------------------------------------------------------------- 1 | @model IdentityServer4.Quickstart.UI.Models.LoggedOutViewModel 2 | 3 | 22 | -------------------------------------------------------------------------------- /src/IdentityServerWithIdentitySQLite/Views/Account/Login.cshtml: -------------------------------------------------------------------------------- 1 | @using System.Collections.Generic 2 | @using Microsoft.AspNetCore.Http 3 | @using Microsoft.AspNetCore.Http.Authentication 4 | @model IdentityServer4.Quickstart.UI.Models.LoginViewModel 5 | @inject SignInManager SignInManager 6 | 7 | @{ 8 | ViewData["Title"] = "Log in"; 9 | } 10 | 11 |

@ViewData["Title"].

12 |
13 |
14 |
15 |
16 |

Use a local account to log in.

17 |
18 |
19 |
20 | 21 |
22 | 23 | 24 |
25 |
26 |
27 | 28 |
29 | 30 | 31 |
32 |
33 |
34 |
35 |
36 | 40 |
41 |
42 |
43 |
44 |
45 | 46 |
47 |
48 |

49 | Register as a new user? 50 |

51 |

52 | Forgot your password? 53 |

54 |
55 |
56 |
57 |
58 |
59 |

Use another service to log in.

60 |
61 | @{ 62 | var loginProviders = Model.ExternalProviders.ToArray(); 63 | if (loginProviders.Length == 0) 64 | { 65 |
66 |

67 | There are no external authentication services configured. See this article 68 | for details on setting up this ASP.NET application to support logging in via external services. 69 |

70 |
71 | } 72 | else 73 | { 74 |
75 |
76 |

77 | @foreach (var provider in loginProviders) 78 | { 79 | 80 | } 81 |

82 |
83 |
84 | } 85 | } 86 |
87 |
88 |
89 | 90 | @section Scripts { 91 | @{ await Html.RenderPartialAsync("_ValidationScriptsPartial"); } 92 | } 93 | -------------------------------------------------------------------------------- /src/IdentityServerWithIdentitySQLite/Views/Account/Logout.cshtml: -------------------------------------------------------------------------------- 1 | @model IdentityServer4.Quickstart.UI.Models.LogoutViewModel 2 | 3 |
4 | 7 | 8 |
9 |
10 |

Would you like to logout of IdentityServer?

11 |
12 | 13 |
14 |
15 | 16 |
17 |
18 |
19 |
20 |
21 |
-------------------------------------------------------------------------------- /src/IdentityServerWithIdentitySQLite/Views/Account/Register.cshtml: -------------------------------------------------------------------------------- 1 | @model RegisterViewModel 2 | @{ 3 | ViewData["Title"] = "Register"; 4 | } 5 | 6 |

@ViewData["Title"].

7 | 8 |
9 |

Create a new account.

10 |
11 |
12 |
13 | 14 |
15 | 16 | 17 |
18 |
19 |
20 | 21 |
22 | 23 | 24 |
25 |
26 |
27 | 28 |
29 | 30 | 31 |
32 |
33 |
34 | 35 |
36 | 37 |
38 |
39 |
40 |
41 | 42 |
43 |
44 |
45 | 46 | @section Scripts { 47 | @{ await Html.RenderPartialAsync("_ValidationScriptsPartial"); } 48 | } 49 | -------------------------------------------------------------------------------- /src/IdentityServerWithIdentitySQLite/Views/Account/ResetPassword.cshtml: -------------------------------------------------------------------------------- 1 | @model ResetPasswordViewModel 2 | @{ 3 | ViewData["Title"] = "Reset password"; 4 | } 5 | 6 |

@ViewData["Title"].

7 | 8 |
9 |

Reset your password.

10 |
11 |
12 | 13 |
14 | 15 |
16 | 17 | 18 |
19 |
20 |
21 | 22 |
23 | 24 | 25 |
26 |
27 |
28 | 29 |
30 | 31 | 32 |
33 |
34 |
35 |
36 | 37 |
38 |
39 |
40 | 41 | @section Scripts { 42 | @{ await Html.RenderPartialAsync("_ValidationScriptsPartial"); } 43 | } 44 | -------------------------------------------------------------------------------- /src/IdentityServerWithIdentitySQLite/Views/Account/ResetPasswordConfirmation.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | ViewData["Title"] = "Reset password confirmation"; 3 | } 4 | 5 |

@ViewData["Title"].

6 |

7 | Your password has been reset. Please Click here to log in. 8 |

9 | -------------------------------------------------------------------------------- /src/IdentityServerWithIdentitySQLite/Views/Account/SendCode.cshtml: -------------------------------------------------------------------------------- 1 | @model SendCodeViewModel 2 | @{ 3 | ViewData["Title"] = "Send Verification Code"; 4 | } 5 | 6 |

@ViewData["Title"].

7 | 8 |
9 | 10 |
11 |
12 | Select Two-Factor Authentication Provider: 13 | 14 | 15 |
16 |
17 |
18 | 19 | @section Scripts { 20 | @{await Html.RenderPartialAsync("_ValidationScriptsPartial"); } 21 | } 22 | -------------------------------------------------------------------------------- /src/IdentityServerWithIdentitySQLite/Views/Account/VerifyCode.cshtml: -------------------------------------------------------------------------------- 1 | @model VerifyCodeViewModel 2 | @{ 3 | ViewData["Title"] = "Verify"; 4 | } 5 | 6 |

@ViewData["Title"].

7 | 8 |
9 |
10 | 11 | 12 |

@ViewData["Status"]

13 |
14 |
15 | 16 |
17 | 18 | 19 |
20 |
21 |
22 |
23 |
24 | 25 | 26 |
27 |
28 |
29 |
30 |
31 | 32 |
33 |
34 |
35 | 36 | @section Scripts { 37 | @{ await Html.RenderPartialAsync("_ValidationScriptsPartial"); } 38 | } 39 | -------------------------------------------------------------------------------- /src/IdentityServerWithIdentitySQLite/Views/Consent/Index.cshtml: -------------------------------------------------------------------------------- 1 | @model IdentityServer4.Quickstart.UI.Models.ConsentViewModel 2 | 3 | -------------------------------------------------------------------------------- /src/IdentityServerWithIdentitySQLite/Views/Consent/_ScopeListItem.cshtml: -------------------------------------------------------------------------------- 1 | @model IdentityServer4.Quickstart.UI.Models.ScopeViewModel 2 | 3 |
  • 4 | 24 | @if (Model.Required) 25 | { 26 | (required) 27 | } 28 | @if (Model.Description != null) 29 | { 30 | 33 | } 34 |
  • -------------------------------------------------------------------------------- /src/IdentityServerWithIdentitySQLite/Views/Home/About.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | ViewData["Title"] = "About"; 3 | } 4 |

    @ViewData["Title"].

    5 |

    @ViewData["Message"]

    6 | 7 |

    Use this area to provide additional information.

    8 | -------------------------------------------------------------------------------- /src/IdentityServerWithIdentitySQLite/Views/Home/Contact.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | ViewData["Title"] = "Contact"; 3 | } 4 |

    @ViewData["Title"].

    5 |

    @ViewData["Message"]

    6 | 7 |
    8 | One Microsoft Way
    9 | Redmond, WA 98052-6399
    10 | P: 11 | 425.555.0100 12 |
    13 | 14 |
    15 | Support: Support@example.com
    16 | Marketing: Marketing@example.com 17 |
    18 | -------------------------------------------------------------------------------- /src/IdentityServerWithIdentitySQLite/Views/Home/Index.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | ViewData["Title"] = "Home Page"; 3 | } 4 | 5 |

    Home

    6 | @if (User.Identity.IsAuthenticated) 7 | { 8 |

    Welcome back @User.Identity.Name

    9 |

    User Claims

    10 |
    11 | @foreach (var claim in User.Claims) 12 | { 13 |
    @claim.Type
    14 |
    @claim.Value
    15 | } 16 |
    17 | 18 | var authScheme = "Identity.Application"; 19 | if (!String.IsNullOrWhiteSpace(authScheme)) 20 | { 21 |

    Cookies Properties

    22 |
    23 | @{ 24 | var props = (await Context.Authentication.GetAuthenticateInfoAsync(authScheme)).Properties; 25 | } 26 | @foreach (var item in props.Items) 27 | { 28 |
    @item.Key
    29 |
    @item.Value
    30 | } 31 |
    32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/IdentityServerWithIdentitySQLite/Views/Manage/AddPhoneNumber.cshtml: -------------------------------------------------------------------------------- 1 | @model AddPhoneNumberViewModel 2 | @{ 3 | ViewData["Title"] = "Add Phone Number"; 4 | } 5 | 6 |

    @ViewData["Title"].

    7 |
    8 |

    Add a phone number.

    9 |
    10 |
    11 |
    12 | 13 |
    14 | 15 | 16 |
    17 |
    18 |
    19 |
    20 | 21 |
    22 |
    23 |
    24 | 25 | @section Scripts { 26 | @{ await Html.RenderPartialAsync("_ValidationScriptsPartial"); } 27 | } 28 | -------------------------------------------------------------------------------- /src/IdentityServerWithIdentitySQLite/Views/Manage/ChangePassword.cshtml: -------------------------------------------------------------------------------- 1 | @model ChangePasswordViewModel 2 | @{ 3 | ViewData["Title"] = "Change Password"; 4 | } 5 | 6 |

    @ViewData["Title"].

    7 | 8 |
    9 |

    Change Password Form

    10 |
    11 |
    12 |
    13 | 14 |
    15 | 16 | 17 |
    18 |
    19 |
    20 | 21 |
    22 | 23 | 24 |
    25 |
    26 |
    27 | 28 |
    29 | 30 | 31 |
    32 |
    33 |
    34 |
    35 | 36 |
    37 |
    38 |
    39 | 40 | @section Scripts { 41 | @{ await Html.RenderPartialAsync("_ValidationScriptsPartial"); } 42 | } 43 | -------------------------------------------------------------------------------- /src/IdentityServerWithIdentitySQLite/Views/Manage/Index.cshtml: -------------------------------------------------------------------------------- 1 | @model IndexViewModel 2 | @{ 3 | ViewData["Title"] = "Manage your account"; 4 | } 5 | 6 |

    @ViewData["Title"].

    7 |

    @ViewData["StatusMessage"]

    8 | 9 |
    10 |

    Change your account settings

    11 |
    12 |
    13 |
    Password:
    14 |
    15 | @if (Model.HasPassword) 16 | { 17 | Change 18 | } 19 | else 20 | { 21 | Create 22 | } 23 |
    24 |
    External Logins:
    25 |
    26 | 27 | @Model.Logins.Count Manage 28 |
    29 |
    Phone Number:
    30 |
    31 |

    32 | Phone Numbers can used as a second factor of verification in two-factor authentication. 33 | See this article 34 | for details on setting up this ASP.NET application to support two-factor authentication using SMS. 35 |

    36 | @*@(Model.PhoneNumber ?? "None") 37 | @if (Model.PhoneNumber != null) 38 | { 39 |
    40 | Change 41 |
    42 | [] 43 |
    44 | } 45 | else 46 | { 47 | Add 48 | }*@ 49 |
    50 | 51 |
    Two-Factor Authentication:
    52 |
    53 |

    54 | There are no two-factor authentication providers configured. See this article 55 | for setting up this application to support two-factor authentication. 56 |

    57 | @*@if (Model.TwoFactor) 58 | { 59 |
    60 | Enabled 61 |
    62 | } 63 | else 64 | { 65 |
    66 | Disabled 67 |
    68 | }*@ 69 |
    70 |
    71 |
    72 | -------------------------------------------------------------------------------- /src/IdentityServerWithIdentitySQLite/Views/Manage/ManageLogins.cshtml: -------------------------------------------------------------------------------- 1 | @model ManageLoginsViewModel 2 | @using Microsoft.AspNetCore.Http.Authentication 3 | @{ 4 | ViewData["Title"] = "Manage your external logins"; 5 | } 6 | 7 |

    @ViewData["Title"].

    8 | 9 |

    @ViewData["StatusMessage"]

    10 | @if (Model.CurrentLogins.Count > 0) 11 | { 12 |

    Registered Logins

    13 | 14 | 15 | @for (var index = 0; index < Model.CurrentLogins.Count; index++) 16 | { 17 | 18 | 19 | 35 | 36 | } 37 | 38 |
    @Model.CurrentLogins[index].LoginProvider 20 | @if ((bool)ViewData["ShowRemoveButton"]) 21 | { 22 |
    23 |
    24 | 25 | 26 | 27 |
    28 |
    29 | } 30 | else 31 | { 32 | @:   33 | } 34 |
    39 | } 40 | @if (Model.OtherLogins.Count > 0) 41 | { 42 |

    Add another service to log in.

    43 |
    44 |
    45 |
    46 |

    47 | @foreach (var provider in Model.OtherLogins) 48 | { 49 | 50 | } 51 |

    52 |
    53 |
    54 | } 55 | -------------------------------------------------------------------------------- /src/IdentityServerWithIdentitySQLite/Views/Manage/SetPassword.cshtml: -------------------------------------------------------------------------------- 1 | @model SetPasswordViewModel 2 | @{ 3 | ViewData["Title"] = "Set Password"; 4 | } 5 | 6 |

    7 | You do not have a local username/password for this site. Add a local 8 | account so you can log in without an external login. 9 |

    10 | 11 |
    12 |

    Set your password

    13 |
    14 |
    15 |
    16 | 17 |
    18 | 19 | 20 |
    21 |
    22 |
    23 | 24 |
    25 | 26 | 27 |
    28 |
    29 |
    30 |
    31 | 32 |
    33 |
    34 |
    35 | 36 | @section Scripts { 37 | @{ await Html.RenderPartialAsync("_ValidationScriptsPartial"); } 38 | } 39 | -------------------------------------------------------------------------------- /src/IdentityServerWithIdentitySQLite/Views/Manage/VerifyPhoneNumber.cshtml: -------------------------------------------------------------------------------- 1 | @model VerifyPhoneNumberViewModel 2 | @{ 3 | ViewData["Title"] = "Verify Phone Number"; 4 | } 5 | 6 |

    @ViewData["Title"].

    7 | 8 |
    9 | 10 |

    Add a phone number.

    11 |
    @ViewData["Status"]
    12 |
    13 |
    14 |
    15 | 16 |
    17 | 18 | 19 |
    20 |
    21 |
    22 |
    23 | 24 |
    25 |
    26 |
    27 | 28 | @section Scripts { 29 | @{ await Html.RenderPartialAsync("_ValidationScriptsPartial"); } 30 | } 31 | -------------------------------------------------------------------------------- /src/IdentityServerWithIdentitySQLite/Views/Shared/Error.cshtml: -------------------------------------------------------------------------------- 1 | @model IdentityServer4.Quickstart.UI.Models.ErrorViewModel 2 | 3 | @{ 4 | var error = Model?.Error?.Error; 5 | var request_id = Model?.Error?.RequestId; 6 | } 7 | 8 |
    9 | 12 | 13 |
    14 |
    15 |
    16 | Sorry, there was an error 17 | 18 | @if (error != null) 19 | { 20 | 21 | 22 | : @error 23 | 24 | 25 | } 26 |
    27 | 28 | @if (request_id != null) 29 | { 30 |
    Request Id: @request_id
    31 | } 32 |
    33 |
    34 |
    35 | -------------------------------------------------------------------------------- /src/IdentityServerWithIdentitySQLite/Views/Shared/_Layout.cshtml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | @ViewData["Title"] - IdentityServerWithAspNetIdentity 7 | 8 | 9 | 10 | 11 | 12 | 13 | 16 | 17 | 18 | 19 | 20 | 41 |
    42 | @RenderBody() 43 |
    44 |
    45 |

    © 2016 - IdentityServerWithAspNetIdentity

    46 |
    47 |
    48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 59 | 63 | 64 | 65 | 66 | @RenderSection("scripts", required: false) 67 | 68 | 69 | -------------------------------------------------------------------------------- /src/IdentityServerWithIdentitySQLite/Views/Shared/_LoginPartial.cshtml: -------------------------------------------------------------------------------- 1 | @using Microsoft.AspNetCore.Identity 2 | @using IdentityServerWithAspNetIdentity.Models 3 | 4 | @inject SignInManager SignInManager 5 | @inject UserManager UserManager 6 | 7 | @if (SignInManager.IsSignedIn(User)) 8 | { 9 | 19 | } 20 | else 21 | { 22 | 26 | } 27 | -------------------------------------------------------------------------------- /src/IdentityServerWithIdentitySQLite/Views/Shared/_ValidationScriptsPartial.cshtml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 10 | 14 | 15 | -------------------------------------------------------------------------------- /src/IdentityServerWithIdentitySQLite/Views/Shared/_ValidationSummary.cshtml: -------------------------------------------------------------------------------- 1 | @if (ViewContext.ModelState.IsValid == false) 2 | { 3 |
    4 | Error 5 |
    6 |
    7 | } -------------------------------------------------------------------------------- /src/IdentityServerWithIdentitySQLite/Views/_ViewImports.cshtml: -------------------------------------------------------------------------------- 1 | @using IdentityServerWithAspNetIdentity 2 | @using IdentityServerWithAspNetIdentity.Models 3 | @using IdentityServerWithAspNetIdentity.Models.AccountViewModels 4 | @using IdentityServerWithAspNetIdentity.Models.ManageViewModels 5 | @using Microsoft.AspNetCore.Identity 6 | @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers 7 | -------------------------------------------------------------------------------- /src/IdentityServerWithIdentitySQLite/Views/_ViewStart.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | Layout = "_Layout"; 3 | } 4 | -------------------------------------------------------------------------------- /src/IdentityServerWithIdentitySQLite/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | 3 | "ConnectionStrings": { 4 | "DefaultConnection": "Data Source=C:\\git\\damienbod\\AspNetCoreIdentityServer4Angular2Docker\\src\\IdentityServerWithIdentitySQLite\\usersdatabase.sqlite" 5 | }, 6 | 7 | "Logging": { 8 | "IncludeScopes": false, 9 | "LogLevel": { 10 | "Default": "Debug", 11 | "System": "Information", 12 | "Microsoft": "Information" 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/IdentityServerWithIdentitySQLite/bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "asp.net", 3 | "private": true, 4 | "dependencies": { 5 | "bootstrap": "3.3.6", 6 | "jquery": "2.2.0", 7 | "jquery-validation": "1.14.0", 8 | "jquery-validation-unobtrusive": "3.2.6" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/IdentityServerWithIdentitySQLite/bundleconfig.json: -------------------------------------------------------------------------------- 1 | // Configure bundling and minification for the project. 2 | // More info at https://go.microsoft.com/fwlink/?LinkId=808241 3 | [ 4 | { 5 | "outputFileName": "wwwroot/css/site.min.css", 6 | // An array of relative input file paths. Globbing patterns supported 7 | "inputFiles": [ 8 | "wwwroot/css/site.css" 9 | ] 10 | }, 11 | { 12 | "outputFileName": "wwwroot/js/site.min.js", 13 | "inputFiles": [ 14 | "wwwroot/js/site.js" 15 | ], 16 | // Optionally specify minification options 17 | "minify": { 18 | "enabled": true, 19 | "renameLocals": true 20 | }, 21 | // Optinally generate .map file 22 | "sourceMap": false 23 | } 24 | ] 25 | -------------------------------------------------------------------------------- /src/IdentityServerWithIdentitySQLite/damienbodserver.pfx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/damienbod/AspNetCoreIdentityServer4Angular2Docker/2a9866d707945a24d27eb06d694d94f94f3467fa/src/IdentityServerWithIdentitySQLite/damienbodserver.pfx -------------------------------------------------------------------------------- /src/IdentityServerWithIdentitySQLite/runtimeconfig.template.json: -------------------------------------------------------------------------------- 1 | { 2 | "configProperties": { 3 | "System.GC.Server": true 4 | } 5 | } -------------------------------------------------------------------------------- /src/IdentityServerWithIdentitySQLite/usersdatabase.sqlite: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/damienbod/AspNetCoreIdentityServer4Angular2Docker/2a9866d707945a24d27eb06d694d94f94f3467fa/src/IdentityServerWithIdentitySQLite/usersdatabase.sqlite -------------------------------------------------------------------------------- /src/IdentityServerWithIdentitySQLite/web.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /src/IdentityServerWithIdentitySQLite/wwwroot/_references.js: -------------------------------------------------------------------------------- 1 | /// 2 | /// 3 | /// 4 | /// 5 | /// 6 | /// 7 | -------------------------------------------------------------------------------- /src/IdentityServerWithIdentitySQLite/wwwroot/css/site.css: -------------------------------------------------------------------------------- 1 | body { 2 | padding-top: 50px; 3 | padding-bottom: 20px; 4 | } 5 | 6 | /* Wrapping element */ 7 | /* Set some basic padding to keep content from hitting the edges */ 8 | .body-content { 9 | padding-left: 15px; 10 | padding-right: 15px; 11 | } 12 | 13 | /* Set widths on the form inputs since otherwise they're 100% wide */ 14 | input, 15 | select, 16 | textarea { 17 | max-width: 280px; 18 | } 19 | 20 | /* Carousel */ 21 | .carousel-caption p { 22 | font-size: 20px; 23 | line-height: 1.4; 24 | } 25 | 26 | /* buttons and links extension to use brackets: [ click me ] */ 27 | .btn-bracketed::before { 28 | display:inline-block; 29 | content: "["; 30 | padding-right: 0.5em; 31 | } 32 | .btn-bracketed::after { 33 | display:inline-block; 34 | content: "]"; 35 | padding-left: 0.5em; 36 | } 37 | 38 | /* Make .svg files in the carousel display properly in older browsers */ 39 | .carousel-inner .item img[src$=".svg"] 40 | { 41 | width: 100%; 42 | } 43 | 44 | /* Hide/rearrange for smaller screens */ 45 | @media screen and (max-width: 767px) { 46 | /* Hide captions */ 47 | .carousel-caption { 48 | display: none 49 | } 50 | } 51 | 52 | .page-consent .client-logo { 53 | float: left; 54 | } 55 | .page-consent .client-logo img { 56 | width: 80px; 57 | height: 80px; 58 | } 59 | .page-consent .consent-buttons { 60 | margin-top: 25px; 61 | } 62 | .page-consent .consent-form .consent-scopecheck { 63 | display: inline-block; 64 | margin-right: 5px; 65 | } 66 | .page-consent .consent-form .consent-description { 67 | margin-left: 25px; 68 | } 69 | .page-consent .consent-form .consent-description label { 70 | font-weight: normal; 71 | } 72 | .page-consent .consent-form .consent-remember { 73 | padding-left: 16px; 74 | } 75 | -------------------------------------------------------------------------------- /src/IdentityServerWithIdentitySQLite/wwwroot/css/site.min.css: -------------------------------------------------------------------------------- 1 | body{padding-top:50px;padding-bottom:20px}.body-content{padding-left:15px;padding-right:15px}input,select,textarea{max-width:280px}.carousel-caption p{font-size:20px;line-height:1.4}.btn-bracketed::before{display:inline-block;content:"[";padding-right:.5em}.btn-bracketed::after{display:inline-block;content:"]";padding-left:.5em}.carousel-inner .item img[src$=".svg"]{width:100%}@media screen and (max-width:767px){.carousel-caption{display:none}}.page-consent .client-logo{float:left}.page-consent .client-logo img{width:80px;height:80px}.page-consent .consent-buttons{margin-top:25px}.page-consent .consent-form .consent-scopecheck{display:inline-block;margin-right:5px}.page-consent .consent-form .consent-description{margin-left:25px}.page-consent .consent-form .consent-description label{font-weight:normal}.page-consent .consent-form .consent-remember{padding-left:16px} -------------------------------------------------------------------------------- /src/IdentityServerWithIdentitySQLite/wwwroot/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/damienbod/AspNetCoreIdentityServer4Angular2Docker/2a9866d707945a24d27eb06d694d94f94f3467fa/src/IdentityServerWithIdentitySQLite/wwwroot/favicon.ico -------------------------------------------------------------------------------- /src/IdentityServerWithIdentitySQLite/wwwroot/js/site.js: -------------------------------------------------------------------------------- 1 | // Write your Javascript code. 2 | -------------------------------------------------------------------------------- /src/IdentityServerWithIdentitySQLite/wwwroot/js/site.min.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/damienbod/AspNetCoreIdentityServer4Angular2Docker/2a9866d707945a24d27eb06d694d94f94f3467fa/src/IdentityServerWithIdentitySQLite/wwwroot/js/site.min.js -------------------------------------------------------------------------------- /src/IdentityServerWithIdentitySQLite/wwwroot/lib/bootstrap/.bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "bootstrap", 3 | "description": "The most popular front-end framework for developing responsive, mobile first projects on the web.", 4 | "keywords": [ 5 | "css", 6 | "js", 7 | "less", 8 | "mobile-first", 9 | "responsive", 10 | "front-end", 11 | "framework", 12 | "web" 13 | ], 14 | "homepage": "http://getbootstrap.com", 15 | "license": "MIT", 16 | "moduleType": "globals", 17 | "main": [ 18 | "less/bootstrap.less", 19 | "dist/js/bootstrap.js" 20 | ], 21 | "ignore": [ 22 | "/.*", 23 | "_config.yml", 24 | "CNAME", 25 | "composer.json", 26 | "CONTRIBUTING.md", 27 | "docs", 28 | "js/tests", 29 | "test-infra" 30 | ], 31 | "dependencies": { 32 | "jquery": "1.9.1 - 2" 33 | }, 34 | "version": "3.3.6", 35 | "_release": "3.3.6", 36 | "_resolution": { 37 | "type": "version", 38 | "tag": "v3.3.6", 39 | "commit": "81df608a40bf0629a1dc08e584849bb1e43e0b7a" 40 | }, 41 | "_source": "git://github.com/twbs/bootstrap.git", 42 | "_target": "3.3.6", 43 | "_originalSource": "bootstrap" 44 | } -------------------------------------------------------------------------------- /src/IdentityServerWithIdentitySQLite/wwwroot/lib/bootstrap/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2011-2015 Twitter, Inc 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /src/IdentityServerWithIdentitySQLite/wwwroot/lib/bootstrap/dist/fonts/glyphicons-halflings-regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/damienbod/AspNetCoreIdentityServer4Angular2Docker/2a9866d707945a24d27eb06d694d94f94f3467fa/src/IdentityServerWithIdentitySQLite/wwwroot/lib/bootstrap/dist/fonts/glyphicons-halflings-regular.eot -------------------------------------------------------------------------------- /src/IdentityServerWithIdentitySQLite/wwwroot/lib/bootstrap/dist/fonts/glyphicons-halflings-regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/damienbod/AspNetCoreIdentityServer4Angular2Docker/2a9866d707945a24d27eb06d694d94f94f3467fa/src/IdentityServerWithIdentitySQLite/wwwroot/lib/bootstrap/dist/fonts/glyphicons-halflings-regular.ttf -------------------------------------------------------------------------------- /src/IdentityServerWithIdentitySQLite/wwwroot/lib/bootstrap/dist/fonts/glyphicons-halflings-regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/damienbod/AspNetCoreIdentityServer4Angular2Docker/2a9866d707945a24d27eb06d694d94f94f3467fa/src/IdentityServerWithIdentitySQLite/wwwroot/lib/bootstrap/dist/fonts/glyphicons-halflings-regular.woff -------------------------------------------------------------------------------- /src/IdentityServerWithIdentitySQLite/wwwroot/lib/bootstrap/dist/fonts/glyphicons-halflings-regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/damienbod/AspNetCoreIdentityServer4Angular2Docker/2a9866d707945a24d27eb06d694d94f94f3467fa/src/IdentityServerWithIdentitySQLite/wwwroot/lib/bootstrap/dist/fonts/glyphicons-halflings-regular.woff2 -------------------------------------------------------------------------------- /src/IdentityServerWithIdentitySQLite/wwwroot/lib/bootstrap/dist/js/npm.js: -------------------------------------------------------------------------------- 1 | // This file is autogenerated via the `commonjs` Grunt task. You can require() this file in a CommonJS environment. 2 | require('../../js/transition.js') 3 | require('../../js/alert.js') 4 | require('../../js/button.js') 5 | require('../../js/carousel.js') 6 | require('../../js/collapse.js') 7 | require('../../js/dropdown.js') 8 | require('../../js/modal.js') 9 | require('../../js/tooltip.js') 10 | require('../../js/popover.js') 11 | require('../../js/scrollspy.js') 12 | require('../../js/tab.js') 13 | require('../../js/affix.js') -------------------------------------------------------------------------------- /src/IdentityServerWithIdentitySQLite/wwwroot/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.min.js: -------------------------------------------------------------------------------- 1 | /* 2 | ** Unobtrusive validation support library for jQuery and jQuery Validate 3 | ** Copyright (C) Microsoft Corporation. All rights reserved. 4 | */ 5 | !function(a){function e(a,e,n){a.rules[e]=n,a.message&&(a.messages[e]=a.message)}function n(a){return a.replace(/^\s+|\s+$/g,"").split(/\s*,\s*/g)}function t(a){return a.replace(/([!"#$%&'()*+,./:;<=>?@\[\\\]^`{|}~])/g,"\\$1")}function r(a){return a.substr(0,a.lastIndexOf(".")+1)}function i(a,e){return 0===a.indexOf("*.")&&(a=a.replace("*.",e)),a}function o(e,n){var r=a(this).find("[data-valmsg-for='"+t(n[0].name)+"']"),i=r.attr("data-valmsg-replace"),o=i?a.parseJSON(i)!==!1:null;r.removeClass("field-validation-valid").addClass("field-validation-error"),e.data("unobtrusiveContainer",r),o?(r.empty(),e.removeClass("input-validation-error").appendTo(r)):e.hide()}function d(e,n){var t=a(this).find("[data-valmsg-summary=true]"),r=t.find("ul");r&&r.length&&n.errorList.length&&(r.empty(),t.addClass("validation-summary-errors").removeClass("validation-summary-valid"),a.each(n.errorList,function(){a("
  • ").html(this.message).appendTo(r)}))}function s(e){var n=e.data("unobtrusiveContainer");if(n){var t=n.attr("data-valmsg-replace"),r=t?a.parseJSON(t):null;n.addClass("field-validation-valid").removeClass("field-validation-error"),e.removeData("unobtrusiveContainer"),r&&n.empty()}}function l(e){var n=a(this),t="__jquery_unobtrusive_validation_form_reset";if(!n.data(t)){n.data(t,!0);try{n.data("validator").resetForm()}finally{n.removeData(t)}n.find(".validation-summary-errors").addClass("validation-summary-valid").removeClass("validation-summary-errors"),n.find(".field-validation-error").addClass("field-validation-valid").removeClass("field-validation-error").removeData("unobtrusiveContainer").find(">*").removeData("unobtrusiveContainer")}}function m(e){var n=a(e),t=n.data(v),r=a.proxy(l,e),i=p.unobtrusive.options||{},m=function(n,t){var r=i[n];r&&a.isFunction(r)&&r.apply(e,t)};return t||(t={options:{errorClass:i.errorClass||"input-validation-error",errorElement:i.errorElement||"span",errorPlacement:function(){o.apply(e,arguments),m("errorPlacement",arguments)},invalidHandler:function(){d.apply(e,arguments),m("invalidHandler",arguments)},messages:{},rules:{},success:function(){s.apply(e,arguments),m("success",arguments)}},attachValidation:function(){n.off("reset."+v,r).on("reset."+v,r).validate(this.options)},validate:function(){return n.validate(),n.valid()}},n.data(v,t)),t}var u,p=a.validator,v="unobtrusiveValidation";p.unobtrusive={adapters:[],parseElement:function(e,n){var t,r,i,o=a(e),d=o.parents("form")[0];d&&(t=m(d),t.options.rules[e.name]=r={},t.options.messages[e.name]=i={},a.each(this.adapters,function(){var n="data-val-"+this.name,t=o.attr(n),s={};void 0!==t&&(n+="-",a.each(this.params,function(){s[this]=o.attr(n+this)}),this.adapt({element:e,form:d,message:t,params:s,rules:r,messages:i}))}),a.extend(r,{__dummy__:!0}),n||t.attachValidation())},parse:function(e){var n=a(e),t=n.parents().addBack().filter("form").add(n.find("form")).has("[data-val=true]");n.find("[data-val=true]").each(function(){p.unobtrusive.parseElement(this,!0)}),t.each(function(){var a=m(this);a&&a.attachValidation()})}},u=p.unobtrusive.adapters,u.add=function(a,e,n){return n||(n=e,e=[]),this.push({name:a,params:e,adapt:n}),this},u.addBool=function(a,n){return this.add(a,function(t){e(t,n||a,!0)})},u.addMinMax=function(a,n,t,r,i,o){return this.add(a,[i||"min",o||"max"],function(a){var i=a.params.min,o=a.params.max;i&&o?e(a,r,[i,o]):i?e(a,n,i):o&&e(a,t,o)})},u.addSingleVal=function(a,n,t){return this.add(a,[n||"val"],function(r){e(r,t||a,r.params[n])})},p.addMethod("__dummy__",function(a,e,n){return!0}),p.addMethod("regex",function(a,e,n){var t;return this.optional(e)?!0:(t=new RegExp(n).exec(a),t&&0===t.index&&t[0].length===a.length)}),p.addMethod("nonalphamin",function(a,e,n){var t;return n&&(t=a.match(/\W/g),t=t&&t.length>=n),t}),p.methods.extension?(u.addSingleVal("accept","mimtype"),u.addSingleVal("extension","extension")):u.addSingleVal("extension","extension","accept"),u.addSingleVal("regex","pattern"),u.addBool("creditcard").addBool("date").addBool("digits").addBool("email").addBool("number").addBool("url"),u.addMinMax("length","minlength","maxlength","rangelength").addMinMax("range","min","max","range"),u.addMinMax("minlength","minlength").addMinMax("maxlength","minlength","maxlength"),u.add("equalto",["other"],function(n){var o=r(n.element.name),d=n.params.other,s=i(d,o),l=a(n.form).find(":input").filter("[name='"+t(s)+"']")[0];e(n,"equalTo",l)}),u.add("required",function(a){("INPUT"!==a.element.tagName.toUpperCase()||"CHECKBOX"!==a.element.type.toUpperCase())&&e(a,"required",!0)}),u.add("remote",["url","type","additionalfields"],function(o){var d={url:o.params.url,type:o.params.type||"GET",data:{}},s=r(o.element.name);a.each(n(o.params.additionalfields||o.element.name),function(e,n){var r=i(n,s);d.data[r]=function(){var e=a(o.form).find(":input").filter("[name='"+t(r)+"']");return e.is(":checkbox")?e.filter(":checked").val()||e.filter(":hidden").val()||"":e.is(":radio")?e.filter(":checked").val()||"":e.val()}}),e(o,"remote",d)}),u.add("password",["min","nonalphamin","regex"],function(a){a.params.min&&e(a,"minlength",a.params.min),a.params.nonalphamin&&e(a,"nonalphamin",a.params.nonalphamin),a.params.regex&&e(a,"regex",a.params.regex)}),a(function(){p.unobtrusive.parse(document)})}(jQuery); -------------------------------------------------------------------------------- /src/ResourceFileServer/.dockerignore: -------------------------------------------------------------------------------- 1 | * 2 | !obj/Docker/publish/* 3 | !obj/Docker/empty/ 4 | -------------------------------------------------------------------------------- /src/ResourceFileServer/Controllers/DownloadController.cs: -------------------------------------------------------------------------------- 1 | using System.Linq; 2 | using Microsoft.AspNetCore.Mvc; 3 | using Microsoft.AspNetCore.Authorization; 4 | using ResourceFileServer.Providers; 5 | using Microsoft.AspNetCore.Hosting; 6 | 7 | namespace ResourceFileServer.Controllers 8 | { 9 | //[Authorize] 10 | [Route("api/[controller]")] 11 | public class DownloadController : Controller 12 | { 13 | private readonly IHostingEnvironment _appEnvironment; 14 | private readonly ISecuredFileProvider _securedFileProvider; 15 | 16 | public DownloadController(ISecuredFileProvider securedFileProvider, IHostingEnvironment appEnvironment) 17 | { 18 | _securedFileProvider = securedFileProvider; 19 | _appEnvironment = appEnvironment; 20 | } 21 | 22 | [AllowAnonymous] 23 | [HttpGet("{accessId}")] 24 | public IActionResult Get(string accessId) 25 | { 26 | var filePath = _securedFileProvider.GetFileIdForUseOnceAccessId(accessId); 27 | if(!string.IsNullOrEmpty(filePath)) 28 | { 29 | var fileContents = System.IO.File.ReadAllBytes(filePath); 30 | return new FileContentResult(fileContents, "application/octet-stream"); 31 | } 32 | 33 | // returning a HTTP Forbidden result. 34 | return new StatusCodeResult(401); 35 | } 36 | 37 | // TODO MUST FIX, user claims validation no longer work since identityserver4 rc4 38 | [Authorize] 39 | //[Authorize("securedFilesUser")] 40 | [HttpGet("GenerateOneTimeAccessToken/{id}")] 41 | public IActionResult GenerateOneTimeAccessToken(string id) 42 | { 43 | if (!_securedFileProvider.FileIdExists(id)) 44 | { 45 | return NotFound($"File id does not exist: {id}"); 46 | } 47 | 48 | var filePath = $"{_appEnvironment.ContentRootPath}/SecuredFileShare/{id}"; 49 | if (!System.IO.File.Exists(filePath)) 50 | { 51 | return NotFound($"File does not exist: {id}"); 52 | } 53 | 54 | var adminClaim = User.Claims.FirstOrDefault(x => x.Type == "role" && x.Value == "securedFiles.admin"); 55 | if (_securedFileProvider.HasUserClaimToAccessFile(id, adminClaim != null)) 56 | { 57 | // TODO generate a one time access token 58 | var oneTimeToken = _securedFileProvider.AddFileIdForUseOnceAccessId(filePath); 59 | return Ok(oneTimeToken); 60 | } 61 | 62 | // returning a HTTP Forbidden result. 63 | return new StatusCodeResult(403); 64 | } 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /src/ResourceFileServer/Controllers/FileExplorerController.cs: -------------------------------------------------------------------------------- 1 | using System.Linq; 2 | using Microsoft.AspNetCore.Mvc; 3 | using Microsoft.AspNetCore.Authorization; 4 | using ResourceFileServer.Providers; 5 | 6 | namespace ResourceFileServer.Controllers 7 | { 8 | [Authorize] 9 | [Route("api/[controller]")] 10 | public class FileExplorerController : Controller 11 | { 12 | private readonly ISecuredFileProvider _securedFileProvider; 13 | 14 | public FileExplorerController(ISecuredFileProvider securedFileProvider) 15 | { 16 | _securedFileProvider = securedFileProvider; 17 | } 18 | 19 | // TODO MUST FIX, user claims validation no longer work since identityserver4 rc4 20 | //[Authorize("securedFilesUser")] 21 | [HttpGet] 22 | public IActionResult Get() 23 | { 24 | // TODO MUST FIX, rc4 update does not work, claims are missing 25 | var adminClaim = User.Claims.FirstOrDefault(x => x.Type == "role" && x.Value == "securedFiles.admin"); 26 | var files = _securedFileProvider.GetFilesForUser(adminClaim != null); 27 | 28 | return Ok(files); 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/ResourceFileServer/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM microsoft/aspnetcore:1.1 2 | ARG source 3 | WORKDIR /app 4 | EXPOSE 80 5 | COPY ${source:-obj/Docker/publish} . 6 | ENTRYPOINT ["dotnet", "ResourceFileServer.dll"] 7 | -------------------------------------------------------------------------------- /src/ResourceFileServer/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "iisSettings": { 3 | "windowsAuthentication": false, 4 | "anonymousAuthentication": true, 5 | "iisExpress": { 6 | "applicationUrl": "https://localhost:44378/", 7 | "sslPort": 44378 8 | } 9 | }, 10 | "profiles": { 11 | "IIS Express": { 12 | "commandName": "IISExpress", 13 | "launchBrowser": true, 14 | "launchUrl": "api/download", 15 | "environmentVariables": { 16 | "Hosting:Environment": "Development" 17 | } 18 | }, 19 | "web": { 20 | "commandName": "web", 21 | "environmentVariables": { 22 | "Hosting:Environment": "Development" 23 | } 24 | } 25 | } 26 | } -------------------------------------------------------------------------------- /src/ResourceFileServer/Providers/ISecuredFileProvider.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | 6 | namespace ResourceFileServer.Providers 7 | { 8 | public interface ISecuredFileProvider 9 | { 10 | bool FileIdExists(string id); 11 | 12 | bool HasUserClaimToAccessFile(string fileId, bool isSecuredFilesAdmin); 13 | 14 | List GetFilesForUser(bool isSecuredFilesAdmin); 15 | string GetFileIdForUseOnceAccessId(string useOnceAccessId); 16 | string AddFileIdForUseOnceAccessId(string filePath); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/ResourceFileServer/Providers/SecureRandom.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Security.Cryptography; 3 | 4 | namespace ResourceFileServer.Providers 5 | { 6 | /// 7 | /// code from: 8 | /// http://stackoverflow.com/questions/4892588/rngcryptoserviceprovider-random-number-review 9 | /// 10 | public class SecureRandom : RandomNumberGenerator 11 | { 12 | private readonly RandomNumberGenerator rng = RandomNumberGenerator.Create(); 13 | 14 | 15 | public int Next() 16 | { 17 | var data = new byte[sizeof(int)]; 18 | rng.GetBytes(data); 19 | return BitConverter.ToInt32(data, 0) & (int.MaxValue - 1); 20 | } 21 | 22 | public int Next(int maxValue) 23 | { 24 | return Next(0, maxValue); 25 | } 26 | 27 | public int Next(int minValue, int maxValue) 28 | { 29 | if (minValue > maxValue) 30 | { 31 | throw new ArgumentOutOfRangeException(); 32 | } 33 | return (int)Math.Floor((minValue + ((double)maxValue - minValue) * NextDouble())); 34 | } 35 | 36 | public double NextDouble() 37 | { 38 | var data = new byte[sizeof(uint)]; 39 | rng.GetBytes(data); 40 | var randUint = BitConverter.ToUInt32(data, 0); 41 | return randUint / (uint.MaxValue + 1.0); 42 | } 43 | 44 | public override void GetBytes(byte[] data) 45 | { 46 | rng.GetBytes(data); 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/ResourceFileServer/Providers/SecuredFileProvider.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | 6 | namespace ResourceFileServer.Providers 7 | { 8 | public class SecuredFileProvider : ISecuredFileProvider 9 | { 10 | private List _fileIds; 11 | 12 | private readonly UseOnceAccessIdService _useOnceAccessIdService; 13 | 14 | public SecuredFileProvider(UseOnceAccessIdService oneTimeTokenService) 15 | { 16 | // create the demo data, this could be data from a database or file provider... 17 | _fileIds = new List { "securefile.txt", "securefileadmin.txt", "securefiletwo.txt" }; 18 | _useOnceAccessIdService = oneTimeTokenService; 19 | } 20 | 21 | public string AddFileIdForUseOnceAccessId(string filePath) 22 | { 23 | return _useOnceAccessIdService.AddFileIdForUseOnceAccessId(filePath); 24 | } 25 | 26 | public bool FileIdExists(string fileId) 27 | { 28 | if(_fileIds.Contains(fileId.ToLower())) 29 | { 30 | return true; 31 | } 32 | 33 | return false; 34 | } 35 | 36 | public string GetFileIdForUseOnceAccessId(string oneTimeToken) 37 | { 38 | return _useOnceAccessIdService.GetFileIdForUseOnceAccessId(oneTimeToken); 39 | } 40 | 41 | public List GetFilesForUser(bool isSecuredFilesAdmin) 42 | { 43 | List files = new List(); 44 | files.Add("SecureFile.txt"); 45 | files.Add("SecureFileTwo.txt"); 46 | 47 | // Use the claims to check if the logged in use has admin rights. 48 | if (isSecuredFilesAdmin) 49 | { 50 | files.Add("SecureFileAdmin.txt"); 51 | } 52 | 53 | return files; 54 | } 55 | 56 | public bool HasUserClaimToAccessFile(string fileId, bool isSecuredFilesAdmin) 57 | { 58 | if ("SecureFileAdmin.txt" == fileId && !isSecuredFilesAdmin) 59 | { 60 | return false; 61 | } 62 | 63 | return true; 64 | 65 | 66 | } 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /src/ResourceFileServer/Providers/UseOnceAccessId.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace ResourceFileServer.Providers 4 | { 5 | internal class UseOnceAccessId 6 | { 7 | public UseOnceAccessId(string fileId) 8 | { 9 | Created = DateTime.UtcNow; 10 | AccessId = CreateAccessId(); 11 | FileId = fileId; 12 | } 13 | 14 | public DateTime Created { get; } 15 | 16 | public string AccessId { get; } 17 | 18 | public string FileId { get; } 19 | 20 | private string CreateAccessId() 21 | { 22 | SecureRandom secureRandom = new SecureRandom(); 23 | return secureRandom.Next() + Guid.NewGuid().ToString(); 24 | } 25 | } 26 | } -------------------------------------------------------------------------------- /src/ResourceFileServer/Providers/UseOnceAccessIdService.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | 6 | namespace ResourceFileServer.Providers 7 | { 8 | public class UseOnceAccessIdService 9 | { 10 | /// 11 | /// One time tokens live for a max of 30 seconds 12 | /// 13 | private double _timeToLive = 30.0; 14 | private static object lockObject = new object(); 15 | 16 | private List _useOnceAccessIds = new List(); 17 | 18 | public string GetFileIdForUseOnceAccessId(string useOnceAccessId) 19 | { 20 | var fileId = string.Empty; 21 | 22 | lock(lockObject) { 23 | 24 | // Max 30 seconds to start download after requesting one time token. 25 | _useOnceAccessIds.RemoveAll(t => t.Created < DateTime.UtcNow.AddSeconds(-_timeToLive)); 26 | 27 | var item = _useOnceAccessIds.FirstOrDefault(t => t.AccessId == useOnceAccessId); 28 | if (item != null) 29 | { 30 | fileId = item.FileId; 31 | _useOnceAccessIds.Remove(item); 32 | } 33 | } 34 | 35 | return fileId; 36 | } 37 | public string AddFileIdForUseOnceAccessId(string filePath) 38 | { 39 | var useOnceAccessId = new UseOnceAccessId(filePath); 40 | lock (lockObject) 41 | { 42 | _useOnceAccessIds.Add(useOnceAccessId); 43 | } 44 | return useOnceAccessId.AccessId; 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/ResourceFileServer/ResourceFileServer.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | netcoreapp1.1 4 | true 5 | ResourceFileServer 6 | Exe 7 | ResourceFileServer 8 | $(PackageTargetFallback);dotnet5.6;portable-net45+win8 9 | aspnet-ResourceFileServer-1e7bf5d8-6c32-4dd3-b77d-2d7d2e0f5093 10 | 11 | 12 | 13 | PreserveNewest 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /src/ResourceFileServer/SecuredFileShare/SecureFile.txt: -------------------------------------------------------------------------------- 1 | This file can only be read when the user has logged in or has access to the containing directory. -------------------------------------------------------------------------------- /src/ResourceFileServer/SecuredFileShare/SecureFileAdmin.txt: -------------------------------------------------------------------------------- 1 | This file can only be read when the user has logged in or has access to the containing directory and has the role admin. -------------------------------------------------------------------------------- /src/ResourceFileServer/SecuredFileShare/SecureFileTwo.txt: -------------------------------------------------------------------------------- 1 | This file can only be read when the user has logged in or has access to the containing directory. -------------------------------------------------------------------------------- /src/ResourceFileServer/Startup.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Authorization; 2 | using Microsoft.AspNetCore.Builder; 3 | using Microsoft.AspNetCore.Hosting; 4 | using Microsoft.Extensions.Configuration; 5 | using Microsoft.Extensions.DependencyInjection; 6 | using Microsoft.Extensions.Logging; 7 | 8 | namespace ResourceFileServer 9 | { 10 | using System.Collections.Generic; 11 | using System.IdentityModel.Tokens.Jwt; 12 | using System.IO; 13 | using Microsoft.AspNetCore.Mvc.Authorization; 14 | using Providers; 15 | public class Startup 16 | { 17 | public Startup(IHostingEnvironment env) 18 | { 19 | var builder = new ConfigurationBuilder() 20 | .SetBasePath(env.ContentRootPath) 21 | .AddJsonFile("appsettings.json"); 22 | Configuration = builder.Build(); 23 | } 24 | 25 | public IConfigurationRoot Configuration { get; set; } 26 | 27 | public void ConfigureServices(IServiceCollection services) 28 | { 29 | //Add Cors support to the service 30 | services.AddCors(); 31 | 32 | var policy = new Microsoft.AspNetCore.Cors.Infrastructure.CorsPolicy(); 33 | 34 | policy.Headers.Add("*"); 35 | policy.Methods.Add("*"); 36 | policy.Origins.Add("*"); 37 | policy.SupportsCredentials = true; 38 | 39 | services.AddCors(x => x.AddPolicy("corsGlobalPolicy", policy)); 40 | 41 | var securedFilesPolicy = new AuthorizationPolicyBuilder() 42 | .RequireAuthenticatedUser() 43 | .RequireClaim("scope", "securedFiles") 44 | .Build(); 45 | 46 | services.AddAuthorization(options => 47 | { 48 | options.AddPolicy("securedFilesUser", policyUser => 49 | { 50 | policyUser.RequireClaim("role", "securedFiles.user"); 51 | }); 52 | }); 53 | 54 | services.AddMvc(options => 55 | { 56 | options.Filters.Add(new AuthorizeFilter(securedFilesPolicy)); 57 | }); 58 | 59 | services.AddMvc(); 60 | 61 | services.AddTransient(); 62 | services.AddSingleton(); 63 | } 64 | 65 | public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory) 66 | { 67 | loggerFactory.AddConsole(Configuration.GetSection("Logging")); 68 | loggerFactory.AddDebug(); 69 | 70 | app.UseCors("corsGlobalPolicy"); 71 | 72 | app.UseStaticFiles(); 73 | 74 | IdentityServerAuthenticationOptions identityServerAuthenticationOptions = new IdentityServerAuthenticationOptions() 75 | { 76 | Authority = "https://localhost:44318/", 77 | AllowedScopes = new List { "securedFiles" }, 78 | ApiSecret = "securedFilesSecret", 79 | ApiName = "securedFiles", 80 | AutomaticAuthenticate = true, 81 | // required if you want to return a 403 and not a 401 for forbidden responses 82 | AutomaticChallenge = true 83 | }; 84 | JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear(); 85 | app.UseIdentityServerAuthentication(identityServerAuthenticationOptions); 86 | 87 | app.UseMvc(); 88 | } 89 | 90 | public static void Main(string[] args) 91 | { 92 | var host = new WebHostBuilder() 93 | .UseKestrel() 94 | .UseContentRoot(Directory.GetCurrentDirectory()) 95 | .UseIISIntegration() 96 | .UseStartup() 97 | .Build(); 98 | 99 | host.Run(); 100 | } 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /src/ResourceFileServer/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "IncludeScopes": false, 4 | "LogLevel": { 5 | "Default": "Debug", 6 | "System": "Information", 7 | "Microsoft": "Information" 8 | } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/ResourceFileServer/runtimeconfig.template.json: -------------------------------------------------------------------------------- 1 | { 2 | "configProperties": { 3 | "System.GC.Server": true 4 | } 5 | } -------------------------------------------------------------------------------- /src/ResourceFileServer/web.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /src/ResourceServer/.dockerignore: -------------------------------------------------------------------------------- 1 | * 2 | !obj/Docker/publish/* 3 | !obj/Docker/empty/ 4 | -------------------------------------------------------------------------------- /src/ResourceServer/Controllers/DataEventRecordController.cs: -------------------------------------------------------------------------------- 1 | using AspNet5SQLite.Model; 2 | using AspNet5SQLite.Repositories; 3 | 4 | using Microsoft.AspNetCore.Authorization; 5 | using Microsoft.AspNetCore.Mvc; 6 | 7 | namespace AspNet5SQLite.Controllers 8 | { 9 | [Authorize] 10 | [Route("api/[controller]")] 11 | public class DataEventRecordsController : Controller 12 | { 13 | private readonly IDataEventRecordRepository _dataEventRecordRepository; 14 | 15 | public DataEventRecordsController(IDataEventRecordRepository dataEventRecordRepository) 16 | { 17 | _dataEventRecordRepository = dataEventRecordRepository; 18 | } 19 | 20 | [Authorize("dataEventRecordsUser")] 21 | [HttpGet] 22 | public IActionResult Get() 23 | { 24 | return Ok(_dataEventRecordRepository.GetAll()); 25 | } 26 | 27 | [Authorize("dataEventRecordsAdmin")] 28 | [HttpGet("{id}")] 29 | public IActionResult Get(long id) 30 | { 31 | return Ok(_dataEventRecordRepository.Get(id)); 32 | } 33 | 34 | [Authorize("dataEventRecordsAdmin")] 35 | [HttpPost] 36 | public void Post([FromBody]DataEventRecord value) 37 | { 38 | _dataEventRecordRepository.Post(value); 39 | } 40 | 41 | [Authorize("dataEventRecordsAdmin")] 42 | [HttpPut("{id}")] 43 | public void Put(long id, [FromBody]DataEventRecord value) 44 | { 45 | _dataEventRecordRepository.Put(id, value); 46 | } 47 | 48 | [Authorize("dataEventRecordsAdmin")] 49 | [HttpDelete("{id}")] 50 | public void Delete(long id) 51 | { 52 | _dataEventRecordRepository.Delete(id); 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/ResourceServer/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM microsoft/aspnetcore:1.1 2 | ARG source 3 | WORKDIR /app 4 | EXPOSE 80 5 | COPY ${source:-obj/Docker/publish} . 6 | ENTRYPOINT ["dotnet", "ResourceServer.dll"] 7 | -------------------------------------------------------------------------------- /src/ResourceServer/Migrations/20160521184959_testMigrations.Designer.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Microsoft.EntityFrameworkCore; 3 | using Microsoft.EntityFrameworkCore.Infrastructure; 4 | using Microsoft.EntityFrameworkCore.Metadata; 5 | using Microsoft.EntityFrameworkCore.Migrations; 6 | using AspNet5SQLite.Model; 7 | 8 | namespace ResourceServer.Migrations 9 | { 10 | [DbContext(typeof(DataEventRecordContext))] 11 | [Migration("20160521184959_testMigrations")] 12 | partial class testMigrations 13 | { 14 | protected override void BuildTargetModel(ModelBuilder modelBuilder) 15 | { 16 | modelBuilder 17 | .HasAnnotation("ProductVersion", "1.0.0-rc2-20896"); 18 | 19 | modelBuilder.Entity("AspNet5SQLite.Model.DataEventRecord", b => 20 | { 21 | b.Property("Id") 22 | .ValueGeneratedOnAdd(); 23 | 24 | b.Property("Description"); 25 | 26 | b.Property("Name"); 27 | 28 | b.Property("Timestamp"); 29 | 30 | b.HasKey("Id"); 31 | 32 | b.ToTable("DataEventRecords"); 33 | }); 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/ResourceServer/Migrations/20160521184959_testMigrations.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using Microsoft.EntityFrameworkCore.Migrations; 4 | 5 | namespace ResourceServer.Migrations 6 | { 7 | public partial class testMigrations : Migration 8 | { 9 | protected override void Up(MigrationBuilder migrationBuilder) 10 | { 11 | migrationBuilder.CreateTable( 12 | name: "DataEventRecords", 13 | columns: table => new 14 | { 15 | Id = table.Column(nullable: false) 16 | .Annotation("Autoincrement", true), 17 | Description = table.Column(nullable: true), 18 | Name = table.Column(nullable: true), 19 | Timestamp = table.Column(nullable: false) 20 | }, 21 | constraints: table => 22 | { 23 | table.PrimaryKey("PK_DataEventRecords", x => x.Id); 24 | }); 25 | } 26 | 27 | protected override void Down(MigrationBuilder migrationBuilder) 28 | { 29 | migrationBuilder.DropTable( 30 | name: "DataEventRecords"); 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/ResourceServer/Migrations/DataEventRecordContextModelSnapshot.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Microsoft.EntityFrameworkCore; 3 | using Microsoft.EntityFrameworkCore.Infrastructure; 4 | using Microsoft.EntityFrameworkCore.Metadata; 5 | using Microsoft.EntityFrameworkCore.Migrations; 6 | using AspNet5SQLite.Model; 7 | 8 | namespace ResourceServer.Migrations 9 | { 10 | [DbContext(typeof(DataEventRecordContext))] 11 | partial class DataEventRecordContextModelSnapshot : ModelSnapshot 12 | { 13 | protected override void BuildModel(ModelBuilder modelBuilder) 14 | { 15 | modelBuilder 16 | .HasAnnotation("ProductVersion", "1.0.0-rc2-20896"); 17 | 18 | modelBuilder.Entity("AspNet5SQLite.Model.DataEventRecord", b => 19 | { 20 | b.Property("Id") 21 | .ValueGeneratedOnAdd(); 22 | 23 | b.Property("Description"); 24 | 25 | b.Property("Name"); 26 | 27 | b.Property("Timestamp"); 28 | 29 | b.HasKey("Id"); 30 | 31 | b.ToTable("DataEventRecords"); 32 | }); 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/ResourceServer/Model/DataEventRecord.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | 6 | namespace AspNet5SQLite.Model 7 | { 8 | // >dnx . ef migration add testMigration 9 | 10 | public class DataEventRecord 11 | { 12 | public long Id { get; set; } 13 | public string Name { get; set; } 14 | 15 | public string Description { get; set; } 16 | 17 | public DateTime Timestamp { get; set; } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/ResourceServer/Model/DataEventRecordContext.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.EntityFrameworkCore; 2 | 3 | namespace AspNet5SQLite.Model 4 | { 5 | // >dotnet ef migration add testMigration 6 | public class DataEventRecordContext : DbContext 7 | { 8 | public DataEventRecordContext(DbContextOptions options) : base(options) 9 | { 10 | } 11 | 12 | public DbSet DataEventRecords { get; set; } 13 | 14 | protected override void OnModelCreating(ModelBuilder builder) 15 | { 16 | builder.Entity().HasKey(m => m.Id); 17 | base.OnModelCreating(builder); 18 | } 19 | } 20 | } -------------------------------------------------------------------------------- /src/ResourceServer/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Linq; 5 | using System.Threading.Tasks; 6 | using Microsoft.AspNetCore.Builder; 7 | using Microsoft.AspNetCore.Hosting; 8 | 9 | namespace AspNet5SQLite 10 | { 11 | public class Program 12 | { 13 | public static void Main(string[] args) 14 | { 15 | var host = new WebHostBuilder() 16 | .UseKestrel() 17 | .UseContentRoot(Directory.GetCurrentDirectory()) 18 | .UseIISIntegration() 19 | .UseStartup() 20 | .UseApplicationInsights() 21 | .Build(); 22 | 23 | host.Run(); 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/ResourceServer/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "iisSettings": { 3 | "windowsAuthentication": false, 4 | "anonymousAuthentication": true, 5 | "iisExpress": { 6 | "applicationUrl": "https://localhost:44390/", 7 | "sslPort": 44390 8 | } 9 | }, 10 | "profiles": { 11 | "IIS Express": { 12 | "commandName": "IISExpress", 13 | "launchBrowser": true, 14 | "launchUrl": "https://localhost:44390/api/DataEventRecords", 15 | "environmentVariables": { 16 | "ASPNETCORE_ENVIRONMENT": "Development" 17 | } 18 | }, 19 | "ResourceServer": { 20 | "commandName": "Project", 21 | "launchUrl": "https://localhost:44390/api/DataEventRecords", 22 | "environmentVariables": { 23 | "ASPNETCORE_ENVIRONMENT": "Development" 24 | }, 25 | "applicationUrl": "https://localhost:44390" 26 | } 27 | } 28 | } -------------------------------------------------------------------------------- /src/ResourceServer/Repositories/DataEventRecordRepository.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | using AspNet5SQLite.Model; 4 | using Microsoft.AspNetCore.Mvc; 5 | using Microsoft.Extensions.Logging; 6 | 7 | namespace AspNet5SQLite.Repositories 8 | { 9 | public class DataEventRecordRepository : IDataEventRecordRepository 10 | { 11 | private readonly DataEventRecordContext _context; 12 | private readonly ILogger _logger; 13 | 14 | public DataEventRecordRepository(DataEventRecordContext context, ILoggerFactory loggerFactory) 15 | { 16 | _context = context; 17 | _logger = loggerFactory.CreateLogger("IDataEventRecordResporitory"); 18 | } 19 | 20 | public List GetAll() 21 | { 22 | _logger.LogCritical("Getting a the existing records"); 23 | return _context.DataEventRecords.ToList(); 24 | } 25 | 26 | public DataEventRecord Get(long id) 27 | { 28 | var dataEventRecord = _context.DataEventRecords.First(t => t.Id == id); 29 | return dataEventRecord; 30 | } 31 | 32 | [HttpPost] 33 | public void Post(DataEventRecord dataEventRecord ) 34 | { 35 | _context.DataEventRecords.Add(dataEventRecord); 36 | _context.SaveChanges(); 37 | } 38 | 39 | public void Put(long id, [FromBody]DataEventRecord dataEventRecord) 40 | { 41 | _context.DataEventRecords.Update(dataEventRecord); 42 | _context.SaveChanges(); 43 | } 44 | 45 | public void Delete(long id) 46 | { 47 | var entity = _context.DataEventRecords.First(t => t.Id == id); 48 | _context.DataEventRecords.Remove(entity); 49 | _context.SaveChanges(); 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/ResourceServer/Repositories/IDataEventRecordRepository.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using AspNet5SQLite.Model; 3 | using Microsoft.AspNetCore.Mvc; 4 | 5 | namespace AspNet5SQLite.Repositories 6 | { 7 | public interface IDataEventRecordRepository 8 | { 9 | void Delete(long id); 10 | DataEventRecord Get(long id); 11 | List GetAll(); 12 | void Post(DataEventRecord dataEventRecord); 13 | void Put(long id, [FromBody] DataEventRecord dataEventRecord); 14 | } 15 | } -------------------------------------------------------------------------------- /src/ResourceServer/ResourceServer.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | netcoreapp1.1 4 | Exe 5 | aspnet-ResourceServer-1e7bf5d8-6c32-4dd3-b77d-2d7d2e0f5094 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | All 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /src/ResourceServer/Startup.cs: -------------------------------------------------------------------------------- 1 | using AspNet5SQLite.Model; 2 | using AspNet5SQLite.Repositories; 3 | using Microsoft.AspNetCore.Builder; 4 | using Microsoft.AspNetCore.Hosting; 5 | using Microsoft.Extensions.Configuration; 6 | using Microsoft.Extensions.DependencyInjection; 7 | using Microsoft.Extensions.Logging; 8 | using System.IO; 9 | using Microsoft.AspNetCore.Authorization; 10 | using System.Security.Cryptography.X509Certificates; 11 | using Microsoft.AspNetCore.Mvc.Authorization; 12 | using Microsoft.EntityFrameworkCore; 13 | using System.IdentityModel.Tokens.Jwt; 14 | using System.Collections.Generic; 15 | using Newtonsoft.Json.Serialization; 16 | using IdentityServer4.AccessTokenValidation; 17 | 18 | namespace AspNet5SQLite 19 | { 20 | public class Startup 21 | { 22 | public IConfigurationRoot Configuration { get; set; } 23 | 24 | private IHostingEnvironment _env { get; set; } 25 | 26 | public Startup(IHostingEnvironment env) 27 | { 28 | _env = env; 29 | var builder = new ConfigurationBuilder() 30 | .SetBasePath(env.ContentRootPath) 31 | .AddJsonFile("config.json"); 32 | Configuration = builder.Build(); 33 | } 34 | 35 | public void ConfigureServices(IServiceCollection services) 36 | { 37 | var connection = Configuration["Production:SqliteConnectionString"]; 38 | var folderForKeyStore = Configuration["Production:KeyStoreFolderWhichIsBacked"]; 39 | 40 | var cert = new X509Certificate2(Path.Combine(_env.ContentRootPath, "damienbodserver.pfx"), ""); 41 | 42 | services.AddDbContext(options => 43 | options.UseSqlite(connection) 44 | ); 45 | 46 | //Add Cors support to the service 47 | services.AddCors(); 48 | 49 | var policy = new Microsoft.AspNetCore.Cors.Infrastructure.CorsPolicy(); 50 | 51 | policy.Headers.Add("*"); 52 | policy.Methods.Add("*"); 53 | policy.Origins.Add("*"); 54 | policy.SupportsCredentials = true; 55 | 56 | services.AddCors(x => x.AddPolicy("corsGlobalPolicy", policy)); 57 | 58 | var guestPolicy = new AuthorizationPolicyBuilder() 59 | .RequireAuthenticatedUser() 60 | .RequireClaim("scope", "dataEventRecords") 61 | .Build(); 62 | 63 | services.AddAuthorization(options => 64 | { 65 | options.AddPolicy("dataEventRecordsAdmin", policyAdmin => 66 | { 67 | policyAdmin.RequireClaim("role", "dataEventRecords.admin"); 68 | }); 69 | options.AddPolicy("dataEventRecordsUser", policyUser => 70 | { 71 | policyUser.RequireClaim("role", "dataEventRecords.user"); 72 | }); 73 | 74 | }); 75 | 76 | services.AddMvc(options => 77 | { 78 | options.Filters.Add(new AuthorizeFilter(guestPolicy)); 79 | }).AddJsonOptions(options => 80 | { 81 | options.SerializerSettings.ContractResolver = new DefaultContractResolver(); 82 | }); 83 | 84 | services.AddScoped(); 85 | } 86 | 87 | public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory) 88 | { 89 | loggerFactory.AddConsole(); 90 | loggerFactory.AddDebug(); 91 | 92 | app.UseExceptionHandler("/Home/Error"); 93 | app.UseCors("corsGlobalPolicy"); 94 | app.UseStaticFiles(); 95 | 96 | JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear(); 97 | IdentityServerAuthenticationOptions identityServerValidationOptions = new IdentityServerAuthenticationOptions 98 | { 99 | Authority = "https://localhost:44318/", 100 | AllowedScopes = new List { "dataEventRecords" }, 101 | ApiSecret = "dataEventRecordsSecret", 102 | ApiName = "dataEventRecords", 103 | AutomaticAuthenticate = true, 104 | SupportedTokens = SupportedTokens.Both, 105 | // TokenRetriever = _tokenRetriever, 106 | // required if you want to return a 403 and not a 401 for forbidden responses 107 | AutomaticChallenge = true, 108 | }; 109 | 110 | app.UseIdentityServerAuthentication(identityServerValidationOptions); 111 | 112 | app.UseMvc(routes => 113 | { 114 | routes.MapRoute( 115 | name: "default", 116 | template: "{controller=Home}/{action=Index}/{id?}"); 117 | }); 118 | } 119 | } 120 | } 121 | -------------------------------------------------------------------------------- /src/ResourceServer/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "Production": { 3 | "SqliteConnectionString": "Data Source=C:\\git\\damienbod\\AspNetCoreIdentityServer4Angular2Docker\\src\\ResourceServer\\dataeventrecords.sqlite" 4 | } 5 | } -------------------------------------------------------------------------------- /src/ResourceServer/damienbodserver.pfx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/damienbod/AspNetCoreIdentityServer4Angular2Docker/2a9866d707945a24d27eb06d694d94f94f3467fa/src/ResourceServer/damienbodserver.pfx -------------------------------------------------------------------------------- /src/ResourceServer/dataeventrecords.sqlite: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/damienbod/AspNetCoreIdentityServer4Angular2Docker/2a9866d707945a24d27eb06d694d94f94f3467fa/src/ResourceServer/dataeventrecords.sqlite -------------------------------------------------------------------------------- /src/ResourceServer/runtimeconfig.template.json: -------------------------------------------------------------------------------- 1 | { 2 | "configProperties": { 3 | "System.GC.Server": true 4 | } 5 | } -------------------------------------------------------------------------------- /src/ResourceServer/web.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | --------------------------------------------------------------------------------