From 585ac7c672a37acf1c7ebe1591119292855f65c4 Mon Sep 17 00:00:00 2001 From: Michele Date: Sat, 7 Nov 2020 11:45:16 +0000 Subject: [PATCH] add identity server --- Identity/.vscode/launch.json | 34 +++++++++++ Identity/.vscode/tasks.json | 42 +++++++++++++ Identity/IdentityServer/Config.cs | 39 ++++++++++++ Identity/IdentityServer/IdentityServer.csproj | 12 ++++ Identity/IdentityServer/Program.cs | 60 +++++++++++++++++++ .../Properties/launchSettings.json | 12 ++++ Identity/IdentityServer/Startup.cs | 60 +++++++++++++++++++ Identity/IdentityServer/tempkey.jwk | 1 + .../Controllers/IdentityController.cs | 18 ++++++ Sledgemapper.Api/Hubs/SledgemapperHub.cs | 2 +- Sledgemapper.Api/Sledgemapper.Api.csproj | 1 + Sledgemapper.Api/Startup.cs | 18 +++++- 12 files changed, 297 insertions(+), 2 deletions(-) create mode 100644 Identity/.vscode/launch.json create mode 100644 Identity/.vscode/tasks.json create mode 100644 Identity/IdentityServer/Config.cs create mode 100644 Identity/IdentityServer/IdentityServer.csproj create mode 100644 Identity/IdentityServer/Program.cs create mode 100644 Identity/IdentityServer/Properties/launchSettings.json create mode 100644 Identity/IdentityServer/Startup.cs create mode 100644 Identity/IdentityServer/tempkey.jwk create mode 100644 Sledgemapper.Api/Controllers/IdentityController.cs diff --git a/Identity/.vscode/launch.json b/Identity/.vscode/launch.json new file mode 100644 index 0000000..d76e9fe --- /dev/null +++ b/Identity/.vscode/launch.json @@ -0,0 +1,34 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "name": ".NET Core Launch (web)", + "type": "coreclr", + "request": "launch", + "preLaunchTask": "build", + "program": "${workspaceFolder}/IdentityServer/bin/Debug/netcoreapp3.1/IdentityServer.dll", + "args": [], + "cwd": "${workspaceFolder}/IdentityServer", + "stopAtEntry": false, + "serverReadyAction": { + "action": "openExternally", + "pattern": "\\bNow listening on:\\s+(https?://\\S+)" + }, + "env": { + "ASPNETCORE_ENVIRONMENT": "Development" + }, + "sourceFileMap": { + "/Views": "${workspaceFolder}/Views" + } + }, + { + "name": ".NET Core Attach", + "type": "coreclr", + "request": "attach", + "processId": "${command:pickProcess}" + } + ] +} \ No newline at end of file diff --git a/Identity/.vscode/tasks.json b/Identity/.vscode/tasks.json new file mode 100644 index 0000000..51a2278 --- /dev/null +++ b/Identity/.vscode/tasks.json @@ -0,0 +1,42 @@ +{ + "version": "2.0.0", + "tasks": [ + { + "label": "build", + "command": "dotnet", + "type": "process", + "args": [ + "build", + "${workspaceFolder}/IdentityServer/IdentityServer.csproj", + "/property:GenerateFullPaths=true", + "/consoleloggerparameters:NoSummary" + ], + "problemMatcher": "$msCompile" + }, + { + "label": "publish", + "command": "dotnet", + "type": "process", + "args": [ + "publish", + "${workspaceFolder}/IdentityServer/IdentityServer.csproj", + "/property:GenerateFullPaths=true", + "/consoleloggerparameters:NoSummary" + ], + "problemMatcher": "$msCompile" + }, + { + "label": "watch", + "command": "dotnet", + "type": "process", + "args": [ + "watch", + "run", + "${workspaceFolder}/IdentityServer/IdentityServer.csproj", + "/property:GenerateFullPaths=true", + "/consoleloggerparameters:NoSummary" + ], + "problemMatcher": "$msCompile" + } + ] +} \ No newline at end of file diff --git a/Identity/IdentityServer/Config.cs b/Identity/IdentityServer/Config.cs new file mode 100644 index 0000000..267d417 --- /dev/null +++ b/Identity/IdentityServer/Config.cs @@ -0,0 +1,39 @@ +// Copyright (c) Brock Allen & Dominick Baier. All rights reserved. +// Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information. + + +using IdentityServer4.Models; +using System.Collections.Generic; + +namespace IdentityServer +{ + public static class Config + { + public static IEnumerable ApiScopes => + new List + { + new ApiScope("seldgemapperApi", "Sledgemapper API") + }; + + public static IEnumerable Clients => + new List + { + new Client + { + ClientId = "client", + + // no interactive user, use the clientid/secret for authentication + AllowedGrantTypes = GrantTypes.ClientCredentials, + + // secret for authentication + ClientSecrets = + { + new Secret("secret".Sha256()) + }, + + // scopes that client has access to + AllowedScopes = { "seldgemapperApi" } + } + }; + } +} \ No newline at end of file diff --git a/Identity/IdentityServer/IdentityServer.csproj b/Identity/IdentityServer/IdentityServer.csproj new file mode 100644 index 0000000..266e57d --- /dev/null +++ b/Identity/IdentityServer/IdentityServer.csproj @@ -0,0 +1,12 @@ + + + + netcoreapp3.1 + + + + + + + + diff --git a/Identity/IdentityServer/Program.cs b/Identity/IdentityServer/Program.cs new file mode 100644 index 0000000..4b2199f --- /dev/null +++ b/Identity/IdentityServer/Program.cs @@ -0,0 +1,60 @@ +// Copyright (c) Brock Allen & Dominick Baier. All rights reserved. +// Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information. + + +using Microsoft.AspNetCore.Hosting; +using Microsoft.Extensions.Hosting; +using Serilog; +using Serilog.Events; +using Serilog.Sinks.SystemConsole.Themes; +using System; + +namespace IdentityServer +{ + public class Program + { + public static int Main(string[] args) + { + Log.Logger = new LoggerConfiguration() + .MinimumLevel.Debug() + .MinimumLevel.Override("Microsoft", LogEventLevel.Warning) + .MinimumLevel.Override("Microsoft.Hosting.Lifetime", LogEventLevel.Information) + .MinimumLevel.Override("System", LogEventLevel.Warning) + .MinimumLevel.Override("Microsoft.AspNetCore.Authentication", LogEventLevel.Information) + .Enrich.FromLogContext() + // uncomment to write to Azure diagnostics stream + //.WriteTo.File( + // @"D:\home\LogFiles\Application\identityserver.txt", + // fileSizeLimitBytes: 1_000_000, + // rollOnFileSizeLimit: true, + // shared: true, + // flushToDiskInterval: TimeSpan.FromSeconds(1)) + .WriteTo.Console(outputTemplate: "[{Timestamp:HH:mm:ss} {Level}] {SourceContext}{NewLine}{Message:lj}{NewLine}{Exception}{NewLine}", theme: AnsiConsoleTheme.Code) + .CreateLogger(); + + try + { + Log.Information("Starting host..."); + CreateHostBuilder(args).Build().Run(); + return 0; + } + catch (Exception ex) + { + Log.Fatal(ex, "Host terminated unexpectedly."); + return 1; + } + finally + { + Log.CloseAndFlush(); + } + } + + public static IHostBuilder CreateHostBuilder(string[] args) => + Host.CreateDefaultBuilder(args) + .UseSerilog() + .ConfigureWebHostDefaults(webBuilder => + { + webBuilder.UseStartup(); + }); + } +} \ No newline at end of file diff --git a/Identity/IdentityServer/Properties/launchSettings.json b/Identity/IdentityServer/Properties/launchSettings.json new file mode 100644 index 0000000..6f874f1 --- /dev/null +++ b/Identity/IdentityServer/Properties/launchSettings.json @@ -0,0 +1,12 @@ +{ + "profiles": { + "SelfHost": { + "commandName": "Project", + "launchBrowser": true, + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + }, + "applicationUrl": "https://localhost:5001" + } + } +} \ No newline at end of file diff --git a/Identity/IdentityServer/Startup.cs b/Identity/IdentityServer/Startup.cs new file mode 100644 index 0000000..4f9e397 --- /dev/null +++ b/Identity/IdentityServer/Startup.cs @@ -0,0 +1,60 @@ +// Copyright (c) Brock Allen & Dominick Baier. All rights reserved. +// Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information. + + +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Hosting; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; + +namespace IdentityServer +{ + public class Startup + { + public IWebHostEnvironment Environment { get; } + + public Startup(IWebHostEnvironment environment) + { + Environment = environment; + } + + public void ConfigureServices(IServiceCollection services) + { + // uncomment, if you want to add an MVC-based UI + //services.AddControllersWithViews(); + + var builder = services.AddIdentityServer(options => + { + // see https://identityserver4.readthedocs.io/en/latest/topics/resources.html + options.EmitStaticAudienceClaim = true; + }) + // .AddInMemoryIdentityResources(Config.IdentityResources) + .AddInMemoryApiScopes(Config.ApiScopes) + .AddInMemoryClients(Config.Clients); + + // not recommended for production - you need to store your key material somewhere secure + builder.AddDeveloperSigningCredential(); + } + + public void Configure(IApplicationBuilder app) + { + if (Environment.IsDevelopment()) + { + app.UseDeveloperExceptionPage(); + } + + // uncomment if you want to add MVC + //app.UseStaticFiles(); + //app.UseRouting(); + + app.UseIdentityServer(); + + // uncomment, if you want to add MVC + //app.UseAuthorization(); + //app.UseEndpoints(endpoints => + //{ + // endpoints.MapDefaultControllerRoute(); + //}); + } + } +} diff --git a/Identity/IdentityServer/tempkey.jwk b/Identity/IdentityServer/tempkey.jwk new file mode 100644 index 0000000..cce2239 --- /dev/null +++ b/Identity/IdentityServer/tempkey.jwk @@ -0,0 +1 @@ +{"alg":"RS256","d":"u88MEy28-4hRvzgL8MRiihCCqiNRJMkslHMr4NX64Xe_3MIxsfDsp-PF69y8OXYl_wlpWwshosmxBWWiRQNEFyJd6XnuLbOPPbEAvvApCDYEAiVqa9K40pCUPL2ICKk_Ix2qAjDzBAAK8Jvyrl_sth4JSw0IOHrZ77dtljLroII9EZaCcFEaUtFt58zKTg0fphqpZJUPjyAcabtHPCEfJKJFpPulnqOQA_BGhbT3Vpdo-N8gtLbVGzIbe5eOMxXf637STyfBrvkJN9BWQMm46H1XWoDaOD34ZbdbIC84xQn9igLeA1QCLP4C4NNNCkdcqpwd2nE7YoSS9PMOwqR-NQ","dp":"POSsdi7VV0EM843kV59KwLn8hYWTjcG6ACZMK5kKVDJ4tm6CDLJ-1MxCaSQwo2jJ6bRRATNLfmjfePU9qEuQ89oomZ-y0KeppKtwaGbsBPLv3LAjacwSzHY6jHvlEa04BZIHqjQc7MMBzARG68sAc3sbfYGwqGSSEtr01bfMAps","dq":"vGkZsdK_bg71EfDoHBAvknNPcXZ3gIjHxYiSZW8r5ZEawe862wcZcMAzI4PkkNcM9jJxWEWmKZvKORFVJstpdgrpNddblWbw4po_QySe2XBtyh1eplYybmZ7-HWdY-ogkJBWtzUdifGqhyjCtgkxV46pPWse3i_ymVV31Wt6Rak","e":"AQAB","kid":"28F80A128E9BFE8960B690D9A7AB7C83","kty":"RSA","n":"1gLbbP6yT36nnrkn6tBbJyulnhMA13uA8_588b4GBkCTFi4v9R193EJQCg28l6cm-_E93mnlc-_C4-ul1MSoUXehOZxayMzGlMANUVBCRUhazfY8lf3bf0vY1enGOYYQVl-_5w0PhoO5H1zIC7ohYkogivnOIH-QO9RrgwgBwpkm58rsT1pOscFrVKSWObp7_pHksBd3uXFnIDlIdvOGcptyD5YoYteS34Z3GRlgmvdm6Sq4oEwk_zgSWwiDLJtzFQsc4OGVoOBFRO0BxrF6CVrp6nEni6toYLyEHpwqoM56if07RSCihY2CqNFBM_FZa6V1YumC67pdWsjFjitxIQ","p":"3F_djAqfvrj-oyYDC_C1oKUTqDaGp-7OcwxKC86bCiWzeiS71gzbj1i5b4hCfjQgUsJNvpu15ETmc-buKstxjR0AJwVy5K5AjXAh-3BDzCHThVnIeG_NAK3PUtUsgpkfooBLClvnaiahDw55mqrqR2I4huFIkH5cE-s-OYuCq6M","q":"-Jul1jY6mO2F1DMESxaYIAMkvkh-dXn9420_olMs6Eu0-FyDGAdc1kzry0HJ94ZEOk0v8sI-jD8GZUncdQY_jHxGWUYqqQfDhJp4rYgkxUI89Odd40j3l2UDr1rY-ue3PHlY6xf17yGbpCXnS3UUhIaCPMKFmq62LXCi2N2WvGs","qi":"AmReUGiL7X8GwXiv_tjpqFwrGslqFkoIYz0Kq26MCTapDk0O8_qgdE5o5wdI2v87rvEGrGwY8vmmW0Okcfu52xxYxpp28-QPbTnjKCsQbsA7jOV7nejWqeQMTjdSzDd2lY0zvof_xLlHDr9ov2Qigj7ZUwqQ3xzdaAvziDQ0LdE"} \ No newline at end of file diff --git a/Sledgemapper.Api/Controllers/IdentityController.cs b/Sledgemapper.Api/Controllers/IdentityController.cs new file mode 100644 index 0000000..d542dc3 --- /dev/null +++ b/Sledgemapper.Api/Controllers/IdentityController.cs @@ -0,0 +1,18 @@ +using System.Linq; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Authorization; + +namespace Sledgemapper.Api.Controllers +{ + [Route("identity")] +[Authorize] +public class IdentityController : ControllerBase +{ + [HttpGet] + public IActionResult Get() + { + return new JsonResult(from c in User.Claims select new { c.Type, c.Value }); + } +} + +} \ No newline at end of file diff --git a/Sledgemapper.Api/Hubs/SledgemapperHub.cs b/Sledgemapper.Api/Hubs/SledgemapperHub.cs index a0b3ffa..41db0dd 100644 --- a/Sledgemapper.Api/Hubs/SledgemapperHub.cs +++ b/Sledgemapper.Api/Hubs/SledgemapperHub.cs @@ -19,7 +19,7 @@ namespace SignalRChat.Hubs private readonly MyDbContext _dbcontext; // public SledgemapperHub(IMediator mediator) => _mediator = mediator; - public SledgemapperHub(MyDbContext dbcontext, IMediator _mediator) =>{ _dbcontext = dbcontext; _mediator=mediator}; + public SledgemapperHub(MyDbContext dbcontext, IMediator mediator) { _dbcontext = dbcontext; _mediator=mediator;} private static Dictionary _sessions = new Dictionary(); public List Colors = new List{"CC0000", "CC3300", diff --git a/Sledgemapper.Api/Sledgemapper.Api.csproj b/Sledgemapper.Api/Sledgemapper.Api.csproj index fb38178..6bbf6f5 100644 --- a/Sledgemapper.Api/Sledgemapper.Api.csproj +++ b/Sledgemapper.Api/Sledgemapper.Api.csproj @@ -7,6 +7,7 @@ + runtime; build; native; contentfiles; analyzers; buildtransitive all diff --git a/Sledgemapper.Api/Startup.cs b/Sledgemapper.Api/Startup.cs index 866ad10..87a5830 100644 --- a/Sledgemapper.Api/Startup.cs +++ b/Sledgemapper.Api/Startup.cs @@ -12,6 +12,8 @@ using SignalRChat.Hubs; using MediatR.Pipeline; using Sledgemapper.Api.Data; using Microsoft.EntityFrameworkCore; +using MediatR; +using Microsoft.IdentityModel.Tokens; namespace SignalRChat { @@ -30,10 +32,19 @@ namespace SignalRChat { services.AddRazorPages(); services.AddSignalR(); - // services.AddMediatR(typeof(Startup)); + services.AddMediatR(typeof(Startup)); services.AddDbContext(options => options.UseSqlite("Data Source=sledgemapper.db")); // services.AddEntityFrameworkSqlite().AddDbContext(); + services.AddAuthentication("Bearer") + .AddJwtBearer("Bearer", options => + { + options.Authority = "https://localhost:5001"; + options.TokenValidationParameters = new TokenValidationParameters + { + ValidateAudience = false + }; + }); } @@ -58,6 +69,11 @@ namespace SignalRChat app.UseAuthorization(); + app.UseEndpoints(endpoints => + { + endpoints.MapControllers(); + }); + app.UseEndpoints(endpoints => { endpoints.MapRazorPages();