diff --git a/.gitignore b/.gitignore index 0b62f8f..79b9a24 100644 --- a/.gitignore +++ b/.gitignore @@ -197,7 +197,6 @@ ClientBin/ *.dbmdl *.dbproj.schemaview *.jfm -*.pfx *.publishsettings orleans.codegen.cs @@ -287,4 +286,5 @@ __pycache__/ *.odx.cs *.xsd.cs -**/identityserver4_log.txt \ No newline at end of file +**/identityserver4_log.txt +**/openiddict-identity.db diff --git a/DuendeIdentityServer/DuendeDynamicProviders/DuendeDynamicProviders.csproj b/DuendeIdentityServer/DuendeDynamicProviders/DuendeDynamicProviders.csproj index b8969e8..6cb0bc9 100644 --- a/DuendeIdentityServer/DuendeDynamicProviders/DuendeDynamicProviders.csproj +++ b/DuendeIdentityServer/DuendeDynamicProviders/DuendeDynamicProviders.csproj @@ -7,10 +7,10 @@ - - - - + + + + diff --git a/DuendeIdentityServer/DuendeDynamicProviders/Pages/Account/Logout/Index.cshtml.cs b/DuendeIdentityServer/DuendeDynamicProviders/Pages/Account/Logout/Index.cshtml.cs index d4e1f8e..aa4d82f 100644 --- a/DuendeIdentityServer/DuendeDynamicProviders/Pages/Account/Logout/Index.cshtml.cs +++ b/DuendeIdentityServer/DuendeDynamicProviders/Pages/Account/Logout/Index.cshtml.cs @@ -1,7 +1,7 @@ +using Duende.IdentityModel; using Duende.IdentityServer.Events; using Duende.IdentityServer.Extensions; using Duende.IdentityServer.Services; -using IdentityModel; using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; diff --git a/DuendeIdentityServer/DuendeDynamicProviders/Pages/Consent/Index.cshtml.cs b/DuendeIdentityServer/DuendeDynamicProviders/Pages/Consent/Index.cshtml.cs index 953955e..f1f1bb4 100644 --- a/DuendeIdentityServer/DuendeDynamicProviders/Pages/Consent/Index.cshtml.cs +++ b/DuendeIdentityServer/DuendeDynamicProviders/Pages/Consent/Index.cshtml.cs @@ -1,9 +1,9 @@ +using Duende.IdentityModel; using Duende.IdentityServer.Events; using Duende.IdentityServer.Extensions; using Duende.IdentityServer.Models; using Duende.IdentityServer.Services; using Duende.IdentityServer.Validation; -using IdentityModel; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.RazorPages; diff --git a/DuendeIdentityServer/DuendeDynamicProviders/Pages/Diagnostics/ViewModel.cs b/DuendeIdentityServer/DuendeDynamicProviders/Pages/Diagnostics/ViewModel.cs index 1f5a7eb..5eb2ae5 100644 --- a/DuendeIdentityServer/DuendeDynamicProviders/Pages/Diagnostics/ViewModel.cs +++ b/DuendeIdentityServer/DuendeDynamicProviders/Pages/Diagnostics/ViewModel.cs @@ -1,11 +1,9 @@ // Copyright (c) Duende Software. All rights reserved. // See LICENSE in the project root for license information. - - -using IdentityModel; using Microsoft.AspNetCore.Authentication; using System.Text; using System.Text.Json; +using Duende.IdentityModel; namespace DuendeDynamicProviders.Pages.Diagnostics; diff --git a/DuendeIdentityServer/DuendeDynamicProviders/Pages/ExternalLogin/Callback.cshtml.cs b/DuendeIdentityServer/DuendeDynamicProviders/Pages/ExternalLogin/Callback.cshtml.cs index 41c37ca..22b1c5f 100644 --- a/DuendeIdentityServer/DuendeDynamicProviders/Pages/ExternalLogin/Callback.cshtml.cs +++ b/DuendeIdentityServer/DuendeDynamicProviders/Pages/ExternalLogin/Callback.cshtml.cs @@ -1,9 +1,9 @@ using System.Security.Claims; +using Duende.IdentityModel; using Duende.IdentityServer; using Duende.IdentityServer.Events; using Duende.IdentityServer.Services; using Duende.IdentityServer.Test; -using IdentityModel; using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; diff --git a/DuendeIdentityServer/DuendeDynamicProviders/Pages/TestUsers.cs b/DuendeIdentityServer/DuendeDynamicProviders/Pages/TestUsers.cs index 06e4a13..4603c06 100644 --- a/DuendeIdentityServer/DuendeDynamicProviders/Pages/TestUsers.cs +++ b/DuendeIdentityServer/DuendeDynamicProviders/Pages/TestUsers.cs @@ -1,10 +1,9 @@ // Copyright (c) Duende Software. All rights reserved. // See LICENSE in the project root for license information. - -using IdentityModel; using System.Security.Claims; using System.Text.Json; +using Duende.IdentityModel; using Duende.IdentityServer; using Duende.IdentityServer.Test; diff --git a/DuendeIdentityServer/DuendeIdP/DuendeIdP.csproj b/DuendeIdentityServer/DuendeIdP/DuendeIdP.csproj index f010e93..2557764 100644 --- a/DuendeIdentityServer/DuendeIdP/DuendeIdP.csproj +++ b/DuendeIdentityServer/DuendeIdP/DuendeIdP.csproj @@ -10,10 +10,9 @@ - - - - - + + + + \ No newline at end of file diff --git a/DuendeIdentityServer/DuendeIdP/Pages/Account/Logout/Index.cshtml.cs b/DuendeIdentityServer/DuendeIdP/Pages/Account/Logout/Index.cshtml.cs index ed5ea66..a5ad19c 100644 --- a/DuendeIdentityServer/DuendeIdP/Pages/Account/Logout/Index.cshtml.cs +++ b/DuendeIdentityServer/DuendeIdP/Pages/Account/Logout/Index.cshtml.cs @@ -1,7 +1,7 @@ +using Duende.IdentityModel; using Duende.IdentityServer.Events; using Duende.IdentityServer.Extensions; using Duende.IdentityServer.Services; -using IdentityModel; using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; diff --git a/DuendeIdentityServer/DuendeIdP/Pages/Consent/Index.cshtml.cs b/DuendeIdentityServer/DuendeIdP/Pages/Consent/Index.cshtml.cs index ca7cc80..55478f8 100644 --- a/DuendeIdentityServer/DuendeIdP/Pages/Consent/Index.cshtml.cs +++ b/DuendeIdentityServer/DuendeIdP/Pages/Consent/Index.cshtml.cs @@ -1,9 +1,9 @@ +using Duende.IdentityModel; using Duende.IdentityServer.Events; using Duende.IdentityServer.Extensions; using Duende.IdentityServer.Models; using Duende.IdentityServer.Services; using Duende.IdentityServer.Validation; -using IdentityModel; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.RazorPages; diff --git a/DuendeIdentityServer/DuendeIdP/Pages/Diagnostics/ViewModel.cs b/DuendeIdentityServer/DuendeIdP/Pages/Diagnostics/ViewModel.cs index 7c1f9a3..9fe2a6a 100644 --- a/DuendeIdentityServer/DuendeIdP/Pages/Diagnostics/ViewModel.cs +++ b/DuendeIdentityServer/DuendeIdP/Pages/Diagnostics/ViewModel.cs @@ -2,10 +2,10 @@ // See LICENSE in the project root for license information. -using IdentityModel; using Microsoft.AspNetCore.Authentication; using System.Text; using System.Text.Json; +using Duende.IdentityModel; namespace DuendeIdP.Pages.Diagnostics; diff --git a/DuendeIdentityServer/DuendeIdP/Pages/ExternalLogin/Callback.cshtml.cs b/DuendeIdentityServer/DuendeIdP/Pages/ExternalLogin/Callback.cshtml.cs index 8c96a6c..ddfff7f 100644 --- a/DuendeIdentityServer/DuendeIdP/Pages/ExternalLogin/Callback.cshtml.cs +++ b/DuendeIdentityServer/DuendeIdP/Pages/ExternalLogin/Callback.cshtml.cs @@ -1,9 +1,9 @@ using System.Security.Claims; +using Duende.IdentityModel; using Duende.IdentityServer; using Duende.IdentityServer.Events; using Duende.IdentityServer.Services; using Duende.IdentityServer.Test; -using IdentityModel; using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; diff --git a/DuendeIdentityServer/DuendeIdP/Pages/TestUsers.cs b/DuendeIdentityServer/DuendeIdP/Pages/TestUsers.cs index 92cc553..2d452c0 100644 --- a/DuendeIdentityServer/DuendeIdP/Pages/TestUsers.cs +++ b/DuendeIdentityServer/DuendeIdP/Pages/TestUsers.cs @@ -2,9 +2,9 @@ // See LICENSE in the project root for license information. -using IdentityModel; using System.Security.Claims; using System.Text.Json; +using Duende.IdentityModel; using Duende.IdentityServer; using Duende.IdentityServer.Test; diff --git a/DuendeIdentityServer/SLO/SamlOidcSLO/Common/TestConstants.cs b/DuendeIdentityServer/SLO/SamlOidcSLO/Common/TestConstants.cs index abdcfac..0877b71 100644 --- a/DuendeIdentityServer/SLO/SamlOidcSLO/Common/TestConstants.cs +++ b/DuendeIdentityServer/SLO/SamlOidcSLO/Common/TestConstants.cs @@ -2,6 +2,6 @@ public static class TestConstants { - public static string LicenseKey = "eyJTb2xkRm9yIjowLjAsIktleVByZXNldCI6NiwiU2F2ZUtleSI6ZmFsc2UsIkxlZ2FjeUtleSI6ZmFsc2UsIlJlbmV3YWxTZW50VGltZSI6IjAwMDEtMDEtMDFUMDA6MDA6MDAiLCJhdXRoIjoiREVNTyIsImV4cCI6IjIwMjMtMDUtMTlUMDE6MDA6MDAuNzA3NTI2NiswMDowMCIsImlhdCI6IjIwMjMtMDQtMTlUMDE6MDA6MDAiLCJvcmciOiJERU1PIiwiYXVkIjoyfQ==.TOLSabk8Uf3jNF908d6r3jj9NzRPNExgZ1qqZMyBWkJ0Fpi+RESseOs7Dj8xtSdxt9SoCn4VnomVZnWA4alV3gDnAKIIatMgT8YzCr5Y/IrgEmJmRTb7jNDd5azBrgjCDNmjI8clx5UzGwLfuL1+K72KjsAq1R6DvAZdFiJ0Ggtw4sCocGfhjKrPbDo6izyc3A6EOtgOL0TDLuqxsPm0vPkHB/NRxUsVAGaiLwhu65Wz9iLMGx9BJIIpTr5frGAfrpmv4brjCe92jZcBuCMWgQPVxJKbGzZqNhK8m1uqiLvSdvdoymsvccLaKeVa8APeaq0KROJu9KqPKNg0R/anSYfwBz88L9CgqszLNYRynK4pcSm52POd3g4ulhtZ5vcvRDDI3W3rgw6LO4Et8iQ6SXU/JEhSIjbmqAbKCnQErUDYT8/k2qpIy5W9Sy14F4OkueW1i19R6UcLQVcRztbGUFz7rGRUwbStWS+Eb1sFjDjFzoEGxQhgy/GW/MNUGFF39KVUfZaYTWuz9MvgsXc7exrmT/zKsTjC6GB0wSFcRK5I34T7aIymC95rPHwAqFzfOr2FNt6DvJXogS7VWS+tJkVAHxVYB/stXT3+eBLU9Qa3Su2nZ36YdrYAMIBJmFwiQMq52QAi2/1/2a2e0nrKFTQJh3tdnQGtG2ZjXRtvdWo="; + public static string LicenseKey = "eyJhdXRoIjoiREVNTyIsImV4cCI6IjIwMjUtMDgtMDZUMDA6MDA6MDEuNjEyNDg5OSswMDowMCIsImlhdCI6IjIwMjUtMDctMDdUMDA6MDA6MDEuOTY4MzEwN1oiLCJvcmciOiJERU1PIiwiYXVkIjoyfQ==.mpi6l7DsJzzHordvTgShzMOf5qny1dMPT3BN2TTr2U42aG6ySUGuZ6U1rqtzdAmS872Mt95x+T5e5qajVpcbxweeYKFDpNcE5X8bEzTGThoLrEtsCdbK7zxN5GHTn4d2zggxKCVPMkddYDMbbQ4eEkfhKL0rlDijZ2maaRYGvPZG4u2cMH3zmS+vzWqCDR31yTSEEGoJp43S1PxMO6iTg8FvZAtnCVO2/hT2+At9mqkEvsdtT90oM7gXdGQxLsiplt1jwCfuE9okkvYJ/mZm3amoQeE2OX4Dayu1zBTgzH74qi8cJrFTnnXbYXC3g26mW6vm8x8JoafJFZe0YDHqMAFqknNMFgfGyLlASIXyAPXnI1xdYIf6VZJ4u6w4Ib2nj+i4CVwzqYwgyOvf9in4EMSHaGrAWbk/PT1P2eprVZREmaRnJYAHOHYbqYyD9WIhsiaDE6grCFNGQ0Vxp/1FL/wsvITXLwdm4A+VnlNotEJpmcM2jjc13JBlO7ocvXnK5Bdq+NkSxNtpAL7ZWrhc2WoqVbGvZR8ibHVh1BLjzEpjVKKolgio5lho3IZDpYXhYgsqbc6qtfutRoGfQ5TcpagVrWXWQ8dYzE/E2oU4XSrJcNC0g+3D7lDjXolgWjnGM1TGDWovidg6fp8f1DgR5+6cSzzrD3FshJjkt/xVy9g="; public static string Licensee = "DEMO"; } \ No newline at end of file diff --git a/DuendeIdentityServer/SLO/SamlOidcSLO/IdentityServer/Config.cs b/DuendeIdentityServer/SLO/SamlOidcSLO/IdentityServer/Config.cs index 3e2e0db..6ffa293 100644 --- a/DuendeIdentityServer/SLO/SamlOidcSLO/IdentityServer/Config.cs +++ b/DuendeIdentityServer/SLO/SamlOidcSLO/IdentityServer/Config.cs @@ -1,7 +1,7 @@ using System.Security.Cryptography.X509Certificates; +using Duende.IdentityModel; using Duende.IdentityServer; using Duende.IdentityServer.Models; -using IdentityModel; using Rsk.Saml; using Rsk.Saml.Models; using ServiceProvider = Rsk.Saml.Models.ServiceProvider; diff --git a/DuendeIdentityServer/SLO/SamlOidcSLO/IdentityServer/IdentityServer.csproj b/DuendeIdentityServer/SLO/SamlOidcSLO/IdentityServer/IdentityServer.csproj index 60b98cf..5940aec 100644 --- a/DuendeIdentityServer/SLO/SamlOidcSLO/IdentityServer/IdentityServer.csproj +++ b/DuendeIdentityServer/SLO/SamlOidcSLO/IdentityServer/IdentityServer.csproj @@ -5,24 +5,24 @@ 38ced442-cf32-4289-bb08-57d4a78831b3 - - - - - - - - + + + + + + + + - - - - - - - - - + + + + + + + + + diff --git a/DuendeIdentityServer/SLO/SamlOidcSLO/IdentityServer/Pages/Account/Logout/Index.cshtml.cs b/DuendeIdentityServer/SLO/SamlOidcSLO/IdentityServer/Pages/Account/Logout/Index.cshtml.cs index 10c2053..0ae620f 100644 --- a/DuendeIdentityServer/SLO/SamlOidcSLO/IdentityServer/Pages/Account/Logout/Index.cshtml.cs +++ b/DuendeIdentityServer/SLO/SamlOidcSLO/IdentityServer/Pages/Account/Logout/Index.cshtml.cs @@ -1,8 +1,8 @@ using System.Threading.Tasks; +using Duende.IdentityModel; using Duende.IdentityServer.Events; using Duende.IdentityServer.Extensions; using Duende.IdentityServer.Services; -using IdentityModel; using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; diff --git a/DuendeIdentityServer/SLO/SamlOidcSLO/IdentityServer/Pages/Consent/Index.cshtml.cs b/DuendeIdentityServer/SLO/SamlOidcSLO/IdentityServer/Pages/Consent/Index.cshtml.cs index a743e71..84763e9 100644 --- a/DuendeIdentityServer/SLO/SamlOidcSLO/IdentityServer/Pages/Consent/Index.cshtml.cs +++ b/DuendeIdentityServer/SLO/SamlOidcSLO/IdentityServer/Pages/Consent/Index.cshtml.cs @@ -2,12 +2,12 @@ using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; +using Duende.IdentityModel; using Duende.IdentityServer.Events; using Duende.IdentityServer.Extensions; using Duende.IdentityServer.Models; using Duende.IdentityServer.Services; using Duende.IdentityServer.Validation; -using IdentityModel; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.RazorPages; diff --git a/DuendeIdentityServer/SLO/SamlOidcSLO/IdentityServer/Pages/TestUsers.cs b/DuendeIdentityServer/SLO/SamlOidcSLO/IdentityServer/Pages/TestUsers.cs index 2db9cc4..f4e1353 100644 --- a/DuendeIdentityServer/SLO/SamlOidcSLO/IdentityServer/Pages/TestUsers.cs +++ b/DuendeIdentityServer/SLO/SamlOidcSLO/IdentityServer/Pages/TestUsers.cs @@ -2,10 +2,10 @@ // See LICENSE in the project root for license information. -using IdentityModel; using System.Collections.Generic; using System.Security.Claims; using System.Text.Json; +using Duende.IdentityModel; using Duende.IdentityServer; using Duende.IdentityServer.Test; diff --git a/DuendeIdentityServer/SLO/SamlOidcSLO/IdentityServer/Program.cs b/DuendeIdentityServer/SLO/SamlOidcSLO/IdentityServer/Program.cs index 3872a4d..eaa75f7 100644 --- a/DuendeIdentityServer/SLO/SamlOidcSLO/IdentityServer/Program.cs +++ b/DuendeIdentityServer/SLO/SamlOidcSLO/IdentityServer/Program.cs @@ -9,7 +9,7 @@ try { - var builder = WebApplication.CreateBuilder(args); + WebApplicationBuilder builder = WebApplication.CreateBuilder(args); builder.Host.UseSerilog((ctx, lc) => lc .WriteTo.Console(outputTemplate: "[{Timestamp:HH:mm:ss} {Level}] {SourceContext}{NewLine}{Message:lj}{NewLine}{Exception}{NewLine}") @@ -20,13 +20,16 @@ logging.SetMinimumLevel(LogLevel.Debug); logging.ClearProviders(); logging.AddSimpleConsole(options => options.IncludeScopes = true); - logging.AddEventLog(); + if (OperatingSystem.IsWindows()) + { + logging.AddEventLog(); + } }); - var app = builder + WebApplication app = builder .ConfigureServices() .ConfigurePipeline(); - app.Run(); + await app.RunAsync(); } catch (Exception ex) { @@ -35,5 +38,5 @@ finally { Log.Information("Shut down complete"); - Log.CloseAndFlush(); + await Log.CloseAndFlushAsync(); } \ No newline at end of file diff --git a/DuendeIdentityServer/SLO/SamlOidcSLO/WebClient.OIDC/WebClient.OIDC.csproj b/DuendeIdentityServer/SLO/SamlOidcSLO/WebClient.OIDC/WebClient.OIDC.csproj index bca54a6..400c348 100644 --- a/DuendeIdentityServer/SLO/SamlOidcSLO/WebClient.OIDC/WebClient.OIDC.csproj +++ b/DuendeIdentityServer/SLO/SamlOidcSLO/WebClient.OIDC/WebClient.OIDC.csproj @@ -10,7 +10,7 @@ - + diff --git a/DuendeIdentityServer/SLO/SamlOidcSLO/WebClient.SAML.1/WebClient.SAML.1.csproj b/DuendeIdentityServer/SLO/SamlOidcSLO/WebClient.SAML.1/WebClient.SAML.1.csproj index 70fba60..ebb90e0 100644 --- a/DuendeIdentityServer/SLO/SamlOidcSLO/WebClient.SAML.1/WebClient.SAML.1.csproj +++ b/DuendeIdentityServer/SLO/SamlOidcSLO/WebClient.SAML.1/WebClient.SAML.1.csproj @@ -9,8 +9,8 @@ - - + + diff --git a/DuendeIdentityServer/SLO/SamlOidcSLO/WebClient.SAML.1/testclient.pfx b/DuendeIdentityServer/SLO/SamlOidcSLO/WebClient.SAML.1/testclient.pfx new file mode 100644 index 0000000..1a3e8b8 Binary files /dev/null and b/DuendeIdentityServer/SLO/SamlOidcSLO/WebClient.SAML.1/testclient.pfx differ diff --git a/DuendeIdentityServer/SLO/SamlOidcSLO/WebClient.SAML.2/WebClient.SAML.2.csproj b/DuendeIdentityServer/SLO/SamlOidcSLO/WebClient.SAML.2/WebClient.SAML.2.csproj index 70fba60..ebb90e0 100644 --- a/DuendeIdentityServer/SLO/SamlOidcSLO/WebClient.SAML.2/WebClient.SAML.2.csproj +++ b/DuendeIdentityServer/SLO/SamlOidcSLO/WebClient.SAML.2/WebClient.SAML.2.csproj @@ -9,8 +9,8 @@ - - + + diff --git a/DuendeIdentityServer/SLO/SamlOidcSLO/WebClient.SAML.2/testclient.pfx b/DuendeIdentityServer/SLO/SamlOidcSLO/WebClient.SAML.2/testclient.pfx new file mode 100644 index 0000000..1a3e8b8 Binary files /dev/null and b/DuendeIdentityServer/SLO/SamlOidcSLO/WebClient.SAML.2/testclient.pfx differ diff --git a/IdentityServer4/idp/Program.cs b/IdentityServer4/idp/Program.cs index 3acd257..7a2ddb1 100644 --- a/IdentityServer4/idp/Program.cs +++ b/IdentityServer4/idp/Program.cs @@ -1,41 +1,74 @@ -// 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 idp; using System; -using Microsoft.AspNetCore; -using Microsoft.AspNetCore.Hosting; +using System.Security.Cryptography.X509Certificates; +using IdentityServer4; +using IdentityServer4.Quickstart.UI; +using Microsoft.AspNetCore.Authentication.Cookies; +using Microsoft.AspNetCore.Builder; +using Microsoft.Extensions.DependencyInjection; +using Rsk.Saml.Configuration; +using Rsk.Saml.Samples; using Serilog; using Serilog.Events; using Serilog.Sinks.SystemConsole.Themes; -namespace idp +Console.Title = "IdentityServer4"; + +WebApplicationBuilder builder = WebApplication.CreateBuilder(args); + +// Configure Serilog +builder.Host.UseSerilog((context, configuration) => { - public class Program + configuration + .MinimumLevel.Debug() + .MinimumLevel.Override("Microsoft", LogEventLevel.Warning) + .MinimumLevel.Override("System", LogEventLevel.Warning) + .MinimumLevel.Override("Microsoft.AspNetCore.Authentication", LogEventLevel.Information) + .Enrich.FromLogContext() + .WriteTo.File("identityserver4_log.txt") + .WriteTo.Console(outputTemplate: "[{Timestamp:HH:mm:ss} {Level}] {SourceContext}{NewLine}{Message:lj}{NewLine}{Exception}{NewLine}", theme: AnsiConsoleTheme.Literate); +}); + +builder.Services.AddControllersWithViews(); + +IIdentityServerBuilder idsrvBuilder = builder.Services.AddIdentityServer(options => + { + options.Events.RaiseErrorEvents = true; + options.Events.RaiseInformationEvents = true; + options.Events.RaiseFailureEvents = true; + options.Events.RaiseSuccessEvents = true; + }) + .AddTestUsers(TestUsers.Users) + .AddInMemoryIdentityResources(Config.GetIdentityResources()) + .AddInMemoryApiResources(Config.GetApis()) + .AddInMemoryClients(Config.GetClients()) + .AddSigningCredential(new X509Certificate2("idsrv3test.pfx", "idsrv3test")); + +// Configure SAML Identity Provider and authorized Service Providers +idsrvBuilder.AddSamlPlugin(options => { - public static void Main(string[] args) - { - Console.Title = "IdentityServer4"; - - BuildWebHost(args).Run(); - } - - public static IWebHost BuildWebHost(string[] args) - { - return WebHost.CreateDefaultBuilder(args) - .UseStartup() - .UseSerilog((context, configuration) => - { - configuration - .MinimumLevel.Debug() - .MinimumLevel.Override("Microsoft", LogEventLevel.Warning) - .MinimumLevel.Override("System", LogEventLevel.Warning) - .MinimumLevel.Override("Microsoft.AspNetCore.Authentication", LogEventLevel.Information) - .Enrich.FromLogContext() - .WriteTo.File(@"identityserver4_log.txt") - .WriteTo.Console(outputTemplate: "[{Timestamp:HH:mm:ss} {Level}] {SourceContext}{NewLine}{Message:lj}{NewLine}{Exception}{NewLine}", theme: AnsiConsoleTheme.Literate); - }) - .Build(); - } - } -} \ No newline at end of file + options.Licensee = LicenseKey.Licensee; + options.LicenseKey = LicenseKey.Key; + options.WantAuthenticationRequestsSigned = false; + }) + .AddInMemoryServiceProviders(Config.GetServiceProviders()); + +// use different cookie name that sp... +builder.Services.Configure(IdentityServerConstants.DefaultCookieAuthenticationScheme, + cookie => { cookie.Cookie.Name = "idsrv.idp"; }); + +WebApplication app = builder.Build(); + +app.UseHttpsRedirection(); +app.UseDeveloperExceptionPage(); +app.UseStaticFiles(); +app.UseRouting(); + +app.UseIdentityServer() + .UseIdentityServerSamlPlugin(); // enables SAML endpoints (e.g. ACS and SLO) + +app.UseAuthorization(); + +app.MapDefaultControllerRoute(); + +await app.RunAsync(); \ No newline at end of file diff --git a/IdentityServer4/idp/Quickstart/Account/ExternalController.cs b/IdentityServer4/idp/Quickstart/Account/ExternalController.cs index 2e1ddce..3419282 100644 --- a/IdentityServer4/idp/Quickstart/Account/ExternalController.cs +++ b/IdentityServer4/idp/Quickstart/Account/ExternalController.cs @@ -145,7 +145,7 @@ private async Task ProcessWindowsLoginAsync(string returnUrl) { // see if windows auth has already been requested and succeeded var result = await HttpContext.AuthenticateAsync(AccountOptions.WindowsAuthenticationSchemeName); - if (result?.Principal is WindowsPrincipal wp) + if (OperatingSystem.IsWindows() && result?.Principal is WindowsPrincipal wp) { // we will issue the external cookie and then redirect the // user back to the external callback, in essence, tresting windows diff --git a/IdentityServer4/idp/Quickstart/SecurityHeadersAttribute.cs b/IdentityServer4/idp/Quickstart/SecurityHeadersAttribute.cs index dcdf6f5..564239a 100644 --- a/IdentityServer4/idp/Quickstart/SecurityHeadersAttribute.cs +++ b/IdentityServer4/idp/Quickstart/SecurityHeadersAttribute.cs @@ -2,6 +2,7 @@ // Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information. +using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.Filters; @@ -17,13 +18,13 @@ public override void OnResultExecuting(ResultExecutingContext context) // https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Content-Type-Options if (!context.HttpContext.Response.Headers.ContainsKey("X-Content-Type-Options")) { - context.HttpContext.Response.Headers.Add("X-Content-Type-Options", "nosniff"); + context.HttpContext.Response.Headers.Append("X-Content-Type-Options", "nosniff"); } // https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Frame-Options if (!context.HttpContext.Response.Headers.ContainsKey("X-Frame-Options")) { - context.HttpContext.Response.Headers.Add("X-Frame-Options", "SAMEORIGIN"); + context.HttpContext.Response.Headers.Append("X-Frame-Options", "SAMEORIGIN"); } // https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy @@ -36,19 +37,19 @@ public override void OnResultExecuting(ResultExecutingContext context) // once for standards compliant browsers if (!context.HttpContext.Response.Headers.ContainsKey("Content-Security-Policy")) { - context.HttpContext.Response.Headers.Add("Content-Security-Policy", csp); + context.HttpContext.Response.Headers.Append("Content-Security-Policy", csp); } // and once again for IE if (!context.HttpContext.Response.Headers.ContainsKey("X-Content-Security-Policy")) { - context.HttpContext.Response.Headers.Add("X-Content-Security-Policy", csp); + context.HttpContext.Response.Headers.Append("X-Content-Security-Policy", csp); } // https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Referrer-Policy var referrer_policy = "no-referrer"; if (!context.HttpContext.Response.Headers.ContainsKey("Referrer-Policy")) { - context.HttpContext.Response.Headers.Add("Referrer-Policy", referrer_policy); + context.HttpContext.Response.Headers.Append("Referrer-Policy", referrer_policy); } } } diff --git a/IdentityServer4/idp/Startup.cs b/IdentityServer4/idp/Startup.cs deleted file mode 100644 index 1444877..0000000 --- a/IdentityServer4/idp/Startup.cs +++ /dev/null @@ -1,63 +0,0 @@ -using System.Security.Cryptography.X509Certificates; -using IdentityServer4; -using IdentityServer4.Quickstart.UI; -using Microsoft.AspNetCore.Authentication.Cookies; -using Microsoft.AspNetCore.Builder; -using Microsoft.Extensions.DependencyInjection; -using Rsk.Saml.Configuration; -using Rsk.Saml.Samples; - -namespace idp -{ - public class Startup - { - public void ConfigureServices(IServiceCollection services) - { - services.AddControllersWithViews(); - - var builder = services.AddIdentityServer(options => - { - options.Events.RaiseErrorEvents = true; - options.Events.RaiseInformationEvents = true; - options.Events.RaiseFailureEvents = true; - options.Events.RaiseSuccessEvents = true; - }) - .AddTestUsers(TestUsers.Users) - .AddInMemoryIdentityResources(Config.GetIdentityResources()) - .AddInMemoryApiResources(Config.GetApis()) - .AddInMemoryClients(Config.GetClients()) - .AddSigningCredential(new X509Certificate2("idsrv3test.pfx", "idsrv3test")); - - // Configure SAML Identity Provider and authorized Service Providers - builder.AddSamlPlugin(options => - { - options.Licensee = LicenseKey.Licensee; - options.LicenseKey = LicenseKey.Key; - - options.WantAuthenticationRequestsSigned = false; - }) - .AddInMemoryServiceProviders(Config.GetServiceProviders()); - - // use different cookie name that sp... - builder.Services.Configure(IdentityServerConstants.DefaultCookieAuthenticationScheme, - cookie => { cookie.Cookie.Name = "idsrv.idp"; }); - } - - public void Configure(IApplicationBuilder app) - { - app.UseHttpsRedirection(); - - app.UseDeveloperExceptionPage(); - - app.UseStaticFiles(); - app.UseRouting(); - - app.UseIdentityServer() - .UseIdentityServerSamlPlugin(); // enables SAML endpoints (e.g. ACS and SLO) - - app.UseAuthorization(); - - app.UseEndpoints(endpoints => endpoints.MapDefaultControllerRoute()); - } - } -} \ No newline at end of file diff --git a/IdentityServer4/idp/idp.csproj b/IdentityServer4/idp/idp.csproj index 0eb31a0..d063879 100644 --- a/IdentityServer4/idp/idp.csproj +++ b/IdentityServer4/idp/idp.csproj @@ -1,7 +1,7 @@  - netcoreapp3.1 + net8.0 @@ -10,13 +10,13 @@ - - + + - - - - + + + + diff --git a/IdentityServer4/idpWithEf/Program.cs b/IdentityServer4/idpWithEf/Program.cs index 02a4cd3..be645f6 100644 --- a/IdentityServer4/idpWithEf/Program.cs +++ b/IdentityServer4/idpWithEf/Program.cs @@ -1,41 +1,99 @@ -// 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 System; -using Microsoft.AspNetCore; -using Microsoft.AspNetCore.Hosting; +using System; +using System.Linq; +using System.Security.Cryptography.X509Certificates; +using IdentityServer4; +using IdentityServer4.Quickstart.UI; +using Microsoft.AspNetCore.Authentication.Cookies; +using Microsoft.AspNetCore.Builder; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.DependencyInjection; +using Rsk.Saml.Configuration; +using Rsk.Saml.IdentityProvider.Storage.EntityFramework.DbContexts; +using Rsk.Saml.IdentityProvider.Storage.EntityFramework; +using Rsk.Saml.IdentityProvider.Storage.EntityFramework.Mappers; +using Rsk.Saml.IdentityProvider.Storage.EntityFramework.Stores; +using Rsk.Saml.Samples; using Serilog; using Serilog.Events; using Serilog.Sinks.SystemConsole.Themes; +using idpWithEf; +using ServiceProvider = Rsk.Saml.Models.ServiceProvider; + +Console.Title = "IdentityServer4"; -namespace idpWithEf +WebApplicationBuilder builder = WebApplication.CreateBuilder(args); + +// Configure Serilog +builder.Host.UseSerilog((context, configuration) => { - public class Program + configuration + .MinimumLevel.Debug() + .MinimumLevel.Override("Microsoft", LogEventLevel.Warning) + .MinimumLevel.Override("System", LogEventLevel.Warning) + .MinimumLevel.Override("Microsoft.AspNetCore.Authentication", LogEventLevel.Information) + .Enrich.FromLogContext() + .WriteTo.File("identityserver4_log.txt") + .WriteTo.Console(outputTemplate: "[{Timestamp:HH:mm:ss} {Level}] {SourceContext}{NewLine}{Message:lj}{NewLine}{Exception}{NewLine}", theme: AnsiConsoleTheme.Literate); +}); + +builder.Services.AddControllersWithViews(); + +// SAML SP database (DbContext) +builder.Services.AddDbContext(db => db.UseInMemoryDatabase("ServiceProviders")); +builder.Services.AddScoped(); + +IIdentityServerBuilder idsrvBuilder = builder.Services.AddIdentityServer(options => { - public static void Main(string[] args) - { - Console.Title = "IdentityServer4"; + options.Events.RaiseErrorEvents = true; + options.Events.RaiseInformationEvents = true; + options.Events.RaiseFailureEvents = true; + options.Events.RaiseSuccessEvents = true; + }) + .AddTestUsers(TestUsers.Users) + .AddInMemoryIdentityResources(Config.GetIdentityResources()) + .AddInMemoryApiResources(Config.GetApis()) + .AddInMemoryClients(Config.GetClients()) + .AddSigningCredential(new X509Certificate2("idsrv3test.pfx", "idsrv3test")); - BuildWebHost(args).Run(); - } +// Configure SAML Identity Provider and authorized Service Providers +idsrvBuilder.AddSamlPlugin(options => + { + options.Licensee = LicenseKey.Licensee; + options.LicenseKey = LicenseKey.Key; + options.WantAuthenticationRequestsSigned = false; + }) + .AddServiceProviderStore(); // Load authorized Service Providers from database - public static IWebHost BuildWebHost(string[] args) +builder.Services.Configure(IdentityServerConstants.DefaultCookieAuthenticationScheme, + cookie => { cookie.Cookie.Name = "idsrv.idp"; }); + +WebApplication app = builder.Build(); + +app.UseHttpsRedirection(); +app.UseDeveloperExceptionPage(); + +// Seed the ServiceProvider database +using (IServiceScope serviceScope = app.Services.GetRequiredService().CreateScope()) +{ + var context = serviceScope.ServiceProvider.GetService(); + if (!await context.ServiceProviders.AnyAsync()) + { + foreach (ServiceProvider serviceProvider in Config.GetServiceProviders()) { - return WebHost.CreateDefaultBuilder(args) - .UseStartup() - .UseSerilog((context, configuration) => - { - configuration - .MinimumLevel.Debug() - .MinimumLevel.Override("Microsoft", LogEventLevel.Warning) - .MinimumLevel.Override("System", LogEventLevel.Warning) - .MinimumLevel.Override("Microsoft.AspNetCore.Authentication", LogEventLevel.Information) - .Enrich.FromLogContext() - .WriteTo.File(@"identityserver4_log.txt") - .WriteTo.Console(outputTemplate: "[{Timestamp:HH:mm:ss} {Level}] {SourceContext}{NewLine}{Message:lj}{NewLine}{Exception}{NewLine}", theme: AnsiConsoleTheme.Literate); - }) - .Build(); + context.ServiceProviders.Add(serviceProvider.ToEntity()); } + await context.SaveChangesAsync(); } -} \ No newline at end of file +} + +app.UseStaticFiles(); +app.UseRouting(); + +app.UseIdentityServer() + .UseIdentityServerSamlPlugin(); // enables SAML endpoints (e.g. ACS and SLO) + +app.UseAuthorization(); + +app.MapDefaultControllerRoute(); + +await app.RunAsync(); \ No newline at end of file diff --git a/IdentityServer4/idpWithEf/Quickstart/Account/ExternalController.cs b/IdentityServer4/idpWithEf/Quickstart/Account/ExternalController.cs index 2e1ddce..3419282 100644 --- a/IdentityServer4/idpWithEf/Quickstart/Account/ExternalController.cs +++ b/IdentityServer4/idpWithEf/Quickstart/Account/ExternalController.cs @@ -145,7 +145,7 @@ private async Task ProcessWindowsLoginAsync(string returnUrl) { // see if windows auth has already been requested and succeeded var result = await HttpContext.AuthenticateAsync(AccountOptions.WindowsAuthenticationSchemeName); - if (result?.Principal is WindowsPrincipal wp) + if (OperatingSystem.IsWindows() && result?.Principal is WindowsPrincipal wp) { // we will issue the external cookie and then redirect the // user back to the external callback, in essence, tresting windows diff --git a/IdentityServer4/idpWithEf/Quickstart/SecurityHeadersAttribute.cs b/IdentityServer4/idpWithEf/Quickstart/SecurityHeadersAttribute.cs index dcdf6f5..564239a 100644 --- a/IdentityServer4/idpWithEf/Quickstart/SecurityHeadersAttribute.cs +++ b/IdentityServer4/idpWithEf/Quickstart/SecurityHeadersAttribute.cs @@ -2,6 +2,7 @@ // Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information. +using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.Filters; @@ -17,13 +18,13 @@ public override void OnResultExecuting(ResultExecutingContext context) // https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Content-Type-Options if (!context.HttpContext.Response.Headers.ContainsKey("X-Content-Type-Options")) { - context.HttpContext.Response.Headers.Add("X-Content-Type-Options", "nosniff"); + context.HttpContext.Response.Headers.Append("X-Content-Type-Options", "nosniff"); } // https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Frame-Options if (!context.HttpContext.Response.Headers.ContainsKey("X-Frame-Options")) { - context.HttpContext.Response.Headers.Add("X-Frame-Options", "SAMEORIGIN"); + context.HttpContext.Response.Headers.Append("X-Frame-Options", "SAMEORIGIN"); } // https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy @@ -36,19 +37,19 @@ public override void OnResultExecuting(ResultExecutingContext context) // once for standards compliant browsers if (!context.HttpContext.Response.Headers.ContainsKey("Content-Security-Policy")) { - context.HttpContext.Response.Headers.Add("Content-Security-Policy", csp); + context.HttpContext.Response.Headers.Append("Content-Security-Policy", csp); } // and once again for IE if (!context.HttpContext.Response.Headers.ContainsKey("X-Content-Security-Policy")) { - context.HttpContext.Response.Headers.Add("X-Content-Security-Policy", csp); + context.HttpContext.Response.Headers.Append("X-Content-Security-Policy", csp); } // https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Referrer-Policy var referrer_policy = "no-referrer"; if (!context.HttpContext.Response.Headers.ContainsKey("Referrer-Policy")) { - context.HttpContext.Response.Headers.Add("Referrer-Policy", referrer_policy); + context.HttpContext.Response.Headers.Append("Referrer-Policy", referrer_policy); } } } diff --git a/IdentityServer4/idpWithEf/Startup.cs b/IdentityServer4/idpWithEf/Startup.cs deleted file mode 100644 index db1c6ef..0000000 --- a/IdentityServer4/idpWithEf/Startup.cs +++ /dev/null @@ -1,92 +0,0 @@ -using System.Linq; -using System.Security.Cryptography.X509Certificates; -using IdentityServer4; -using IdentityServer4.Quickstart.UI; -using Microsoft.AspNetCore.Authentication.Cookies; -using Microsoft.AspNetCore.Builder; -using Microsoft.EntityFrameworkCore; -using Microsoft.Extensions.DependencyInjection; -using Rsk.Saml.Configuration; -using Rsk.Saml.IdentityProvider.Storage.EntityFramework.DbContexts; -using Rsk.Saml.IdentityProvider.Storage.EntityFramework; -using Rsk.Saml.IdentityProvider.Storage.EntityFramework.Mappers; -using Rsk.Saml.IdentityProvider.Storage.EntityFramework.Stores; -using Rsk.Saml.Samples; - -namespace idpWithEf -{ - public class Startup - { - public void ConfigureServices(IServiceCollection services) - { - services.AddControllersWithViews(); - - // SAML SP database (DbContext) - services.AddDbContext(db => - db.UseInMemoryDatabase("ServiceProviders")); - services.AddScoped(); - - var builder = services.AddIdentityServer(options => - { - options.Events.RaiseErrorEvents = true; - options.Events.RaiseInformationEvents = true; - options.Events.RaiseFailureEvents = true; - options.Events.RaiseSuccessEvents = true; - }) - .AddTestUsers(TestUsers.Users) - .AddInMemoryIdentityResources(Config.GetIdentityResources()) - .AddInMemoryApiResources(Config.GetApis()) - .AddInMemoryClients(Config.GetClients()) - .AddSigningCredential(new X509Certificate2("idsrv3test.pfx", "idsrv3test")); - - // Configure SAML Identity Provider and authorized Service Providers - builder.AddSamlPlugin(options => - { - options.Licensee = LicenseKey.Licensee; - options.LicenseKey = LicenseKey.Key; - - options.WantAuthenticationRequestsSigned = false; - }) - .AddServiceProviderStore(); // Load authorized Service Providers from database - - builder.Services.Configure(IdentityServerConstants.DefaultCookieAuthenticationScheme, - cookie => { cookie.Cookie.Name = "idsrv.idp"; }); - } - - public void Configure(IApplicationBuilder app) - { - app.UseHttpsRedirection(); - - app.UseDeveloperExceptionPage(); - - SeedServiceProviderDatabase(app); - - app.UseStaticFiles(); - app.UseRouting(); - - app.UseIdentityServer() - .UseIdentityServerSamlPlugin(); // enables SAML endpoints (e.g. ACS and SLO) - - app.UseAuthorization(); - - app.UseEndpoints(endpoints => endpoints.MapDefaultControllerRoute()); - } - - private void SeedServiceProviderDatabase(IApplicationBuilder app) - { - using (var serviceScope = app.ApplicationServices.GetRequiredService().CreateScope()) - { - var context = serviceScope.ServiceProvider.GetService(); - if (!context.ServiceProviders.Any()) - { - foreach (var serviceProvider in Config.GetServiceProviders()) - { - context.ServiceProviders.Add(serviceProvider.ToEntity()); - } - - context.SaveChanges(); - } - } - } - } -} \ No newline at end of file diff --git a/IdentityServer4/idpWithEf/idpWithEf.csproj b/IdentityServer4/idpWithEf/idpWithEf.csproj index a5becdc..b0e1776 100644 --- a/IdentityServer4/idpWithEf/idpWithEf.csproj +++ b/IdentityServer4/idpWithEf/idpWithEf.csproj @@ -1,7 +1,7 @@  - netcoreapp3.1 + net8.0 @@ -10,15 +10,15 @@ - - - - + + + + - - - - + + + + diff --git a/IdentityServer4/idpWithIdpInitiated/Program.cs b/IdentityServer4/idpWithIdpInitiated/Program.cs index a18b499..0e35e5c 100644 --- a/IdentityServer4/idpWithIdpInitiated/Program.cs +++ b/IdentityServer4/idpWithIdpInitiated/Program.cs @@ -1,41 +1,74 @@ -// 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 System; -using Microsoft.AspNetCore; -using Microsoft.AspNetCore.Hosting; +using System; +using System.Security.Cryptography.X509Certificates; +using IdentityServer4; +using IdentityServer4.Quickstart.UI; +using Microsoft.AspNetCore.Authentication.Cookies; +using Microsoft.AspNetCore.Builder; +using Microsoft.Extensions.DependencyInjection; +using Rsk.Saml.Configuration; +using Rsk.Saml.Samples; using Serilog; using Serilog.Events; using Serilog.Sinks.SystemConsole.Themes; +using idpWithIdpInitiated; + +Console.Title = "IdentityServer4"; + +WebApplicationBuilder builder = WebApplication.CreateBuilder(args); -namespace idpWithIdpInitiated +// Configure Serilog +builder.Host.UseSerilog((context, configuration) => { - public class Program + configuration + .MinimumLevel.Debug() + .MinimumLevel.Override("Microsoft", LogEventLevel.Warning) + .MinimumLevel.Override("System", LogEventLevel.Warning) + .MinimumLevel.Override("Microsoft.AspNetCore.Authentication", LogEventLevel.Information) + .Enrich.FromLogContext() + .WriteTo.File("identityserver4_log.txt") + .WriteTo.Console(outputTemplate: "[{Timestamp:HH:mm:ss} {Level}] {SourceContext}{NewLine}{Message:lj}{NewLine}{Exception}{NewLine}", theme: AnsiConsoleTheme.Literate); +}); + +builder.Services.AddControllersWithViews(); + +IIdentityServerBuilder idsrvBuilder = builder.Services.AddIdentityServer(options => + { + options.Events.RaiseErrorEvents = true; + options.Events.RaiseInformationEvents = true; + options.Events.RaiseFailureEvents = true; + options.Events.RaiseSuccessEvents = true; + }) + .AddTestUsers(TestUsers.Users) + .AddInMemoryIdentityResources(Config.GetIdentityResources()) + .AddInMemoryApiResources(Config.GetApis()) + .AddInMemoryClients(Config.GetClients()) + .AddSigningCredential(new X509Certificate2("idsrv3test.pfx", "idsrv3test")); + +// Configure SAML Identity Provider and authorized Service Providers +idsrvBuilder.AddSamlPlugin(options => { - public static void Main(string[] args) - { - Console.Title = "IdentityServer4"; - - BuildWebHost(args).Run(); - } - - public static IWebHost BuildWebHost(string[] args) - { - return WebHost.CreateDefaultBuilder(args) - .UseStartup() - .UseSerilog((context, configuration) => - { - configuration - .MinimumLevel.Debug() - .MinimumLevel.Override("Microsoft", LogEventLevel.Warning) - .MinimumLevel.Override("System", LogEventLevel.Warning) - .MinimumLevel.Override("Microsoft.AspNetCore.Authentication", LogEventLevel.Information) - .Enrich.FromLogContext() - .WriteTo.File(@"identityserver4_log.txt") - .WriteTo.Console(outputTemplate: "[{Timestamp:HH:mm:ss} {Level}] {SourceContext}{NewLine}{Message:lj}{NewLine}{Exception}{NewLine}", theme: AnsiConsoleTheme.Literate); - }) - .Build(); - } - } -} \ No newline at end of file + options.Licensee = LicenseKey.Licensee; + options.LicenseKey = LicenseKey.Key; + options.WantAuthenticationRequestsSigned = false; + }) + .AddInMemoryServiceProviders(Config.GetServiceProviders()); + +// use different cookie name that sp... +builder.Services.Configure(IdentityServerConstants.DefaultCookieAuthenticationScheme, + cookie => { cookie.Cookie.Name = "idsrv.idpWithIdpInitiated"; }); + +WebApplication app = builder.Build(); + +app.UseHttpsRedirection(); +app.UseDeveloperExceptionPage(); +app.UseStaticFiles(); +app.UseRouting(); + +app.UseIdentityServer() + .UseIdentityServerSamlPlugin(); // enables SAML endpoints (e.g. ACS and SLO) + +app.UseAuthorization(); + +app.MapDefaultControllerRoute(); + +await app.RunAsync(); \ No newline at end of file diff --git a/IdentityServer4/idpWithIdpInitiated/Quickstart/Account/ExternalController.cs b/IdentityServer4/idpWithIdpInitiated/Quickstart/Account/ExternalController.cs index ec08af6..6cc97e2 100644 --- a/IdentityServer4/idpWithIdpInitiated/Quickstart/Account/ExternalController.cs +++ b/IdentityServer4/idpWithIdpInitiated/Quickstart/Account/ExternalController.cs @@ -145,7 +145,7 @@ private async Task ProcessWindowsLoginAsync(string returnUrl) { // see if windows auth has already been requested and succeeded var result = await HttpContext.AuthenticateAsync(AccountOptions.WindowsAuthenticationSchemeName); - if (result?.Principal is WindowsPrincipal wp) + if (OperatingSystem.IsWindows() && result?.Principal is WindowsPrincipal wp) { // we will issue the external cookie and then redirect the // user back to the external callback, in essence, tresting windows diff --git a/IdentityServer4/idpWithIdpInitiated/Quickstart/SecurityHeadersAttribute.cs b/IdentityServer4/idpWithIdpInitiated/Quickstart/SecurityHeadersAttribute.cs index dcdf6f5..564239a 100644 --- a/IdentityServer4/idpWithIdpInitiated/Quickstart/SecurityHeadersAttribute.cs +++ b/IdentityServer4/idpWithIdpInitiated/Quickstart/SecurityHeadersAttribute.cs @@ -2,6 +2,7 @@ // Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information. +using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.Filters; @@ -17,13 +18,13 @@ public override void OnResultExecuting(ResultExecutingContext context) // https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Content-Type-Options if (!context.HttpContext.Response.Headers.ContainsKey("X-Content-Type-Options")) { - context.HttpContext.Response.Headers.Add("X-Content-Type-Options", "nosniff"); + context.HttpContext.Response.Headers.Append("X-Content-Type-Options", "nosniff"); } // https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Frame-Options if (!context.HttpContext.Response.Headers.ContainsKey("X-Frame-Options")) { - context.HttpContext.Response.Headers.Add("X-Frame-Options", "SAMEORIGIN"); + context.HttpContext.Response.Headers.Append("X-Frame-Options", "SAMEORIGIN"); } // https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy @@ -36,19 +37,19 @@ public override void OnResultExecuting(ResultExecutingContext context) // once for standards compliant browsers if (!context.HttpContext.Response.Headers.ContainsKey("Content-Security-Policy")) { - context.HttpContext.Response.Headers.Add("Content-Security-Policy", csp); + context.HttpContext.Response.Headers.Append("Content-Security-Policy", csp); } // and once again for IE if (!context.HttpContext.Response.Headers.ContainsKey("X-Content-Security-Policy")) { - context.HttpContext.Response.Headers.Add("X-Content-Security-Policy", csp); + context.HttpContext.Response.Headers.Append("X-Content-Security-Policy", csp); } // https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Referrer-Policy var referrer_policy = "no-referrer"; if (!context.HttpContext.Response.Headers.ContainsKey("Referrer-Policy")) { - context.HttpContext.Response.Headers.Add("Referrer-Policy", referrer_policy); + context.HttpContext.Response.Headers.Append("Referrer-Policy", referrer_policy); } } } diff --git a/IdentityServer4/idpWithIdpInitiated/Startup.cs b/IdentityServer4/idpWithIdpInitiated/Startup.cs deleted file mode 100644 index 6dff9a2..0000000 --- a/IdentityServer4/idpWithIdpInitiated/Startup.cs +++ /dev/null @@ -1,63 +0,0 @@ -using System.Security.Cryptography.X509Certificates; -using IdentityServer4; -using IdentityServer4.Quickstart.UI; -using Microsoft.AspNetCore.Authentication.Cookies; -using Microsoft.AspNetCore.Builder; -using Microsoft.Extensions.DependencyInjection; -using Rsk.Saml.Configuration; -using Rsk.Saml.Samples; - -namespace idpWithIdpInitiated -{ - public class Startup - { - public void ConfigureServices(IServiceCollection services) - { - services.AddControllersWithViews(); - - var builder = services.AddIdentityServer(options => - { - options.Events.RaiseErrorEvents = true; - options.Events.RaiseInformationEvents = true; - options.Events.RaiseFailureEvents = true; - options.Events.RaiseSuccessEvents = true; - }) - .AddTestUsers(TestUsers.Users) - .AddInMemoryIdentityResources(Config.GetIdentityResources()) - .AddInMemoryApiResources(Config.GetApis()) - .AddInMemoryClients(Config.GetClients()) - .AddSigningCredential(new X509Certificate2("idsrv3test.pfx", "idsrv3test")); - - // Configure SAML Identity Provider and authorized Service Providers - builder.AddSamlPlugin(options => - { - options.Licensee = LicenseKey.Licensee; - options.LicenseKey = LicenseKey.Key; - - options.WantAuthenticationRequestsSigned = false; - }) - .AddInMemoryServiceProviders(Config.GetServiceProviders()); - - // use different cookie name that sp... - builder.Services.Configure(IdentityServerConstants.DefaultCookieAuthenticationScheme, - cookie => { cookie.Cookie.Name = "idsrv.idpWithIdpInitiated"; }); - } - - public void Configure(IApplicationBuilder app) - { - app.UseHttpsRedirection(); - - app.UseDeveloperExceptionPage(); - - app.UseStaticFiles(); - app.UseRouting(); - - app.UseIdentityServer() - .UseIdentityServerSamlPlugin(); // enables SAML endpoints (e.g. ACS and SLO) - - app.UseAuthorization(); - - app.UseEndpoints(endpoints => endpoints.MapDefaultControllerRoute()); - } - } -} \ No newline at end of file diff --git a/IdentityServer4/idpWithIdpInitiated/idpWithIdpInitiated.csproj b/IdentityServer4/idpWithIdpInitiated/idpWithIdpInitiated.csproj index 0eb31a0..d063879 100644 --- a/IdentityServer4/idpWithIdpInitiated/idpWithIdpInitiated.csproj +++ b/IdentityServer4/idpWithIdpInitiated/idpWithIdpInitiated.csproj @@ -1,7 +1,7 @@  - netcoreapp3.1 + net8.0 @@ -10,13 +10,13 @@ - - + + - - - - + + + + diff --git a/IdentityServer4/sp/Program.cs b/IdentityServer4/sp/Program.cs index 761dda8..ae17bdf 100644 --- a/IdentityServer4/sp/Program.cs +++ b/IdentityServer4/sp/Program.cs @@ -1,42 +1,105 @@ -// 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 System; -using Microsoft.AspNetCore; -using Microsoft.AspNetCore.Hosting; +using System; +using System.Security.Cryptography.X509Certificates; +using IdentityServer4; +using IdentityServer4.Quickstart.UI; +using Microsoft.AspNetCore.Builder; +using Microsoft.Extensions.DependencyInjection; +using Rsk.AspNetCore.Authentication.Saml2p; +using Rsk.Saml.Configuration; +using Rsk.Saml.Samples; using Serilog; using Serilog.Events; using Serilog.Sinks.SystemConsole.Themes; +using sp; + +Console.Title = "IdentityServer4"; -namespace sp +WebApplicationBuilder builder = WebApplication.CreateBuilder(args); + +// Configure Serilog +builder.Host.UseSerilog((context, configuration) => { - public class Program + configuration + .MinimumLevel.Debug() + .MinimumLevel.Override("Microsoft", LogEventLevel.Warning) + .MinimumLevel.Override("System", LogEventLevel.Warning) + .MinimumLevel.Override("Microsoft.AspNetCore.Authentication", LogEventLevel.Information) + .Enrich.FromLogContext() + .WriteTo.File("identityserver4_log.txt") + .WriteTo.Console( + outputTemplate: + "[{Timestamp:HH:mm:ss} {Level}] {SourceContext}{NewLine}{Message:lj}{NewLine}{Exception}{NewLine}", + theme: AnsiConsoleTheme.Literate); +}); + +builder.WebHost.UseSetting("urls", "https://*:5001"); + +builder.Services.AddControllersWithViews(); + +IIdentityServerBuilder idsrvBuilder = builder.Services.AddIdentityServer(options => { - public static void Main(string[] args) - { - Console.Title = "IdentityServer4"; + options.Events.RaiseErrorEvents = true; + options.Events.RaiseInformationEvents = true; + options.Events.RaiseFailureEvents = true; + options.Events.RaiseSuccessEvents = true; + }) + .AddTestUsers(TestUsers.Users) + .AddInMemoryIdentityResources(Config.GetIdentityResources()) + .AddInMemoryApiResources(Config.GetApis()) + .AddInMemoryClients(Config.GetClients()) + .AddSigningCredential(new X509Certificate2("testclient.pfx", "test")); + +// OPTIONAL - only required if you want to be a SAML IdP too +idsrvBuilder.AddSamlPlugin(options => + { + options.Licensee = LicenseKey.Licensee; + options.LicenseKey = LicenseKey.Key; + options.WantAuthenticationRequestsSigned = false; + }) + .AddInMemoryServiceProviders(Config.GetServiceProviders()); - BuildWebHost(args).Run(); - } +// SP configuration +builder.Services.AddAuthentication() + .AddSaml2p("saml2p", options => + { + options.Licensee = LicenseKey.Licensee; + options.LicenseKey = LicenseKey.Key; + + // The IdP you want to integrate with + options.IdentityProviderOptions = new IdpOptions + { + EntityId = "https://localhost:5000", + SigningCertificates = { new X509Certificate2("idsrv3test.cer") }, + SingleSignOnEndpoint = new SamlEndpoint("https://localhost:5000/saml/sso", SamlBindingTypes.HttpRedirect), + SingleLogoutEndpoint = new SamlEndpoint("https://localhost:5000/saml/slo", SamlBindingTypes.HttpRedirect), + }; - public static IWebHost BuildWebHost(string[] args) + // Details about yourself (the SP) + options.ServiceProviderOptions = new SpOptions { - return WebHost.CreateDefaultBuilder(args) - .UseStartup() - .UseSerilog((context, configuration) => - { - configuration - .MinimumLevel.Debug() - .MinimumLevel.Override("Microsoft", LogEventLevel.Warning) - .MinimumLevel.Override("System", LogEventLevel.Warning) - .MinimumLevel.Override("Microsoft.AspNetCore.Authentication", LogEventLevel.Information) - .Enrich.FromLogContext() - .WriteTo.File(@"identityserver4_log.txt") - .WriteTo.Console(outputTemplate: "[{Timestamp:HH:mm:ss} {Level}] {SourceContext}{NewLine}{Message:lj}{NewLine}{Exception}{NewLine}", theme: AnsiConsoleTheme.Literate); - }) - .UseUrls("https://*:5001") - .Build(); - } - } -} \ No newline at end of file + EntityId = "https://localhost:5001/saml", + MetadataPath = "/saml/metadata", + SignAuthenticationRequests = true, // OPTIONAL - use if you want to sign your auth requests + SigningCertificate = new X509Certificate2("testclient.pfx", "test") + }; + + options.NameIdClaimType = "sub"; + options.CallbackPath = "/signin-saml"; + options.SignInScheme = IdentityServerConstants.ExternalCookieAuthenticationScheme; + }); + +WebApplication app = builder.Build(); + +app.UseHttpsRedirection(); +app.UseDeveloperExceptionPage(); +app.UseStaticFiles(); +app.UseRouting(); + +app.UseIdentityServer() + .UseIdentityServerSamlPlugin(); // OPTIONAL - only required if you want to be a SAML IdP too + +app.UseAuthorization(); + +app.MapDefaultControllerRoute(); + +await app.RunAsync(); \ No newline at end of file diff --git a/IdentityServer4/sp/Quickstart/Account/ExternalController.cs b/IdentityServer4/sp/Quickstart/Account/ExternalController.cs index 2e1ddce..3419282 100644 --- a/IdentityServer4/sp/Quickstart/Account/ExternalController.cs +++ b/IdentityServer4/sp/Quickstart/Account/ExternalController.cs @@ -145,7 +145,7 @@ private async Task ProcessWindowsLoginAsync(string returnUrl) { // see if windows auth has already been requested and succeeded var result = await HttpContext.AuthenticateAsync(AccountOptions.WindowsAuthenticationSchemeName); - if (result?.Principal is WindowsPrincipal wp) + if (OperatingSystem.IsWindows() && result?.Principal is WindowsPrincipal wp) { // we will issue the external cookie and then redirect the // user back to the external callback, in essence, tresting windows diff --git a/IdentityServer4/sp/Quickstart/SecurityHeadersAttribute.cs b/IdentityServer4/sp/Quickstart/SecurityHeadersAttribute.cs index dcdf6f5..564239a 100644 --- a/IdentityServer4/sp/Quickstart/SecurityHeadersAttribute.cs +++ b/IdentityServer4/sp/Quickstart/SecurityHeadersAttribute.cs @@ -2,6 +2,7 @@ // Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information. +using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.Filters; @@ -17,13 +18,13 @@ public override void OnResultExecuting(ResultExecutingContext context) // https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Content-Type-Options if (!context.HttpContext.Response.Headers.ContainsKey("X-Content-Type-Options")) { - context.HttpContext.Response.Headers.Add("X-Content-Type-Options", "nosniff"); + context.HttpContext.Response.Headers.Append("X-Content-Type-Options", "nosniff"); } // https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Frame-Options if (!context.HttpContext.Response.Headers.ContainsKey("X-Frame-Options")) { - context.HttpContext.Response.Headers.Add("X-Frame-Options", "SAMEORIGIN"); + context.HttpContext.Response.Headers.Append("X-Frame-Options", "SAMEORIGIN"); } // https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy @@ -36,19 +37,19 @@ public override void OnResultExecuting(ResultExecutingContext context) // once for standards compliant browsers if (!context.HttpContext.Response.Headers.ContainsKey("Content-Security-Policy")) { - context.HttpContext.Response.Headers.Add("Content-Security-Policy", csp); + context.HttpContext.Response.Headers.Append("Content-Security-Policy", csp); } // and once again for IE if (!context.HttpContext.Response.Headers.ContainsKey("X-Content-Security-Policy")) { - context.HttpContext.Response.Headers.Add("X-Content-Security-Policy", csp); + context.HttpContext.Response.Headers.Append("X-Content-Security-Policy", csp); } // https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Referrer-Policy var referrer_policy = "no-referrer"; if (!context.HttpContext.Response.Headers.ContainsKey("Referrer-Policy")) { - context.HttpContext.Response.Headers.Add("Referrer-Policy", referrer_policy); + context.HttpContext.Response.Headers.Append("Referrer-Policy", referrer_policy); } } } diff --git a/IdentityServer4/sp/Startup.cs b/IdentityServer4/sp/Startup.cs deleted file mode 100644 index 3551368..0000000 --- a/IdentityServer4/sp/Startup.cs +++ /dev/null @@ -1,88 +0,0 @@ -using System.Security.Cryptography.X509Certificates; -using IdentityServer4; -using IdentityServer4.Quickstart.UI; -using Microsoft.AspNetCore.Builder; -using Microsoft.Extensions.DependencyInjection; -using Rsk.AspNetCore.Authentication.Saml2p; -using Rsk.Saml.Configuration; -using Rsk.Saml.Samples; - -namespace sp -{ - public class Startup - { - public void ConfigureServices(IServiceCollection services) - { - services.AddControllersWithViews(); - - var builder = services.AddIdentityServer(options => - { - options.Events.RaiseErrorEvents = true; - options.Events.RaiseInformationEvents = true; - options.Events.RaiseFailureEvents = true; - options.Events.RaiseSuccessEvents = true; - }) - .AddTestUsers(TestUsers.Users) - .AddInMemoryIdentityResources(Config.GetIdentityResources()) - .AddInMemoryApiResources(Config.GetApis()) - .AddInMemoryClients(Config.GetClients()) - .AddSigningCredential(new X509Certificate2("testclient.pfx", "test")); - - // OPTIONAL - only required if you want to be a SAML IdP too - builder.AddSamlPlugin(options => - { - options.Licensee = LicenseKey.Licensee; - options.LicenseKey = LicenseKey.Key; - - options.WantAuthenticationRequestsSigned = false; - }) - .AddInMemoryServiceProviders(Config.GetServiceProviders()); - - // SP configuration - services.AddAuthentication() - .AddSaml2p("saml2p", options => { - options.Licensee = "/* your DEMO Licensee */"; - options.LicenseKey = "/* your DEMO LicenseKey */"; - - // The IdP you want to integrate with - options.IdentityProviderOptions = new IdpOptions - { - EntityId = "https://localhost:5000", - SigningCertificates = {new X509Certificate2("idsrv3test.cer")}, - SingleSignOnEndpoint = new SamlEndpoint("https://localhost:5000/saml/sso", SamlBindingTypes.HttpRedirect), - SingleLogoutEndpoint = new SamlEndpoint("https://localhost:5000/saml/slo", SamlBindingTypes.HttpRedirect), - }; - - // Details about yourself (the SP) - options.ServiceProviderOptions = new SpOptions - { - EntityId = "https://localhost:5001/saml", - MetadataPath = "/saml/metadata", - SignAuthenticationRequests = true, // OPTIONAL - use if you want to sign your auth requests - SigningCertificate = new X509Certificate2("testclient.pfx", "test") - }; - - options.NameIdClaimType = "sub"; - options.CallbackPath = "/signin-saml"; - options.SignInScheme = IdentityServerConstants.ExternalCookieAuthenticationScheme; - }); - } - - public void Configure(IApplicationBuilder app) - { - app.UseHttpsRedirection(); - - app.UseDeveloperExceptionPage(); - - app.UseStaticFiles(); - app.UseRouting(); - - app.UseIdentityServer() - .UseIdentityServerSamlPlugin(); // OPTIONAL - only required if you want to be a SAML IdP too - - app.UseAuthorization(); - - app.UseEndpoints(endpoints => endpoints.MapDefaultControllerRoute()); - } - } -} \ No newline at end of file diff --git a/IdentityServer4/sp/sp.csproj b/IdentityServer4/sp/sp.csproj index 824bfca..3a0862d 100644 --- a/IdentityServer4/sp/sp.csproj +++ b/IdentityServer4/sp/sp.csproj @@ -1,7 +1,7 @@  - netcoreapp3.1 + net8.0 @@ -10,13 +10,13 @@ - - + + - - - - + + + + diff --git a/LicenseKey.cs b/LicenseKey.cs index bce0db4..01e4b6a 100644 --- a/LicenseKey.cs +++ b/LicenseKey.cs @@ -3,6 +3,6 @@ public static class LicenseKey { public const string Licensee = "DEMO"; - public const string Key = "visit https://www.identityserver.com/products/saml2p to obtain a free demo key"; + public const string Key = "eyJhdXRoIjoiREVNTyIsImV4cCI6IjIwMjUtMDgtMDZUMDA6MDA6MDEuNjEyNDg5OSswMDowMCIsImlhdCI6IjIwMjUtMDctMDdUMDA6MDA6MDEuOTY4MzEwN1oiLCJvcmciOiJERU1PIiwiYXVkIjoyfQ==.mpi6l7DsJzzHordvTgShzMOf5qny1dMPT3BN2TTr2U42aG6ySUGuZ6U1rqtzdAmS872Mt95x+T5e5qajVpcbxweeYKFDpNcE5X8bEzTGThoLrEtsCdbK7zxN5GHTn4d2zggxKCVPMkddYDMbbQ4eEkfhKL0rlDijZ2maaRYGvPZG4u2cMH3zmS+vzWqCDR31yTSEEGoJp43S1PxMO6iTg8FvZAtnCVO2/hT2+At9mqkEvsdtT90oM7gXdGQxLsiplt1jwCfuE9okkvYJ/mZm3amoQeE2OX4Dayu1zBTgzH74qi8cJrFTnnXbYXC3g26mW6vm8x8JoafJFZe0YDHqMAFqknNMFgfGyLlASIXyAPXnI1xdYIf6VZJ4u6w4Ib2nj+i4CVwzqYwgyOvf9in4EMSHaGrAWbk/PT1P2eprVZREmaRnJYAHOHYbqYyD9WIhsiaDE6grCFNGQ0Vxp/1FL/wsvITXLwdm4A+VnlNotEJpmcM2jjc13JBlO7ocvXnK5Bdq+NkSxNtpAL7ZWrhc2WoqVbGvZR8ibHVh1BLjzEpjVKKolgio5lho3IZDpYXhYgsqbc6qtfutRoGfQ5TcpagVrWXWQ8dYzE/E2oU4XSrJcNC0g+3D7lDjXolgWjnGM1TGDWovidg6fp8f1DgR5+6cSzzrD3FshJjkt/xVy9g="; } } \ No newline at end of file diff --git a/OpenIddict/OpenIddictIdP/Controllers/AuthorizationController.cs b/OpenIddict/OpenIddictIdP/Controllers/AuthorizationController.cs index b6784f4..83e853a 100644 --- a/OpenIddict/OpenIddictIdP/Controllers/AuthorizationController.cs +++ b/OpenIddict/OpenIddictIdP/Controllers/AuthorizationController.cs @@ -62,13 +62,13 @@ public async Task Authorize() // - If prompt=login was specified by the client application. // - If a max_age parameter was provided and the authentication cookie is not considered "fresh" enough. var result = await HttpContext.AuthenticateAsync(IdentityConstants.ApplicationScheme); - if (result == null || !result.Succeeded || request.HasPrompt(Prompts.Login) || + if (result == null || !result.Succeeded || request.HasPromptValue(PromptValues.Login) || request.MaxAge != null && result.Properties?.IssuedUtc != null && DateTimeOffset.UtcNow - result.Properties.IssuedUtc > TimeSpan.FromSeconds(request.MaxAge.Value)) { // If the client application requested promptless authentication, // return an error indicating that the user is not logged in. - if (request.HasPrompt(Prompts.None)) + if (request.HasPromptValue(PromptValues.None)) { return Forbid( authenticationSchemes: OpenIddictServerAspNetCoreDefaults.AuthenticationScheme, @@ -81,7 +81,7 @@ public async Task Authorize() // To avoid endless login -> authorization redirects, the prompt=login flag // is removed from the authorization request payload before redirecting the user. - var prompt = string.Join(" ", request.GetPrompts().Remove(Prompts.Login)); + var prompt = string.Join(" ", request.GetPromptValues().Remove(PromptValues.Login)); var parameters = Request.HasFormContentType ? Request.Form.Where(parameter => parameter.Key != Parameters.Prompt).ToList() : @@ -142,7 +142,7 @@ public async Task Authorize() // return an authorization response without displaying the consent form. case ConsentTypes.Implicit: case ConsentTypes.External when authorizations.Any(): - case ConsentTypes.Explicit when authorizations.Any() && !request.HasPrompt(Prompts.Consent): + case ConsentTypes.Explicit when authorizations.Any() && !request.HasPromptValue(PromptValues.Consent): // Create the claims-based identity that will be used by OpenIddict to generate tokens. var identity = new ClaimsIdentity( authenticationType: TokenValidationParameters.DefaultAuthenticationType, @@ -178,8 +178,8 @@ public async Task Authorize() // At this point, no authorization was found in the database and an error must be returned // if the client application specified prompt=none in the authorization request. - case ConsentTypes.Explicit when request.HasPrompt(Prompts.None): - case ConsentTypes.Systematic when request.HasPrompt(Prompts.None): + case ConsentTypes.Explicit when request.HasPromptValue(PromptValues.None): + case ConsentTypes.Systematic when request.HasPromptValue(PromptValues.None): return Forbid( authenticationSchemes: OpenIddictServerAspNetCoreDefaults.AuthenticationScheme, properties: new AuthenticationProperties(new Dictionary diff --git a/OpenIddict/OpenIddictIdP/Data/Migrations/ApplicationDb/20250707141914_InitialCreate.Designer.cs b/OpenIddict/OpenIddictIdP/Data/Migrations/ApplicationDb/20250707141914_InitialCreate.Designer.cs new file mode 100644 index 0000000..7e6dfe3 --- /dev/null +++ b/OpenIddict/OpenIddictIdP/Data/Migrations/ApplicationDb/20250707141914_InitialCreate.Designer.cs @@ -0,0 +1,512 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using openiddictidp.Data; + +#nullable disable + +namespace OpenIddictIdP.Data.Migrations.ApplicationDb +{ + [DbContext(typeof(ApplicationDbContext))] + [Migration("20250707141914_InitialCreate")] + partial class InitialCreate + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder.HasAnnotation("ProductVersion", "8.0.17"); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("TEXT"); + + b.Property("Name") + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.Property("NormalizedName") + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedName") + .IsUnique() + .HasDatabaseName("RoleNameIndex"); + + b.ToTable("AspNetRoles", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ClaimType") + .HasColumnType("TEXT"); + + b.Property("ClaimValue") + .HasColumnType("TEXT"); + + b.Property("RoleId") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetRoleClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ClaimType") + .HasColumnType("TEXT"); + + b.Property("ClaimValue") + .HasColumnType("TEXT"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.Property("LoginProvider") + .HasColumnType("TEXT"); + + b.Property("ProviderKey") + .HasColumnType("TEXT"); + + b.Property("ProviderDisplayName") + .HasColumnType("TEXT"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("LoginProvider", "ProviderKey"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserLogins", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.Property("UserId") + .HasColumnType("TEXT"); + + b.Property("RoleId") + .HasColumnType("TEXT"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetUserRoles", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.Property("UserId") + .HasColumnType("TEXT"); + + b.Property("LoginProvider") + .HasColumnType("TEXT"); + + b.Property("Name") + .HasColumnType("TEXT"); + + b.Property("Value") + .HasColumnType("TEXT"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("AspNetUserTokens", (string)null); + }); + + modelBuilder.Entity("OpenIddict.EntityFrameworkCore.Models.OpenIddictEntityFrameworkCoreApplication", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("TEXT"); + + b.Property("ApplicationType") + .HasMaxLength(50) + .HasColumnType("TEXT"); + + b.Property("ClientId") + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("ClientSecret") + .HasColumnType("TEXT"); + + b.Property("ClientType") + .HasMaxLength(50) + .HasColumnType("TEXT"); + + b.Property("ConcurrencyToken") + .IsConcurrencyToken() + .HasMaxLength(50) + .HasColumnType("TEXT"); + + b.Property("ConsentType") + .HasMaxLength(50) + .HasColumnType("TEXT"); + + b.Property("DisplayName") + .HasColumnType("TEXT"); + + b.Property("DisplayNames") + .HasColumnType("TEXT"); + + b.Property("JsonWebKeySet") + .HasColumnType("TEXT"); + + b.Property("Permissions") + .HasColumnType("TEXT"); + + b.Property("PostLogoutRedirectUris") + .HasColumnType("TEXT"); + + b.Property("Properties") + .HasColumnType("TEXT"); + + b.Property("RedirectUris") + .HasColumnType("TEXT"); + + b.Property("Requirements") + .HasColumnType("TEXT"); + + b.Property("Settings") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("ClientId") + .IsUnique(); + + b.ToTable("OpenIddictApplications", (string)null); + }); + + modelBuilder.Entity("OpenIddict.EntityFrameworkCore.Models.OpenIddictEntityFrameworkCoreAuthorization", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("TEXT"); + + b.Property("ApplicationId") + .HasColumnType("TEXT"); + + b.Property("ConcurrencyToken") + .IsConcurrencyToken() + .HasMaxLength(50) + .HasColumnType("TEXT"); + + b.Property("CreationDate") + .HasColumnType("TEXT"); + + b.Property("Properties") + .HasColumnType("TEXT"); + + b.Property("Scopes") + .HasColumnType("TEXT"); + + b.Property("Status") + .HasMaxLength(50) + .HasColumnType("TEXT"); + + b.Property("Subject") + .HasMaxLength(400) + .HasColumnType("TEXT"); + + b.Property("Type") + .HasMaxLength(50) + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("ApplicationId", "Status", "Subject", "Type"); + + b.ToTable("OpenIddictAuthorizations", (string)null); + }); + + modelBuilder.Entity("OpenIddict.EntityFrameworkCore.Models.OpenIddictEntityFrameworkCoreScope", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("TEXT"); + + b.Property("ConcurrencyToken") + .IsConcurrencyToken() + .HasMaxLength(50) + .HasColumnType("TEXT"); + + b.Property("Description") + .HasColumnType("TEXT"); + + b.Property("Descriptions") + .HasColumnType("TEXT"); + + b.Property("DisplayName") + .HasColumnType("TEXT"); + + b.Property("DisplayNames") + .HasColumnType("TEXT"); + + b.Property("Name") + .HasMaxLength(200) + .HasColumnType("TEXT"); + + b.Property("Properties") + .HasColumnType("TEXT"); + + b.Property("Resources") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("Name") + .IsUnique(); + + b.ToTable("OpenIddictScopes", (string)null); + }); + + modelBuilder.Entity("OpenIddict.EntityFrameworkCore.Models.OpenIddictEntityFrameworkCoreToken", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("TEXT"); + + b.Property("ApplicationId") + .HasColumnType("TEXT"); + + b.Property("AuthorizationId") + .HasColumnType("TEXT"); + + b.Property("ConcurrencyToken") + .IsConcurrencyToken() + .HasMaxLength(50) + .HasColumnType("TEXT"); + + b.Property("CreationDate") + .HasColumnType("TEXT"); + + b.Property("ExpirationDate") + .HasColumnType("TEXT"); + + b.Property("Payload") + .HasColumnType("TEXT"); + + b.Property("Properties") + .HasColumnType("TEXT"); + + b.Property("RedemptionDate") + .HasColumnType("TEXT"); + + b.Property("ReferenceId") + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("Status") + .HasMaxLength(50) + .HasColumnType("TEXT"); + + b.Property("Subject") + .HasMaxLength(400) + .HasColumnType("TEXT"); + + b.Property("Type") + .HasMaxLength(50) + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("AuthorizationId"); + + b.HasIndex("ReferenceId") + .IsUnique(); + + b.HasIndex("ApplicationId", "Status", "Subject", "Type"); + + b.ToTable("OpenIddictTokens", (string)null); + }); + + modelBuilder.Entity("openiddictidp.Data.ApplicationUser", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("AccessFailedCount") + .HasColumnType("INTEGER"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("TEXT"); + + b.Property("Email") + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.Property("EmailConfirmed") + .HasColumnType("INTEGER"); + + b.Property("LockoutEnabled") + .HasColumnType("INTEGER"); + + b.Property("LockoutEnd") + .HasColumnType("TEXT"); + + b.Property("NormalizedEmail") + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.Property("NormalizedUserName") + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.Property("PasswordHash") + .HasColumnType("TEXT"); + + b.Property("PhoneNumber") + .HasColumnType("TEXT"); + + b.Property("PhoneNumberConfirmed") + .HasColumnType("INTEGER"); + + b.Property("SecurityStamp") + .HasColumnType("TEXT"); + + b.Property("TwoFactorEnabled") + .HasColumnType("INTEGER"); + + b.Property("UserName") + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedEmail") + .HasDatabaseName("EmailIndex"); + + b.HasIndex("NormalizedUserName") + .IsUnique() + .HasDatabaseName("UserNameIndex"); + + b.ToTable("AspNetUsers", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.HasOne("openiddictidp.Data.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.HasOne("openiddictidp.Data.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("openiddictidp.Data.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.HasOne("openiddictidp.Data.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("OpenIddict.EntityFrameworkCore.Models.OpenIddictEntityFrameworkCoreAuthorization", b => + { + b.HasOne("OpenIddict.EntityFrameworkCore.Models.OpenIddictEntityFrameworkCoreApplication", "Application") + .WithMany("Authorizations") + .HasForeignKey("ApplicationId"); + + b.Navigation("Application"); + }); + + modelBuilder.Entity("OpenIddict.EntityFrameworkCore.Models.OpenIddictEntityFrameworkCoreToken", b => + { + b.HasOne("OpenIddict.EntityFrameworkCore.Models.OpenIddictEntityFrameworkCoreApplication", "Application") + .WithMany("Tokens") + .HasForeignKey("ApplicationId"); + + b.HasOne("OpenIddict.EntityFrameworkCore.Models.OpenIddictEntityFrameworkCoreAuthorization", "Authorization") + .WithMany("Tokens") + .HasForeignKey("AuthorizationId"); + + b.Navigation("Application"); + + b.Navigation("Authorization"); + }); + + modelBuilder.Entity("OpenIddict.EntityFrameworkCore.Models.OpenIddictEntityFrameworkCoreApplication", b => + { + b.Navigation("Authorizations"); + + b.Navigation("Tokens"); + }); + + modelBuilder.Entity("OpenIddict.EntityFrameworkCore.Models.OpenIddictEntityFrameworkCoreAuthorization", b => + { + b.Navigation("Tokens"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/OpenIddict/OpenIddictIdP/Data/Migrations/ApplicationDb/20250707141914_InitialCreate.cs b/OpenIddict/OpenIddictIdP/Data/Migrations/ApplicationDb/20250707141914_InitialCreate.cs new file mode 100644 index 0000000..66bb981 --- /dev/null +++ b/OpenIddict/OpenIddictIdP/Data/Migrations/ApplicationDb/20250707141914_InitialCreate.cs @@ -0,0 +1,369 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace OpenIddictIdP.Data.Migrations.ApplicationDb +{ + /// + public partial class InitialCreate : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "AspNetRoles", + columns: table => new + { + Id = table.Column(type: "TEXT", nullable: false), + Name = table.Column(type: "TEXT", maxLength: 256, nullable: true), + NormalizedName = table.Column(type: "TEXT", maxLength: 256, nullable: true), + ConcurrencyStamp = table.Column(type: "TEXT", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AspNetRoles", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AspNetUsers", + columns: table => new + { + Id = table.Column(type: "TEXT", nullable: false), + UserName = table.Column(type: "TEXT", maxLength: 256, nullable: true), + NormalizedUserName = table.Column(type: "TEXT", maxLength: 256, nullable: true), + Email = table.Column(type: "TEXT", maxLength: 256, nullable: true), + NormalizedEmail = table.Column(type: "TEXT", maxLength: 256, nullable: true), + EmailConfirmed = table.Column(type: "INTEGER", nullable: false), + PasswordHash = table.Column(type: "TEXT", nullable: true), + SecurityStamp = table.Column(type: "TEXT", nullable: true), + ConcurrencyStamp = table.Column(type: "TEXT", nullable: true), + PhoneNumber = table.Column(type: "TEXT", nullable: true), + PhoneNumberConfirmed = table.Column(type: "INTEGER", nullable: false), + TwoFactorEnabled = table.Column(type: "INTEGER", nullable: false), + LockoutEnd = table.Column(type: "TEXT", nullable: true), + LockoutEnabled = table.Column(type: "INTEGER", nullable: false), + AccessFailedCount = table.Column(type: "INTEGER", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_AspNetUsers", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "OpenIddictApplications", + columns: table => new + { + Id = table.Column(type: "TEXT", nullable: false), + ApplicationType = table.Column(type: "TEXT", maxLength: 50, nullable: true), + ClientId = table.Column(type: "TEXT", maxLength: 100, nullable: true), + ClientSecret = table.Column(type: "TEXT", nullable: true), + ClientType = table.Column(type: "TEXT", maxLength: 50, nullable: true), + ConcurrencyToken = table.Column(type: "TEXT", maxLength: 50, nullable: true), + ConsentType = table.Column(type: "TEXT", maxLength: 50, nullable: true), + DisplayName = table.Column(type: "TEXT", nullable: true), + DisplayNames = table.Column(type: "TEXT", nullable: true), + JsonWebKeySet = table.Column(type: "TEXT", nullable: true), + Permissions = table.Column(type: "TEXT", nullable: true), + PostLogoutRedirectUris = table.Column(type: "TEXT", nullable: true), + Properties = table.Column(type: "TEXT", nullable: true), + RedirectUris = table.Column(type: "TEXT", nullable: true), + Requirements = table.Column(type: "TEXT", nullable: true), + Settings = table.Column(type: "TEXT", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_OpenIddictApplications", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "OpenIddictScopes", + columns: table => new + { + Id = table.Column(type: "TEXT", nullable: false), + ConcurrencyToken = table.Column(type: "TEXT", maxLength: 50, nullable: true), + Description = table.Column(type: "TEXT", nullable: true), + Descriptions = table.Column(type: "TEXT", nullable: true), + DisplayName = table.Column(type: "TEXT", nullable: true), + DisplayNames = table.Column(type: "TEXT", nullable: true), + Name = table.Column(type: "TEXT", maxLength: 200, nullable: true), + Properties = table.Column(type: "TEXT", nullable: true), + Resources = table.Column(type: "TEXT", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_OpenIddictScopes", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AspNetRoleClaims", + columns: table => new + { + Id = table.Column(type: "INTEGER", nullable: false) + .Annotation("Sqlite:Autoincrement", true), + RoleId = table.Column(type: "TEXT", nullable: false), + ClaimType = table.Column(type: "TEXT", nullable: true), + ClaimValue = table.Column(type: "TEXT", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AspNetRoleClaims", x => x.Id); + table.ForeignKey( + name: "FK_AspNetRoleClaims_AspNetRoles_RoleId", + column: x => x.RoleId, + principalTable: "AspNetRoles", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "AspNetUserClaims", + columns: table => new + { + Id = table.Column(type: "INTEGER", nullable: false) + .Annotation("Sqlite:Autoincrement", true), + UserId = table.Column(type: "TEXT", nullable: false), + ClaimType = table.Column(type: "TEXT", nullable: true), + ClaimValue = table.Column(type: "TEXT", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AspNetUserClaims", x => x.Id); + table.ForeignKey( + name: "FK_AspNetUserClaims_AspNetUsers_UserId", + column: x => x.UserId, + principalTable: "AspNetUsers", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "AspNetUserLogins", + columns: table => new + { + LoginProvider = table.Column(type: "TEXT", nullable: false), + ProviderKey = table.Column(type: "TEXT", nullable: false), + ProviderDisplayName = table.Column(type: "TEXT", nullable: true), + UserId = table.Column(type: "TEXT", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_AspNetUserLogins", x => new { x.LoginProvider, x.ProviderKey }); + table.ForeignKey( + name: "FK_AspNetUserLogins_AspNetUsers_UserId", + column: x => x.UserId, + principalTable: "AspNetUsers", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "AspNetUserRoles", + columns: table => new + { + UserId = table.Column(type: "TEXT", nullable: false), + RoleId = table.Column(type: "TEXT", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_AspNetUserRoles", x => new { x.UserId, x.RoleId }); + table.ForeignKey( + name: "FK_AspNetUserRoles_AspNetRoles_RoleId", + column: x => x.RoleId, + principalTable: "AspNetRoles", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_AspNetUserRoles_AspNetUsers_UserId", + column: x => x.UserId, + principalTable: "AspNetUsers", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "AspNetUserTokens", + columns: table => new + { + UserId = table.Column(type: "TEXT", nullable: false), + LoginProvider = table.Column(type: "TEXT", nullable: false), + Name = table.Column(type: "TEXT", nullable: false), + Value = table.Column(type: "TEXT", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AspNetUserTokens", x => new { x.UserId, x.LoginProvider, x.Name }); + table.ForeignKey( + name: "FK_AspNetUserTokens_AspNetUsers_UserId", + column: x => x.UserId, + principalTable: "AspNetUsers", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "OpenIddictAuthorizations", + columns: table => new + { + Id = table.Column(type: "TEXT", nullable: false), + ApplicationId = table.Column(type: "TEXT", nullable: true), + ConcurrencyToken = table.Column(type: "TEXT", maxLength: 50, nullable: true), + CreationDate = table.Column(type: "TEXT", nullable: true), + Properties = table.Column(type: "TEXT", nullable: true), + Scopes = table.Column(type: "TEXT", nullable: true), + Status = table.Column(type: "TEXT", maxLength: 50, nullable: true), + Subject = table.Column(type: "TEXT", maxLength: 400, nullable: true), + Type = table.Column(type: "TEXT", maxLength: 50, nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_OpenIddictAuthorizations", x => x.Id); + table.ForeignKey( + name: "FK_OpenIddictAuthorizations_OpenIddictApplications_ApplicationId", + column: x => x.ApplicationId, + principalTable: "OpenIddictApplications", + principalColumn: "Id"); + }); + + migrationBuilder.CreateTable( + name: "OpenIddictTokens", + columns: table => new + { + Id = table.Column(type: "TEXT", nullable: false), + ApplicationId = table.Column(type: "TEXT", nullable: true), + AuthorizationId = table.Column(type: "TEXT", nullable: true), + ConcurrencyToken = table.Column(type: "TEXT", maxLength: 50, nullable: true), + CreationDate = table.Column(type: "TEXT", nullable: true), + ExpirationDate = table.Column(type: "TEXT", nullable: true), + Payload = table.Column(type: "TEXT", nullable: true), + Properties = table.Column(type: "TEXT", nullable: true), + RedemptionDate = table.Column(type: "TEXT", nullable: true), + ReferenceId = table.Column(type: "TEXT", maxLength: 100, nullable: true), + Status = table.Column(type: "TEXT", maxLength: 50, nullable: true), + Subject = table.Column(type: "TEXT", maxLength: 400, nullable: true), + Type = table.Column(type: "TEXT", maxLength: 50, nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_OpenIddictTokens", x => x.Id); + table.ForeignKey( + name: "FK_OpenIddictTokens_OpenIddictApplications_ApplicationId", + column: x => x.ApplicationId, + principalTable: "OpenIddictApplications", + principalColumn: "Id"); + table.ForeignKey( + name: "FK_OpenIddictTokens_OpenIddictAuthorizations_AuthorizationId", + column: x => x.AuthorizationId, + principalTable: "OpenIddictAuthorizations", + principalColumn: "Id"); + }); + + migrationBuilder.CreateIndex( + name: "IX_AspNetRoleClaims_RoleId", + table: "AspNetRoleClaims", + column: "RoleId"); + + migrationBuilder.CreateIndex( + name: "RoleNameIndex", + table: "AspNetRoles", + column: "NormalizedName", + unique: true); + + migrationBuilder.CreateIndex( + name: "IX_AspNetUserClaims_UserId", + table: "AspNetUserClaims", + column: "UserId"); + + migrationBuilder.CreateIndex( + name: "IX_AspNetUserLogins_UserId", + table: "AspNetUserLogins", + column: "UserId"); + + migrationBuilder.CreateIndex( + name: "IX_AspNetUserRoles_RoleId", + table: "AspNetUserRoles", + column: "RoleId"); + + migrationBuilder.CreateIndex( + name: "EmailIndex", + table: "AspNetUsers", + column: "NormalizedEmail"); + + migrationBuilder.CreateIndex( + name: "UserNameIndex", + table: "AspNetUsers", + column: "NormalizedUserName", + unique: true); + + migrationBuilder.CreateIndex( + name: "IX_OpenIddictApplications_ClientId", + table: "OpenIddictApplications", + column: "ClientId", + unique: true); + + migrationBuilder.CreateIndex( + name: "IX_OpenIddictAuthorizations_ApplicationId_Status_Subject_Type", + table: "OpenIddictAuthorizations", + columns: new[] { "ApplicationId", "Status", "Subject", "Type" }); + + migrationBuilder.CreateIndex( + name: "IX_OpenIddictScopes_Name", + table: "OpenIddictScopes", + column: "Name", + unique: true); + + migrationBuilder.CreateIndex( + name: "IX_OpenIddictTokens_ApplicationId_Status_Subject_Type", + table: "OpenIddictTokens", + columns: new[] { "ApplicationId", "Status", "Subject", "Type" }); + + migrationBuilder.CreateIndex( + name: "IX_OpenIddictTokens_AuthorizationId", + table: "OpenIddictTokens", + column: "AuthorizationId"); + + migrationBuilder.CreateIndex( + name: "IX_OpenIddictTokens_ReferenceId", + table: "OpenIddictTokens", + column: "ReferenceId", + unique: true); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "AspNetRoleClaims"); + + migrationBuilder.DropTable( + name: "AspNetUserClaims"); + + migrationBuilder.DropTable( + name: "AspNetUserLogins"); + + migrationBuilder.DropTable( + name: "AspNetUserRoles"); + + migrationBuilder.DropTable( + name: "AspNetUserTokens"); + + migrationBuilder.DropTable( + name: "OpenIddictScopes"); + + migrationBuilder.DropTable( + name: "OpenIddictTokens"); + + migrationBuilder.DropTable( + name: "AspNetRoles"); + + migrationBuilder.DropTable( + name: "AspNetUsers"); + + migrationBuilder.DropTable( + name: "OpenIddictAuthorizations"); + + migrationBuilder.DropTable( + name: "OpenIddictApplications"); + } + } +} diff --git a/OpenIddict/OpenIddictIdP/Data/Migrations/ApplicationDb/ApplicationDbContextModelSnapshot.cs b/OpenIddict/OpenIddictIdP/Data/Migrations/ApplicationDb/ApplicationDbContextModelSnapshot.cs new file mode 100644 index 0000000..2c2397d --- /dev/null +++ b/OpenIddict/OpenIddictIdP/Data/Migrations/ApplicationDb/ApplicationDbContextModelSnapshot.cs @@ -0,0 +1,509 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using openiddictidp.Data; + +#nullable disable + +namespace OpenIddictIdP.Data.Migrations.ApplicationDb +{ + [DbContext(typeof(ApplicationDbContext))] + partial class ApplicationDbContextModelSnapshot : ModelSnapshot + { + protected override void BuildModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder.HasAnnotation("ProductVersion", "8.0.17"); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("TEXT"); + + b.Property("Name") + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.Property("NormalizedName") + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedName") + .IsUnique() + .HasDatabaseName("RoleNameIndex"); + + b.ToTable("AspNetRoles", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ClaimType") + .HasColumnType("TEXT"); + + b.Property("ClaimValue") + .HasColumnType("TEXT"); + + b.Property("RoleId") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetRoleClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ClaimType") + .HasColumnType("TEXT"); + + b.Property("ClaimValue") + .HasColumnType("TEXT"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.Property("LoginProvider") + .HasColumnType("TEXT"); + + b.Property("ProviderKey") + .HasColumnType("TEXT"); + + b.Property("ProviderDisplayName") + .HasColumnType("TEXT"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("LoginProvider", "ProviderKey"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserLogins", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.Property("UserId") + .HasColumnType("TEXT"); + + b.Property("RoleId") + .HasColumnType("TEXT"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetUserRoles", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.Property("UserId") + .HasColumnType("TEXT"); + + b.Property("LoginProvider") + .HasColumnType("TEXT"); + + b.Property("Name") + .HasColumnType("TEXT"); + + b.Property("Value") + .HasColumnType("TEXT"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("AspNetUserTokens", (string)null); + }); + + modelBuilder.Entity("OpenIddict.EntityFrameworkCore.Models.OpenIddictEntityFrameworkCoreApplication", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("TEXT"); + + b.Property("ApplicationType") + .HasMaxLength(50) + .HasColumnType("TEXT"); + + b.Property("ClientId") + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("ClientSecret") + .HasColumnType("TEXT"); + + b.Property("ClientType") + .HasMaxLength(50) + .HasColumnType("TEXT"); + + b.Property("ConcurrencyToken") + .IsConcurrencyToken() + .HasMaxLength(50) + .HasColumnType("TEXT"); + + b.Property("ConsentType") + .HasMaxLength(50) + .HasColumnType("TEXT"); + + b.Property("DisplayName") + .HasColumnType("TEXT"); + + b.Property("DisplayNames") + .HasColumnType("TEXT"); + + b.Property("JsonWebKeySet") + .HasColumnType("TEXT"); + + b.Property("Permissions") + .HasColumnType("TEXT"); + + b.Property("PostLogoutRedirectUris") + .HasColumnType("TEXT"); + + b.Property("Properties") + .HasColumnType("TEXT"); + + b.Property("RedirectUris") + .HasColumnType("TEXT"); + + b.Property("Requirements") + .HasColumnType("TEXT"); + + b.Property("Settings") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("ClientId") + .IsUnique(); + + b.ToTable("OpenIddictApplications", (string)null); + }); + + modelBuilder.Entity("OpenIddict.EntityFrameworkCore.Models.OpenIddictEntityFrameworkCoreAuthorization", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("TEXT"); + + b.Property("ApplicationId") + .HasColumnType("TEXT"); + + b.Property("ConcurrencyToken") + .IsConcurrencyToken() + .HasMaxLength(50) + .HasColumnType("TEXT"); + + b.Property("CreationDate") + .HasColumnType("TEXT"); + + b.Property("Properties") + .HasColumnType("TEXT"); + + b.Property("Scopes") + .HasColumnType("TEXT"); + + b.Property("Status") + .HasMaxLength(50) + .HasColumnType("TEXT"); + + b.Property("Subject") + .HasMaxLength(400) + .HasColumnType("TEXT"); + + b.Property("Type") + .HasMaxLength(50) + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("ApplicationId", "Status", "Subject", "Type"); + + b.ToTable("OpenIddictAuthorizations", (string)null); + }); + + modelBuilder.Entity("OpenIddict.EntityFrameworkCore.Models.OpenIddictEntityFrameworkCoreScope", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("TEXT"); + + b.Property("ConcurrencyToken") + .IsConcurrencyToken() + .HasMaxLength(50) + .HasColumnType("TEXT"); + + b.Property("Description") + .HasColumnType("TEXT"); + + b.Property("Descriptions") + .HasColumnType("TEXT"); + + b.Property("DisplayName") + .HasColumnType("TEXT"); + + b.Property("DisplayNames") + .HasColumnType("TEXT"); + + b.Property("Name") + .HasMaxLength(200) + .HasColumnType("TEXT"); + + b.Property("Properties") + .HasColumnType("TEXT"); + + b.Property("Resources") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("Name") + .IsUnique(); + + b.ToTable("OpenIddictScopes", (string)null); + }); + + modelBuilder.Entity("OpenIddict.EntityFrameworkCore.Models.OpenIddictEntityFrameworkCoreToken", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("TEXT"); + + b.Property("ApplicationId") + .HasColumnType("TEXT"); + + b.Property("AuthorizationId") + .HasColumnType("TEXT"); + + b.Property("ConcurrencyToken") + .IsConcurrencyToken() + .HasMaxLength(50) + .HasColumnType("TEXT"); + + b.Property("CreationDate") + .HasColumnType("TEXT"); + + b.Property("ExpirationDate") + .HasColumnType("TEXT"); + + b.Property("Payload") + .HasColumnType("TEXT"); + + b.Property("Properties") + .HasColumnType("TEXT"); + + b.Property("RedemptionDate") + .HasColumnType("TEXT"); + + b.Property("ReferenceId") + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("Status") + .HasMaxLength(50) + .HasColumnType("TEXT"); + + b.Property("Subject") + .HasMaxLength(400) + .HasColumnType("TEXT"); + + b.Property("Type") + .HasMaxLength(50) + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("AuthorizationId"); + + b.HasIndex("ReferenceId") + .IsUnique(); + + b.HasIndex("ApplicationId", "Status", "Subject", "Type"); + + b.ToTable("OpenIddictTokens", (string)null); + }); + + modelBuilder.Entity("openiddictidp.Data.ApplicationUser", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("AccessFailedCount") + .HasColumnType("INTEGER"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("TEXT"); + + b.Property("Email") + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.Property("EmailConfirmed") + .HasColumnType("INTEGER"); + + b.Property("LockoutEnabled") + .HasColumnType("INTEGER"); + + b.Property("LockoutEnd") + .HasColumnType("TEXT"); + + b.Property("NormalizedEmail") + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.Property("NormalizedUserName") + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.Property("PasswordHash") + .HasColumnType("TEXT"); + + b.Property("PhoneNumber") + .HasColumnType("TEXT"); + + b.Property("PhoneNumberConfirmed") + .HasColumnType("INTEGER"); + + b.Property("SecurityStamp") + .HasColumnType("TEXT"); + + b.Property("TwoFactorEnabled") + .HasColumnType("INTEGER"); + + b.Property("UserName") + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedEmail") + .HasDatabaseName("EmailIndex"); + + b.HasIndex("NormalizedUserName") + .IsUnique() + .HasDatabaseName("UserNameIndex"); + + b.ToTable("AspNetUsers", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.HasOne("openiddictidp.Data.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.HasOne("openiddictidp.Data.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("openiddictidp.Data.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.HasOne("openiddictidp.Data.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("OpenIddict.EntityFrameworkCore.Models.OpenIddictEntityFrameworkCoreAuthorization", b => + { + b.HasOne("OpenIddict.EntityFrameworkCore.Models.OpenIddictEntityFrameworkCoreApplication", "Application") + .WithMany("Authorizations") + .HasForeignKey("ApplicationId"); + + b.Navigation("Application"); + }); + + modelBuilder.Entity("OpenIddict.EntityFrameworkCore.Models.OpenIddictEntityFrameworkCoreToken", b => + { + b.HasOne("OpenIddict.EntityFrameworkCore.Models.OpenIddictEntityFrameworkCoreApplication", "Application") + .WithMany("Tokens") + .HasForeignKey("ApplicationId"); + + b.HasOne("OpenIddict.EntityFrameworkCore.Models.OpenIddictEntityFrameworkCoreAuthorization", "Authorization") + .WithMany("Tokens") + .HasForeignKey("AuthorizationId"); + + b.Navigation("Application"); + + b.Navigation("Authorization"); + }); + + modelBuilder.Entity("OpenIddict.EntityFrameworkCore.Models.OpenIddictEntityFrameworkCoreApplication", b => + { + b.Navigation("Authorizations"); + + b.Navigation("Tokens"); + }); + + modelBuilder.Entity("OpenIddict.EntityFrameworkCore.Models.OpenIddictEntityFrameworkCoreAuthorization", b => + { + b.Navigation("Tokens"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/OpenIddict/OpenIddictIdP/Data/Migrations/OpenIddictSamlMessage/20250707141929_InitialCreate.Designer.cs b/OpenIddict/OpenIddictIdP/Data/Migrations/OpenIddictSamlMessage/20250707141929_InitialCreate.Designer.cs new file mode 100644 index 0000000..561518c --- /dev/null +++ b/OpenIddict/OpenIddictIdP/Data/Migrations/OpenIddictSamlMessage/20250707141929_InitialCreate.Designer.cs @@ -0,0 +1,66 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Rsk.Saml.OpenIddict.EntityFrameworkCore.DbContexts; + +#nullable disable + +namespace OpenIddictIdP.Data.Migrations.OpenIddictSamlMessage +{ + [DbContext(typeof(OpenIddictSamlMessageDbContext))] + [Migration("20250707141929_InitialCreate")] + partial class InitialCreate + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder.HasAnnotation("ProductVersion", "8.0.17"); + + modelBuilder.Entity("Rsk.Saml.OpenIddict.EntityFrameworkCore.Models.OpenIddictEntityFrameworkCoreSamlMessage", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("CreationTime") + .HasColumnType("TEXT"); + + b.Property("Data") + .IsRequired() + .HasMaxLength(50000) + .HasColumnType("TEXT"); + + b.Property("EntityId") + .HasMaxLength(200) + .HasColumnType("TEXT"); + + b.Property("Expiration") + .HasColumnType("TEXT"); + + b.Property("RequestId") + .HasMaxLength(200) + .HasColumnType("TEXT"); + + b.Property("Type") + .HasMaxLength(50) + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("CreationTime"); + + b.HasIndex("Expiration"); + + b.HasIndex("RequestId") + .IsUnique(); + + b.ToTable("OpenIddctSamlMessages", (string)null); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/OpenIddict/OpenIddictIdP/Data/Migrations/OpenIddictSamlMessage/20250707141929_InitialCreate.cs b/OpenIddict/OpenIddictIdP/Data/Migrations/OpenIddictSamlMessage/20250707141929_InitialCreate.cs new file mode 100644 index 0000000..afe9ff9 --- /dev/null +++ b/OpenIddict/OpenIddictIdP/Data/Migrations/OpenIddictSamlMessage/20250707141929_InitialCreate.cs @@ -0,0 +1,56 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace OpenIddictIdP.Data.Migrations.OpenIddictSamlMessage +{ + /// + public partial class InitialCreate : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "OpenIddctSamlMessages", + columns: table => new + { + Id = table.Column(type: "INTEGER", nullable: false) + .Annotation("Sqlite:Autoincrement", true), + RequestId = table.Column(type: "TEXT", maxLength: 200, nullable: true), + EntityId = table.Column(type: "TEXT", maxLength: 200, nullable: true), + Type = table.Column(type: "TEXT", maxLength: 50, nullable: true), + CreationTime = table.Column(type: "TEXT", nullable: false), + Expiration = table.Column(type: "TEXT", nullable: false), + Data = table.Column(type: "TEXT", maxLength: 50000, nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_OpenIddctSamlMessages", x => x.Id); + }); + + migrationBuilder.CreateIndex( + name: "IX_OpenIddctSamlMessages_CreationTime", + table: "OpenIddctSamlMessages", + column: "CreationTime"); + + migrationBuilder.CreateIndex( + name: "IX_OpenIddctSamlMessages_Expiration", + table: "OpenIddctSamlMessages", + column: "Expiration"); + + migrationBuilder.CreateIndex( + name: "IX_OpenIddctSamlMessages_RequestId", + table: "OpenIddctSamlMessages", + column: "RequestId", + unique: true); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "OpenIddctSamlMessages"); + } + } +} diff --git a/OpenIddict/OpenIddictIdP/Data/Migrations/OpenIddictSamlMessage/OpenIddictSamlMessageDbContextModelSnapshot.cs b/OpenIddict/OpenIddictIdP/Data/Migrations/OpenIddictSamlMessage/OpenIddictSamlMessageDbContextModelSnapshot.cs new file mode 100644 index 0000000..f255561 --- /dev/null +++ b/OpenIddict/OpenIddictIdP/Data/Migrations/OpenIddictSamlMessage/OpenIddictSamlMessageDbContextModelSnapshot.cs @@ -0,0 +1,63 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Rsk.Saml.OpenIddict.EntityFrameworkCore.DbContexts; + +#nullable disable + +namespace OpenIddictIdP.Data.Migrations.OpenIddictSamlMessage +{ + [DbContext(typeof(OpenIddictSamlMessageDbContext))] + partial class OpenIddictSamlMessageDbContextModelSnapshot : ModelSnapshot + { + protected override void BuildModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder.HasAnnotation("ProductVersion", "8.0.17"); + + modelBuilder.Entity("Rsk.Saml.OpenIddict.EntityFrameworkCore.Models.OpenIddictEntityFrameworkCoreSamlMessage", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("CreationTime") + .HasColumnType("TEXT"); + + b.Property("Data") + .IsRequired() + .HasMaxLength(50000) + .HasColumnType("TEXT"); + + b.Property("EntityId") + .HasMaxLength(200) + .HasColumnType("TEXT"); + + b.Property("Expiration") + .HasColumnType("TEXT"); + + b.Property("RequestId") + .HasMaxLength(200) + .HasColumnType("TEXT"); + + b.Property("Type") + .HasMaxLength(50) + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("CreationTime"); + + b.HasIndex("Expiration"); + + b.HasIndex("RequestId") + .IsUnique(); + + b.ToTable("OpenIddctSamlMessages", (string)null); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/OpenIddict/OpenIddictIdP/Data/Migrations/SamlConfiguration/20250707141940_InitialCreate.Designer.cs b/OpenIddict/OpenIddictIdP/Data/Migrations/SamlConfiguration/20250707141940_InitialCreate.Designer.cs new file mode 100644 index 0000000..fc08002 --- /dev/null +++ b/OpenIddict/OpenIddictIdP/Data/Migrations/SamlConfiguration/20250707141940_InitialCreate.Designer.cs @@ -0,0 +1,284 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Rsk.Saml.IdentityProvider.Storage.EntityFramework.DbContexts; + +#nullable disable + +namespace OpenIddictIdP.Data.Migrations.SamlConfiguration +{ + [DbContext(typeof(SamlConfigurationDbContext))] + [Migration("20250707141940_InitialCreate")] + partial class InitialCreate + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder.HasAnnotation("ProductVersion", "8.0.17"); + + modelBuilder.Entity("Rsk.Saml.IdentityProvider.Storage.EntityFramework.Entities.ArtifactResolutionService", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Binding") + .IsRequired() + .HasMaxLength(2000) + .HasColumnType("TEXT"); + + b.Property("Index") + .HasColumnType("INTEGER"); + + b.Property("IsDefault") + .HasColumnType("INTEGER"); + + b.Property("Location") + .IsRequired() + .HasMaxLength(2000) + .HasColumnType("TEXT"); + + b.Property("ServiceProviderId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("ServiceProviderId"); + + b.ToTable("ServiceProviderArtifactResolutionServices", (string)null); + }); + + modelBuilder.Entity("Rsk.Saml.IdentityProvider.Storage.EntityFramework.Entities.AssertionConsumerService", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Binding") + .IsRequired() + .HasMaxLength(2000) + .HasColumnType("TEXT"); + + b.Property("Index") + .HasColumnType("INTEGER"); + + b.Property("IsDefault") + .HasColumnType("INTEGER"); + + b.Property("Location") + .IsRequired() + .HasMaxLength(2000) + .HasColumnType("TEXT"); + + b.Property("ServiceProviderId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("ServiceProviderId"); + + b.ToTable("ServiceProviderAssertionConsumerServices", (string)null); + }); + + modelBuilder.Entity("Rsk.Saml.IdentityProvider.Storage.EntityFramework.Entities.SamlClaimMap", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("NewClaimType") + .IsRequired() + .HasMaxLength(250) + .HasColumnType("TEXT"); + + b.Property("OriginalClaimType") + .IsRequired() + .HasMaxLength(250) + .HasColumnType("TEXT"); + + b.Property("ServiceProviderId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("ServiceProviderId"); + + b.ToTable("ServiceProviderClaimMappings", (string)null); + }); + + modelBuilder.Entity("Rsk.Saml.IdentityProvider.Storage.EntityFramework.Entities.ServiceProvider", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AllowIdpInitiatedSso") + .HasColumnType("INTEGER"); + + b.Property("ArtifactDeliveryBindingType") + .HasColumnType("TEXT"); + + b.Property("EncryptAssertions") + .HasColumnType("INTEGER"); + + b.Property("EncryptionCertificate") + .HasColumnType("BLOB"); + + b.Property("EntityId") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("TEXT"); + + b.Property("NameIdentifierFormat") + .HasColumnType("TEXT"); + + b.Property("RequireAuthenticationRequestsSigned") + .HasColumnType("INTEGER"); + + b.Property("RequireSamlMessageDestination") + .HasColumnType("INTEGER"); + + b.Property("RequireSignedArtifactResolveRequests") + .HasColumnType("INTEGER"); + + b.Property("RequireSignedArtifactResponses") + .HasColumnType("INTEGER"); + + b.Property("SignAssertions") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("EntityId") + .IsUnique(); + + b.ToTable("ServiceProviders", (string)null); + }); + + modelBuilder.Entity("Rsk.Saml.IdentityProvider.Storage.EntityFramework.Entities.SigningCertificate", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Certificate") + .IsRequired() + .HasColumnType("BLOB"); + + b.Property("ServiceProviderId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("ServiceProviderId"); + + b.ToTable("ServiceProviderSignCertificates", (string)null); + }); + + modelBuilder.Entity("Rsk.Saml.IdentityProvider.Storage.EntityFramework.Entities.SingleLogoutService", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Binding") + .IsRequired() + .HasMaxLength(2000) + .HasColumnType("TEXT"); + + b.Property("Index") + .HasColumnType("INTEGER"); + + b.Property("IsDefault") + .HasColumnType("INTEGER"); + + b.Property("Location") + .IsRequired() + .HasMaxLength(2000) + .HasColumnType("TEXT"); + + b.Property("ServiceProviderId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("ServiceProviderId"); + + b.ToTable("ServiceProviderSingleLogoutServices", (string)null); + }); + + modelBuilder.Entity("Rsk.Saml.IdentityProvider.Storage.EntityFramework.Entities.ArtifactResolutionService", b => + { + b.HasOne("Rsk.Saml.IdentityProvider.Storage.EntityFramework.Entities.ServiceProvider", "ServiceProvider") + .WithMany("ArtifactResolutionServices") + .HasForeignKey("ServiceProviderId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("ServiceProvider"); + }); + + modelBuilder.Entity("Rsk.Saml.IdentityProvider.Storage.EntityFramework.Entities.AssertionConsumerService", b => + { + b.HasOne("Rsk.Saml.IdentityProvider.Storage.EntityFramework.Entities.ServiceProvider", "ServiceProvider") + .WithMany("AssertionConsumerServices") + .HasForeignKey("ServiceProviderId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("ServiceProvider"); + }); + + modelBuilder.Entity("Rsk.Saml.IdentityProvider.Storage.EntityFramework.Entities.SamlClaimMap", b => + { + b.HasOne("Rsk.Saml.IdentityProvider.Storage.EntityFramework.Entities.ServiceProvider", "ServiceProvider") + .WithMany("ClaimsMapping") + .HasForeignKey("ServiceProviderId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("ServiceProvider"); + }); + + modelBuilder.Entity("Rsk.Saml.IdentityProvider.Storage.EntityFramework.Entities.SigningCertificate", b => + { + b.HasOne("Rsk.Saml.IdentityProvider.Storage.EntityFramework.Entities.ServiceProvider", "ServiceProvider") + .WithMany("SigningCertificates") + .HasForeignKey("ServiceProviderId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("ServiceProvider"); + }); + + modelBuilder.Entity("Rsk.Saml.IdentityProvider.Storage.EntityFramework.Entities.SingleLogoutService", b => + { + b.HasOne("Rsk.Saml.IdentityProvider.Storage.EntityFramework.Entities.ServiceProvider", "ServiceProvider") + .WithMany("SingleLogoutServices") + .HasForeignKey("ServiceProviderId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("ServiceProvider"); + }); + + modelBuilder.Entity("Rsk.Saml.IdentityProvider.Storage.EntityFramework.Entities.ServiceProvider", b => + { + b.Navigation("ArtifactResolutionServices"); + + b.Navigation("AssertionConsumerServices"); + + b.Navigation("ClaimsMapping"); + + b.Navigation("SigningCertificates"); + + b.Navigation("SingleLogoutServices"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/OpenIddict/OpenIddictIdP/Data/Migrations/SamlConfiguration/20250707141940_InitialCreate.cs b/OpenIddict/OpenIddictIdP/Data/Migrations/SamlConfiguration/20250707141940_InitialCreate.cs new file mode 100644 index 0000000..1f62812 --- /dev/null +++ b/OpenIddict/OpenIddictIdP/Data/Migrations/SamlConfiguration/20250707141940_InitialCreate.cs @@ -0,0 +1,200 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace OpenIddictIdP.Data.Migrations.SamlConfiguration +{ + /// + public partial class InitialCreate : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "ServiceProviders", + columns: table => new + { + Id = table.Column(type: "INTEGER", nullable: false) + .Annotation("Sqlite:Autoincrement", true), + EntityId = table.Column(type: "TEXT", maxLength: 200, nullable: false), + EncryptionCertificate = table.Column(type: "BLOB", nullable: true), + SignAssertions = table.Column(type: "INTEGER", nullable: false), + EncryptAssertions = table.Column(type: "INTEGER", nullable: false), + RequireSamlMessageDestination = table.Column(type: "INTEGER", nullable: false), + AllowIdpInitiatedSso = table.Column(type: "INTEGER", nullable: false), + RequireAuthenticationRequestsSigned = table.Column(type: "INTEGER", nullable: true), + ArtifactDeliveryBindingType = table.Column(type: "TEXT", nullable: true), + RequireSignedArtifactResponses = table.Column(type: "INTEGER", nullable: true), + RequireSignedArtifactResolveRequests = table.Column(type: "INTEGER", nullable: true), + NameIdentifierFormat = table.Column(type: "TEXT", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_ServiceProviders", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "ServiceProviderArtifactResolutionServices", + columns: table => new + { + Id = table.Column(type: "INTEGER", nullable: false) + .Annotation("Sqlite:Autoincrement", true), + Binding = table.Column(type: "TEXT", maxLength: 2000, nullable: false), + Location = table.Column(type: "TEXT", maxLength: 2000, nullable: false), + Index = table.Column(type: "INTEGER", nullable: false), + IsDefault = table.Column(type: "INTEGER", nullable: false), + ServiceProviderId = table.Column(type: "INTEGER", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_ServiceProviderArtifactResolutionServices", x => x.Id); + table.ForeignKey( + name: "FK_ServiceProviderArtifactResolutionServices_ServiceProviders_ServiceProviderId", + column: x => x.ServiceProviderId, + principalTable: "ServiceProviders", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "ServiceProviderAssertionConsumerServices", + columns: table => new + { + Id = table.Column(type: "INTEGER", nullable: false) + .Annotation("Sqlite:Autoincrement", true), + Binding = table.Column(type: "TEXT", maxLength: 2000, nullable: false), + Location = table.Column(type: "TEXT", maxLength: 2000, nullable: false), + Index = table.Column(type: "INTEGER", nullable: false), + IsDefault = table.Column(type: "INTEGER", nullable: false), + ServiceProviderId = table.Column(type: "INTEGER", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_ServiceProviderAssertionConsumerServices", x => x.Id); + table.ForeignKey( + name: "FK_ServiceProviderAssertionConsumerServices_ServiceProviders_ServiceProviderId", + column: x => x.ServiceProviderId, + principalTable: "ServiceProviders", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "ServiceProviderClaimMappings", + columns: table => new + { + Id = table.Column(type: "INTEGER", nullable: false) + .Annotation("Sqlite:Autoincrement", true), + OriginalClaimType = table.Column(type: "TEXT", maxLength: 250, nullable: false), + NewClaimType = table.Column(type: "TEXT", maxLength: 250, nullable: false), + ServiceProviderId = table.Column(type: "INTEGER", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_ServiceProviderClaimMappings", x => x.Id); + table.ForeignKey( + name: "FK_ServiceProviderClaimMappings_ServiceProviders_ServiceProviderId", + column: x => x.ServiceProviderId, + principalTable: "ServiceProviders", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "ServiceProviderSignCertificates", + columns: table => new + { + Id = table.Column(type: "INTEGER", nullable: false) + .Annotation("Sqlite:Autoincrement", true), + Certificate = table.Column(type: "BLOB", nullable: false), + ServiceProviderId = table.Column(type: "INTEGER", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_ServiceProviderSignCertificates", x => x.Id); + table.ForeignKey( + name: "FK_ServiceProviderSignCertificates_ServiceProviders_ServiceProviderId", + column: x => x.ServiceProviderId, + principalTable: "ServiceProviders", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "ServiceProviderSingleLogoutServices", + columns: table => new + { + Id = table.Column(type: "INTEGER", nullable: false) + .Annotation("Sqlite:Autoincrement", true), + Binding = table.Column(type: "TEXT", maxLength: 2000, nullable: false), + Location = table.Column(type: "TEXT", maxLength: 2000, nullable: false), + Index = table.Column(type: "INTEGER", nullable: false), + IsDefault = table.Column(type: "INTEGER", nullable: false), + ServiceProviderId = table.Column(type: "INTEGER", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_ServiceProviderSingleLogoutServices", x => x.Id); + table.ForeignKey( + name: "FK_ServiceProviderSingleLogoutServices_ServiceProviders_ServiceProviderId", + column: x => x.ServiceProviderId, + principalTable: "ServiceProviders", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateIndex( + name: "IX_ServiceProviderArtifactResolutionServices_ServiceProviderId", + table: "ServiceProviderArtifactResolutionServices", + column: "ServiceProviderId"); + + migrationBuilder.CreateIndex( + name: "IX_ServiceProviderAssertionConsumerServices_ServiceProviderId", + table: "ServiceProviderAssertionConsumerServices", + column: "ServiceProviderId"); + + migrationBuilder.CreateIndex( + name: "IX_ServiceProviderClaimMappings_ServiceProviderId", + table: "ServiceProviderClaimMappings", + column: "ServiceProviderId"); + + migrationBuilder.CreateIndex( + name: "IX_ServiceProviders_EntityId", + table: "ServiceProviders", + column: "EntityId", + unique: true); + + migrationBuilder.CreateIndex( + name: "IX_ServiceProviderSignCertificates_ServiceProviderId", + table: "ServiceProviderSignCertificates", + column: "ServiceProviderId"); + + migrationBuilder.CreateIndex( + name: "IX_ServiceProviderSingleLogoutServices_ServiceProviderId", + table: "ServiceProviderSingleLogoutServices", + column: "ServiceProviderId"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "ServiceProviderArtifactResolutionServices"); + + migrationBuilder.DropTable( + name: "ServiceProviderAssertionConsumerServices"); + + migrationBuilder.DropTable( + name: "ServiceProviderClaimMappings"); + + migrationBuilder.DropTable( + name: "ServiceProviderSignCertificates"); + + migrationBuilder.DropTable( + name: "ServiceProviderSingleLogoutServices"); + + migrationBuilder.DropTable( + name: "ServiceProviders"); + } + } +} diff --git a/OpenIddict/OpenIddictIdP/Data/Migrations/SamlConfiguration/SamlConfigurationDbContextModelSnapshot.cs b/OpenIddict/OpenIddictIdP/Data/Migrations/SamlConfiguration/SamlConfigurationDbContextModelSnapshot.cs new file mode 100644 index 0000000..cd68081 --- /dev/null +++ b/OpenIddict/OpenIddictIdP/Data/Migrations/SamlConfiguration/SamlConfigurationDbContextModelSnapshot.cs @@ -0,0 +1,281 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Rsk.Saml.IdentityProvider.Storage.EntityFramework.DbContexts; + +#nullable disable + +namespace OpenIddictIdP.Data.Migrations.SamlConfiguration +{ + [DbContext(typeof(SamlConfigurationDbContext))] + partial class SamlConfigurationDbContextModelSnapshot : ModelSnapshot + { + protected override void BuildModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder.HasAnnotation("ProductVersion", "8.0.17"); + + modelBuilder.Entity("Rsk.Saml.IdentityProvider.Storage.EntityFramework.Entities.ArtifactResolutionService", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Binding") + .IsRequired() + .HasMaxLength(2000) + .HasColumnType("TEXT"); + + b.Property("Index") + .HasColumnType("INTEGER"); + + b.Property("IsDefault") + .HasColumnType("INTEGER"); + + b.Property("Location") + .IsRequired() + .HasMaxLength(2000) + .HasColumnType("TEXT"); + + b.Property("ServiceProviderId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("ServiceProviderId"); + + b.ToTable("ServiceProviderArtifactResolutionServices", (string)null); + }); + + modelBuilder.Entity("Rsk.Saml.IdentityProvider.Storage.EntityFramework.Entities.AssertionConsumerService", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Binding") + .IsRequired() + .HasMaxLength(2000) + .HasColumnType("TEXT"); + + b.Property("Index") + .HasColumnType("INTEGER"); + + b.Property("IsDefault") + .HasColumnType("INTEGER"); + + b.Property("Location") + .IsRequired() + .HasMaxLength(2000) + .HasColumnType("TEXT"); + + b.Property("ServiceProviderId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("ServiceProviderId"); + + b.ToTable("ServiceProviderAssertionConsumerServices", (string)null); + }); + + modelBuilder.Entity("Rsk.Saml.IdentityProvider.Storage.EntityFramework.Entities.SamlClaimMap", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("NewClaimType") + .IsRequired() + .HasMaxLength(250) + .HasColumnType("TEXT"); + + b.Property("OriginalClaimType") + .IsRequired() + .HasMaxLength(250) + .HasColumnType("TEXT"); + + b.Property("ServiceProviderId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("ServiceProviderId"); + + b.ToTable("ServiceProviderClaimMappings", (string)null); + }); + + modelBuilder.Entity("Rsk.Saml.IdentityProvider.Storage.EntityFramework.Entities.ServiceProvider", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AllowIdpInitiatedSso") + .HasColumnType("INTEGER"); + + b.Property("ArtifactDeliveryBindingType") + .HasColumnType("TEXT"); + + b.Property("EncryptAssertions") + .HasColumnType("INTEGER"); + + b.Property("EncryptionCertificate") + .HasColumnType("BLOB"); + + b.Property("EntityId") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("TEXT"); + + b.Property("NameIdentifierFormat") + .HasColumnType("TEXT"); + + b.Property("RequireAuthenticationRequestsSigned") + .HasColumnType("INTEGER"); + + b.Property("RequireSamlMessageDestination") + .HasColumnType("INTEGER"); + + b.Property("RequireSignedArtifactResolveRequests") + .HasColumnType("INTEGER"); + + b.Property("RequireSignedArtifactResponses") + .HasColumnType("INTEGER"); + + b.Property("SignAssertions") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("EntityId") + .IsUnique(); + + b.ToTable("ServiceProviders", (string)null); + }); + + modelBuilder.Entity("Rsk.Saml.IdentityProvider.Storage.EntityFramework.Entities.SigningCertificate", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Certificate") + .IsRequired() + .HasColumnType("BLOB"); + + b.Property("ServiceProviderId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("ServiceProviderId"); + + b.ToTable("ServiceProviderSignCertificates", (string)null); + }); + + modelBuilder.Entity("Rsk.Saml.IdentityProvider.Storage.EntityFramework.Entities.SingleLogoutService", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Binding") + .IsRequired() + .HasMaxLength(2000) + .HasColumnType("TEXT"); + + b.Property("Index") + .HasColumnType("INTEGER"); + + b.Property("IsDefault") + .HasColumnType("INTEGER"); + + b.Property("Location") + .IsRequired() + .HasMaxLength(2000) + .HasColumnType("TEXT"); + + b.Property("ServiceProviderId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("ServiceProviderId"); + + b.ToTable("ServiceProviderSingleLogoutServices", (string)null); + }); + + modelBuilder.Entity("Rsk.Saml.IdentityProvider.Storage.EntityFramework.Entities.ArtifactResolutionService", b => + { + b.HasOne("Rsk.Saml.IdentityProvider.Storage.EntityFramework.Entities.ServiceProvider", "ServiceProvider") + .WithMany("ArtifactResolutionServices") + .HasForeignKey("ServiceProviderId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("ServiceProvider"); + }); + + modelBuilder.Entity("Rsk.Saml.IdentityProvider.Storage.EntityFramework.Entities.AssertionConsumerService", b => + { + b.HasOne("Rsk.Saml.IdentityProvider.Storage.EntityFramework.Entities.ServiceProvider", "ServiceProvider") + .WithMany("AssertionConsumerServices") + .HasForeignKey("ServiceProviderId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("ServiceProvider"); + }); + + modelBuilder.Entity("Rsk.Saml.IdentityProvider.Storage.EntityFramework.Entities.SamlClaimMap", b => + { + b.HasOne("Rsk.Saml.IdentityProvider.Storage.EntityFramework.Entities.ServiceProvider", "ServiceProvider") + .WithMany("ClaimsMapping") + .HasForeignKey("ServiceProviderId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("ServiceProvider"); + }); + + modelBuilder.Entity("Rsk.Saml.IdentityProvider.Storage.EntityFramework.Entities.SigningCertificate", b => + { + b.HasOne("Rsk.Saml.IdentityProvider.Storage.EntityFramework.Entities.ServiceProvider", "ServiceProvider") + .WithMany("SigningCertificates") + .HasForeignKey("ServiceProviderId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("ServiceProvider"); + }); + + modelBuilder.Entity("Rsk.Saml.IdentityProvider.Storage.EntityFramework.Entities.SingleLogoutService", b => + { + b.HasOne("Rsk.Saml.IdentityProvider.Storage.EntityFramework.Entities.ServiceProvider", "ServiceProvider") + .WithMany("SingleLogoutServices") + .HasForeignKey("ServiceProviderId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("ServiceProvider"); + }); + + modelBuilder.Entity("Rsk.Saml.IdentityProvider.Storage.EntityFramework.Entities.ServiceProvider", b => + { + b.Navigation("ArtifactResolutionServices"); + + b.Navigation("AssertionConsumerServices"); + + b.Navigation("ClaimsMapping"); + + b.Navigation("SigningCertificates"); + + b.Navigation("SingleLogoutServices"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/OpenIddict/OpenIddictIdP/DbProvider.cs b/OpenIddict/OpenIddictIdP/DbProvider.cs new file mode 100644 index 0000000..83c6f74 --- /dev/null +++ b/OpenIddict/OpenIddictIdP/DbProvider.cs @@ -0,0 +1,9 @@ +namespace openiddictidp; + +public enum DbProvider +{ + Sqlite, + SqlServer, + MySql, + PostgreSql +} \ No newline at end of file diff --git a/OpenIddict/OpenIddictIdP/JwtClaimTypes.cs b/OpenIddict/OpenIddictIdP/JwtClaimTypes.cs new file mode 100644 index 0000000..bad4104 --- /dev/null +++ b/OpenIddict/OpenIddictIdP/JwtClaimTypes.cs @@ -0,0 +1,9 @@ +namespace openiddictidp; + +public class JwtClaimTypes +{ + public const string Subject = "sub"; + public const string Name = "name"; + public const string Role = "role"; + public const string Email = "email"; +} \ No newline at end of file diff --git a/OpenIddict/OpenIddictIdP/OpenIddictIdP.csproj b/OpenIddict/OpenIddictIdP/OpenIddictIdP.csproj index b2eab57..f726d9a 100644 --- a/OpenIddict/OpenIddictIdP/OpenIddictIdP.csproj +++ b/OpenIddict/OpenIddictIdP/OpenIddictIdP.csproj @@ -7,22 +7,24 @@ - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + diff --git a/OpenIddict/OpenIddictIdP/README.md b/OpenIddict/OpenIddictIdP/README.md new file mode 100644 index 0000000..806176f --- /dev/null +++ b/OpenIddict/OpenIddictIdP/README.md @@ -0,0 +1,38 @@ +# OpenIddict IDP sample + +To run the project with a specific database provider, the following commands and connection strings can be used to run with the database servers in Docker + +#### PostgreSQL + +```sh +docker run --name my-postgres -e POSTGRES_USER=myuser -e POSTGRES_PASSWORD=mypassword -e POSTGRES_DB=mydb -p 5432:5432 -d postgres:latest +``` + +Connection string: +``` +Host=localhost;Port=5432;Database=mydb;Username=myuser;Password=mypassword +``` + +#### MySQL + +```sh +docker run --name my-mysql -e MYSQL_ROOT_PASSWORD=mypassword -e MYSQL_DATABASE=mydb -e MYSQL_USER=myuser -e MYSQL_PASSWORD=mypassword -p 3306:3306 -d mysql:latest +``` + +Connection string: +``` +Server=localhost;Port=3306;Database=mydb;User=myuser;Password=mypassword +``` + +#### SQL Server + +```sh +docker run --name my-mssql -e 'ACCEPT_EULA=Y' -e 'SA_PASSWORD=MyStrong!Passw0rd' -p 1433:1433 -d mcr.microsoft.com/mssql/server:2022-latest +``` + +Connection string: +``` +Server=localhost,1433;Database=master;User Id=sa;Password=MyStrong!Passw0rd;TrustServerCertificate=True +``` + +You can adjust usernames, passwords, and database names as needed. \ No newline at end of file diff --git a/OpenIddict/OpenIddictIdP/Startup.cs b/OpenIddict/OpenIddictIdP/Startup.cs index 8bcf342..89b433c 100644 --- a/OpenIddict/OpenIddictIdP/Startup.cs +++ b/OpenIddict/OpenIddictIdP/Startup.cs @@ -1,5 +1,6 @@ +using System; +using System.Diagnostics; using Rsk.Saml.OpenIddict.Quartz.Configuration.DependencyInjection; -using IdentityModel; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Identity; @@ -29,11 +30,28 @@ public void ConfigureServices(IServiceCollection services) { services.AddControllersWithViews(); services.AddRazorPages(); - var defaultConnectionString = Configuration.GetConnectionString("DefaultConnection"); + var dbProvider = Configuration.GetValue("DbProvider"); + string connectionString = Configuration.GetConnectionString("DefaultConnection"); + services.AddDbContext(options => { - //Configure the database provider to use. - options.UseSqlServer(defaultConnectionString); + switch (dbProvider) + { + case DbProvider.SqlServer: + options.UseSqlServer(connectionString); + break; + case DbProvider.MySql: + options.UseMySql(connectionString, ServerVersion.AutoDetect(connectionString)); + break; + case DbProvider.PostgreSql: + options.UseNpgsql(connectionString); + break; + case DbProvider.Sqlite: + options.UseSqlite(connectionString); + break; + default: + throw new ArgumentOutOfRangeException($"{dbProvider} is not a supported database provider."); + } // Register the entity sets needed by OpenIddict. // Note: use the generic overload if you need @@ -56,7 +74,7 @@ public void ConfigureServices(IServiceCollection services) options.ClaimsIdentity.RoleClaimType = JwtClaimTypes.Role; options.ClaimsIdentity.EmailClaimType = JwtClaimTypes.Email; }); - + // OpenIddict offers native integration with Quartz.NET to perform scheduled tasks // (like pruning orphaned authorizations/tokens from the database) at regular intervals. services.AddQuartz(options => @@ -76,7 +94,7 @@ public void ConfigureServices(IServiceCollection services) // Configure OpenIddict to use the Entity Framework Core stores and models. // Note: call ReplaceDefaultEntities() to replace the default OpenIddict entities. options.UseEntityFrameworkCore() - .UseDbContext(); + .UseDbContext(); // Enable Quartz.NET integration. options.UseQuartz(); @@ -92,9 +110,9 @@ public void ConfigureServices(IServiceCollection services) // Enable the authorization, logout, token and userinfo endpoints. options.SetAuthorizationEndpointUris("connect/authorize") - .SetLogoutEndpointUris("connect/logout") - .SetTokenEndpointUris("connect/token") - .SetUserinfoEndpointUris("connect/userinfo"); + .SetEndSessionEndpointUris("connect/logout") + .SetTokenEndpointUris("connect/token") + .SetUserInfoEndpointUris("connect/userinfo"); // Mark the "email", "profile" and "roles" scopes as supported scopes. options.RegisterScopes(Scopes.Email, Scopes.Profile, Scopes.Roles); @@ -105,51 +123,66 @@ public void ConfigureServices(IServiceCollection services) // Register the signing and encryption credentials. options.AddDevelopmentEncryptionCertificate() - .AddDevelopmentSigningCertificate(); + .AddDevelopmentSigningCertificate(); // Register the ASP.NET Core host and configure the ASP.NET Core-specific options. options.UseAspNetCore() .EnableAuthorizationEndpointPassthrough() - .EnableLogoutEndpointPassthrough() - .EnableTokenEndpointPassthrough() - .EnableUserinfoEndpointPassthrough() - .EnableStatusCodePagesIntegration(); + .EnableEndSessionEndpointPassthrough() + .EnableTokenEndpointPassthrough() + .EnableUserInfoEndpointPassthrough() + .EnableStatusCodePagesIntegration(); options.AddSamlPlugin(builder => { //use quartz to prune old SAML messages every 14 days. builder.PruneSamlMessages(); - + //Already added the DbContext above builder.UseSamlEntityFrameworkCore() - .AddSamlMessageDbContext(optionsBuilder => + .AddSamlDbContexts(optionsBuilder => { - //Configure the database provider to use. - optionsBuilder.UseSqlServer(defaultConnectionString, x =>x.MigrationsAssembly(typeof(Startup).Assembly.FullName)); - }) - .AddSamlConfigurationDbContext(optionsBuilder => - { - //Configure the database provider to use. - optionsBuilder.UseSqlServer(defaultConnectionString, - x => x.MigrationsAssembly(typeof(Startup).Assembly.FullName)); + switch (dbProvider) + { + case DbProvider.SqlServer: + optionsBuilder.UseSqlServer(connectionString, + x => x.MigrationsAssembly(typeof(Startup).Assembly.FullName)); + break; + case DbProvider.MySql: + optionsBuilder.UseMySql(connectionString, + ServerVersion.AutoDetect(connectionString), + x => x.MigrationsAssembly(typeof(Startup).Assembly.FullName)); + break; + case DbProvider.PostgreSql: + optionsBuilder.UseNpgsql(connectionString, + x => x.MigrationsAssembly(typeof(Startup).Assembly.FullName)); + break; + case DbProvider.Sqlite: + optionsBuilder.UseSqlite(connectionString, + x => x.MigrationsAssembly(typeof(Startup).Assembly.FullName)); + break; + default: + throw new ArgumentOutOfRangeException( + $"{dbProvider} is not a supported database provider."); + } }); + builder.ConfigureSamlOpenIddictServerOptions(serverOptions => + { + serverOptions.HostOptions = new SamlHostUserInteractionOptions() { - serverOptions.HostOptions = new SamlHostUserInteractionOptions() - { - LoginUrl = "/Identity/Account/Login", - LogoutUrl = "/connect/logout", - }; - - serverOptions.IdpOptions = new SamlIdpOptions() - { - Licensee = LicenseKey.Licensee, - LicenseKey =LicenseKey.Key, - UseIFramesForSlo = false + LoginUrl = "/Identity/Account/Login", + LogoutUrl = "/connect/logout", + }; - }; - }); + serverOptions.IdpOptions = new SamlIdpOptions() + { + Licensee = LicenseKey.Licensee, + LicenseKey = LicenseKey.Key, + UseIFramesForSlo = false + }; + }); builder.AddSamlAspIdentity(); }); @@ -170,7 +203,7 @@ public void ConfigureServices(IServiceCollection services) services.AddHostedService(); } - public void Configure(IApplicationBuilder app, IWebHostEnvironment env) + public static void Configure(IApplicationBuilder app, IWebHostEnvironment env) { if (env.IsDevelopment()) { @@ -185,6 +218,7 @@ public void Configure(IApplicationBuilder app, IWebHostEnvironment env) // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts. //app.UseHsts(); } + app.UseHttpsRedirection(); app.UseStaticFiles(); @@ -202,4 +236,4 @@ public void Configure(IApplicationBuilder app, IWebHostEnvironment env) endpoints.MapRazorPages(); }); } -} +} \ No newline at end of file diff --git a/OpenIddict/OpenIddictIdP/Worker.cs b/OpenIddict/OpenIddictIdP/Worker.cs index e59c4f1..9d40aec 100644 --- a/OpenIddict/OpenIddictIdP/Worker.cs +++ b/OpenIddict/OpenIddictIdP/Worker.cs @@ -1,5 +1,4 @@ using Microsoft.AspNetCore.Identity; -using Microsoft.Data.SqlClient; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; @@ -13,55 +12,60 @@ using Rsk.Saml.OpenIddict.EntityFrameworkCore.DbContexts; using openiddictidp.Data; using System; -using System.Collections.Generic; using System.Data; using System.Data.Common; -using System.Linq; using System.Net.Http; using System.Security.Cryptography.X509Certificates; using System.Text.Json; using System.Threading; using System.Threading.Tasks; +using Microsoft.Data.Sqlite; using static OpenIddict.Abstractions.OpenIddictConstants; using ServiceProvider = Rsk.Saml.Models.ServiceProvider; +using Microsoft.Data.SqlClient; +using MySqlConnector; +using Npgsql; namespace openiddictidp; -public class Worker : IHostedService +public class Worker(IServiceProvider serviceProvider, IConfiguration configuration) : IHostedService { - private readonly IServiceProvider _serviceProvider; - - public Worker(IServiceProvider serviceProvider) - => _serviceProvider = serviceProvider; + private DbProvider dbProvider; public async Task StartAsync(CancellationToken cancellationToken) { - await using var scope = _serviceProvider.CreateAsyncScope(); + dbProvider = configuration.GetValue("DbProvider"); + + await using AsyncServiceScope scope = serviceProvider.CreateAsyncScope(); await EnsureAllDatabasesAreCreated(scope); await CreateMvcClientIfNotExists(scope); await CreateSamlClientIfNotExists(scope); await CreateFakeUserBobIfNotExists(scope); await CreateEmailScopeIfNotExists(scope); - await CreateSamlServiceProviderWithArtifactBindingIfNotExists(scope, "https://localhost:5001/saml/artifact", x => - { - x.EntityId = "https://localhost:5001/saml/artifact"; - x.EncryptAssertions = false; - x.AssertionConsumerServices.Add(new Service(SamlConstants.BindingTypes.HttpArtifact, - "https://localhost:5001/signin-saml-openIddict-artifact")); - x.SingleLogoutServices.Add(new Service(SamlConstants.BindingTypes.HttpRedirect, - "https://localhost:5001/signout-saml-artifasct")); - x.ArtifactResolutionServices.Add(new Service(SamlConstants.BindingTypes.Soap, "https://localhost:5001/ars-saml")); - x.SigningCertificates = new List { new("Resources/testclient.cer") }; - x.EncryptionCertificate = new X509Certificate2("Resources/idsrv3test.cer"); - }); + await CreateServiceProviderIfNotExists(scope, "https://localhost:5001/saml/artifact", + x => + { + x.EntityId = "https://localhost:5001/saml/artifact"; + x.EncryptAssertions = false; + x.AssertionConsumerServices.Add(new Service(SamlConstants.BindingTypes.HttpArtifact, + "https://localhost:5001/signin-saml-openIddict-artifact")); + x.SingleLogoutServices.Add(new Service(SamlConstants.BindingTypes.HttpRedirect, + "https://localhost:5001/signout-saml-artifasct")); + x.ArtifactResolutionServices.Add(new Service(SamlConstants.BindingTypes.Soap, + "https://localhost:5001/ars-saml")); + x.SigningCertificates = [new X509Certificate2("Resources/testclient.cer")]; + x.EncryptionCertificate = new X509Certificate2("Resources/idsrv3test.cer"); + }); await CreateServiceProviderIfNotExists(scope, "https://localhost:5001/saml", x => { x.EntityId = "https://localhost:5001/saml"; x.EncryptAssertions = false; x.AllowIdpInitiatedSso = true; - x.AssertionConsumerServices.Add(new Service(SamlConstants.BindingTypes.HttpPost, "https://localhost:5001/signin-saml-openIddict")); - x.SingleLogoutServices.Add(new Service(SamlConstants.BindingTypes.HttpRedirect, "https://localhost:5001/signout-saml")); - x.SigningCertificates = new List { new("Resources/testclient.cer") }; + x.AssertionConsumerServices.Add(new Service(SamlConstants.BindingTypes.HttpPost, + "https://localhost:5001/signin-saml-openIddict")); + x.SingleLogoutServices.Add(new Service(SamlConstants.BindingTypes.HttpRedirect, + "https://localhost:5001/signout-saml")); + x.SigningCertificates = [new X509Certificate2("Resources/testclient.cer")]; x.EncryptionCertificate = new X509Certificate2("Resources/idsrv3test.cer"); }); await SaveAllChanges(scope); @@ -71,136 +75,126 @@ await CreateServiceProviderIfNotExists(scope, "https://localhost:5001/saml", x = private async Task EnsureAllDatabasesAreCreated(IServiceScope scope) { - //Create the database backed by the ApplicationDbContext. + // Apply migrations for the ApplicationDbContext. var applicationDbContext = scope.ServiceProvider.GetRequiredService(); - await applicationDbContext.Database.EnsureCreatedAsync(); + await applicationDbContext.Database.MigrateAsync(); - //Create the database backed by the OpenIddictSamlMessageDbContext. + // Apply migrations for the OpenIddictSamlMessageDbContext. var samlOpenIddictMessageContext = scope.ServiceProvider.GetRequiredService(); - await samlOpenIddictMessageContext.Database.EnsureCreatedAsync(); + await samlOpenIddictMessageContext.Database.MigrateAsync(); - //Create the database backed by the SamlConfigurationContext. + // Apply migrations for the SamlConfigurationDbContext. var samlConfigurationContext = scope.ServiceProvider.GetRequiredService(); - await samlConfigurationContext.Database.EnsureCreatedAsync(); + await samlConfigurationContext.Database.MigrateAsync(); + //Create the database used by the quartz scheduler. - await CreateTheQuartzDatabase(scope); + await CreateQuartzDatabase(scope); } - private async Task CreateTheQuartzDatabase(IServiceScope scope) + private async Task CreateQuartzDatabase(IServiceScope scope) { - var quartzDatabaseDownloadUrlTemplate ="https://github.com/quartznet/quartznet/blob/main/database/tables/tables_{0}.sql"; - string quartzDatabaseDownloadUrl = null; - quartzDatabaseDownloadUrl = String.Format(quartzDatabaseDownloadUrlTemplate, "sqlServer"); - - var quartzDatabaseSql =await DownloadQuartzDatabaseSql(scope, quartzDatabaseDownloadUrl); - + const string quartzDatabaseDownloadUrlTemplate = "https://raw.githubusercontent.com/quartznet/quartznet/refs/heads/main/database/tables/tables_{0}.sql"; + string quartzDatabaseDownloadUrl = string.Format(quartzDatabaseDownloadUrlTemplate, GetDbNameForQuartzTablesSqlUrl()); + string quartzDatabaseSql = await DownloadQuartzDatabaseSql(scope, quartzDatabaseDownloadUrl); await InitializeQuartzDatabase(scope, quartzDatabaseSql); } + private string GetDbNameForQuartzTablesSqlUrl() => dbProvider switch + { + DbProvider.SqlServer => "sqlServer", + DbProvider.MySql => "mysql_innodb", + DbProvider.PostgreSql => "postgres", + DbProvider.Sqlite => "sqlite", + _ => throw new NotSupportedException($"The database provider {dbProvider} is not supported.") + }; + private static async Task DownloadQuartzDatabaseSql(IServiceScope scope, string quartzDatabaseDownloadUrl) { var clientFactory = scope.ServiceProvider.GetRequiredService(); - using var client = clientFactory.CreateClient(); + using HttpClient client = clientFactory.CreateClient(); return await client.GetStringAsync(quartzDatabaseDownloadUrl); } private async Task InitializeQuartzDatabase(IServiceScope scope, string quartzDatabaseSql) { - var quartzDatabaseCommands =GetQuartzDatabaseCommands(quartzDatabaseSql); - var connection =GetDbConnection(scope); - var command = connection.CreateCommand(); - command.CommandType= CommandType.Text; + using DbConnection connection = GetDbConnection(scope); + using DbCommand command = connection.CreateCommand(); + command.CommandType = CommandType.Text; await connection.OpenAsync(); - foreach (var quartzDatabaseCommand in quartzDatabaseCommands) - { - command.CommandText = quartzDatabaseCommand; - await command.ExecuteNonQueryAsync(); - } - - await connection.DisposeAsync(); - } - - private static IList GetQuartzDatabaseCommands(string quartzDatabaseSql) - { - var databaseDelimiter = GetDatabaseDelimiter(); - return quartzDatabaseSql.Split(databaseDelimiter).Select(x => x.Trim()).ToList(); - } - - private static string GetDatabaseDelimiter() - { - return "GO"; + command.CommandText = quartzDatabaseSql; + await command.ExecuteNonQueryAsync(); } - private static DbConnection GetDbConnection(IServiceScope scope) + private DbConnection GetDbConnection(IServiceScope scope) { var configuration = scope.ServiceProvider.GetRequiredService(); - var connectionString = configuration.GetConnectionString("DefaultConnection"); - DbConnection connection = null; - connection = new SqlConnection(connectionString); - return connection; - } - - private Task CreateMvcClientIfNotExists(IServiceScope scope) - { - return CreateClientIfNotExists(scope, "mvc", ocd => - { - ocd.ClientId = "mvc"; - ocd.ClientSecret = "901564A5-E7FE-42CB-B10D-61EF6A8F3654"; - ocd.ConsentType = ConsentTypes.Explicit; - ocd.DisplayName = "MVC client application"; - ocd.RedirectUris.Add(new Uri("https://localhost:44338/callback/login/local")); - ocd.PostLogoutRedirectUris.Add(new Uri("https://localhost:44338/callback/logout/local")); - - ocd.Permissions.UnionWith(new[] - { - Permissions.Endpoints.Authorization, - Permissions.Endpoints.Logout, - Permissions.Endpoints.Token, - Permissions.GrantTypes.AuthorizationCode, - Permissions.ResponseTypes.Code, - Permissions.Scopes.Email, - Permissions.Scopes.Profile, - Permissions.Scopes.Roles}); - ocd.Requirements.Add(Requirements.Features.ProofKeyForCodeExchange); - }); - } - - private Task CreateSamlClientIfNotExists(AsyncServiceScope scope) - { - return CreateClientIfNotExists(scope, "https://localhost:5001/saml", x => + string connectionString = configuration.GetConnectionString("DefaultConnection"); + return dbProvider switch { - x.ClientId = "https://localhost:5001/saml"; - x.Permissions.UnionWith(new[] { Permissions.Scopes.Email }); - }); - } - - private async Task CreateClientIfNotExists(IServiceScope scope, string clientId, Action descriptorCoonfiguration) + DbProvider.SqlServer => new SqlConnection(connectionString), + DbProvider.MySql => new MySqlConnection(connectionString), + DbProvider.PostgreSql => new NpgsqlConnection(connectionString), + DbProvider.Sqlite => new SqliteConnection(connectionString), + _ => throw new NotSupportedException($"The database provider {dbProvider} is not supported.") + }; + } + + private static Task CreateMvcClientIfNotExists(IServiceScope scope) => CreateClientIfNotExists(scope, "mvc", ocd => + { + ocd.ClientId = "mvc"; + ocd.ClientSecret = "901564A5-E7FE-42CB-B10D-61EF6A8F3654"; + ocd.ConsentType = ConsentTypes.Explicit; + ocd.DisplayName = "MVC client application"; + ocd.RedirectUris.Add(new Uri("https://localhost:44338/callback/login/local")); + ocd.PostLogoutRedirectUris.Add(new Uri("https://localhost:44338/callback/logout/local")); + + ocd.Permissions.UnionWith([ + Permissions.Endpoints.Authorization, + Permissions.Endpoints.EndSession, + Permissions.Endpoints.Token, + Permissions.GrantTypes.AuthorizationCode, + Permissions.ResponseTypes.Code, + Permissions.Scopes.Email, + Permissions.Scopes.Profile, + Permissions.Scopes.Roles + ]); + ocd.Requirements.Add(Requirements.Features.ProofKeyForCodeExchange); + }); + + private static Task CreateSamlClientIfNotExists(AsyncServiceScope scope) => CreateClientIfNotExists(scope, "https://localhost:5001/saml", x => + { + x.ClientId = "https://localhost:5001/saml"; + x.Permissions.UnionWith([Permissions.Scopes.Email]); + }); + + private static async Task CreateClientIfNotExists(IServiceScope scope, string clientId, + Action descriptorCoonfiguration) { var manager = scope.ServiceProvider.GetRequiredService(); if (await manager.FindByClientIdAsync(clientId) == null) { - var newClientDescriptor = CreateAndConfigureOpenIddictApplicationDescriptor(descriptorCoonfiguration); + OpenIddictApplicationDescriptor newClientDescriptor = + CreateAndConfigureOpenIddictApplicationDescriptor(descriptorCoonfiguration); await manager.CreateAsync(newClientDescriptor); } } - private OpenIddictApplicationDescriptor CreateAndConfigureOpenIddictApplicationDescriptor(Action configuration) + private static OpenIddictApplicationDescriptor CreateAndConfigureOpenIddictApplicationDescriptor( + Action configuration) { var od = new OpenIddictApplicationDescriptor(); configuration(od); return od; } - private Task CreateFakeUserBobIfNotExists(IServiceScope scope) + private static Task CreateFakeUserBobIfNotExists(IServiceScope scope) => CreateUserIfNotExists(scope, "bob@test.fake", user => { - return CreateUserIfNotExists(scope, "bob@test.fake", user => - { - user.UserName = "bob@test.fake"; - user.Email = "bob@test.fake"; - }, "Password123!"); - } + user.UserName = "bob@test.fake"; + user.Email = "bob@test.fake"; + }, "Password123!"); - private async Task CreateUserIfNotExists(IServiceScope scope, string userName, Action userConfiguration, string userPassword) + private static async Task CreateUserIfNotExists(IServiceScope scope, string userName, + Action userConfiguration, string userPassword) { var userManager = scope.ServiceProvider.GetRequiredService>(); if (await userManager.FindByNameAsync(userName) == null) @@ -211,12 +205,12 @@ private async Task CreateUserIfNotExists(IServiceScope scope, string userName, A } } - private Task CreateEmailScopeIfNotExists(IServiceScope scope) + private static Task CreateEmailScopeIfNotExists(IServiceScope scope) { var claims = new[] { "email" }; - var serializedClaims = JsonSerializer.Serialize(claims); - using var jsonDocument = JsonDocument.Parse(serializedClaims); - var claimsElemennt = jsonDocument.RootElement.Clone(); + string serializedClaims = JsonSerializer.Serialize(claims); + using JsonDocument jsonDocument = JsonDocument.Parse(serializedClaims); + JsonElement claimsElemennt = jsonDocument.RootElement.Clone(); return CreateScopeIfNotExists(scope, "email", x => { x.Name = "email"; @@ -225,7 +219,8 @@ private Task CreateEmailScopeIfNotExists(IServiceScope scope) }); } - private static async Task CreateScopeIfNotExists(IServiceScope scope, string scopeName, Action scopeConfiguration) + private static async Task CreateScopeIfNotExists(IServiceScope scope, string scopeName, + Action scopeConfiguration) { var scopeManager = scope.ServiceProvider.GetRequiredService(); if (await scopeManager.FindByNameAsync(scopeName) == null) @@ -237,12 +232,7 @@ private static async Task CreateScopeIfNotExists(IServiceScope scope, string sco } } - private Task CreateSamlServiceProviderWithArtifactBindingIfNotExists(IServiceScope scope, string entityId, Action serviceProviderConfiguration) - { - return CreateServiceProviderIfNotExists(scope, entityId, serviceProviderConfiguration); - } - - private async Task CreateServiceProviderIfNotExists(IServiceScope scope, string entityId, + private static async Task CreateServiceProviderIfNotExists(IServiceScope scope, string entityId, Action serviceProviderConfiguration) { var samlConfigurationDbContext = scope.ServiceProvider.GetRequiredService(); @@ -255,11 +245,11 @@ private async Task CreateServiceProviderIfNotExists(IServiceScope scope, string } } - private async Task SaveAllChanges(IServiceScope scope) + private static async Task SaveAllChanges(IServiceScope scope) { var applicationDbContext = scope.ServiceProvider.GetRequiredService(); await applicationDbContext.SaveChangesAsync(); var samlConfigurationDbContext = scope.ServiceProvider.GetRequiredService(); await samlConfigurationDbContext.SaveChangesAsync(); } -} \ No newline at end of file +} diff --git a/OpenIddict/OpenIddictIdP/appsettings.json b/OpenIddict/OpenIddictIdP/appsettings.json index 3c954fd..2e2feed 100644 --- a/OpenIddict/OpenIddictIdP/appsettings.json +++ b/OpenIddict/OpenIddictIdP/appsettings.json @@ -1,6 +1,7 @@ { "ConnectionStrings": { - "DefaultConnection": "Server=(localdb)\\mssqllocaldb;Database=openiddict-velusia-server;Trusted_Connection=True;MultipleActiveResultSets=true" + "DefaultConnection": "Host=localhost;Port=5432;Database=mydb;Username=myuser;Password=mypassword" + //"Data Source=openiddict-identity.db;" }, "Logging": { "LogLevel": { @@ -9,5 +10,6 @@ "Microsoft.Hosting.Lifetime": "Information" } }, - "AllowedHosts": "*" + "AllowedHosts": "*", + "DbProvider": "PostgreSql" // Options: "PostgreSql", "MySql", "SqlServer", "Sqlite" } \ No newline at end of file diff --git a/README.md b/README.md index 1798291..dc1ad99 100644 --- a/README.md +++ b/README.md @@ -1,23 +1,19 @@ # Sample projects implementing Rsk SAML component -SAML2P service provider and identity provider implementations. We support various IdentityServer implementations, including IdentityServer4, Duende IdentityServer and OpenIddict. +SAML2P service provider and identity provider implementations. We support various IdentityServer implementations, including Duende IdentityServer and OpenIddict. -The SAML2P component is available from [www.identityserver.com/products/saml2p](https://www.identityserver.com/products/saml2p). + The SAML2P component is available from [www.identityserver.com/products/saml2p](https://www.identityserver.com/products/saml2p). -The [master](https://github.com/RockSolidKnowledge/Samples.IdentityServer4.Saml2pIntegration/tree/master) branch currently uses IdentityServer4 v4 and Duende IdentityServer. Check out [identityserver4-v3](https://github.com/RockSolidKnowledge/Samples.IdentityServer4.Saml2pIntegration/tree/identityserver4-v3) for IdentityServer4 v3 samples. + +The [master](https://github.com/RockSolidKnowledge/Samples.IdentityServer4.Saml2pIntegration/tree/master) branch currently uses version 10.0 of the Saml component along with Duende IdentityServer version 7.1 and OpenIddict version 6.0. ## Projects - **spWithIdpInitiated:** an ASP.NET Core website that can accept unsolicited SAML assertions sent via IdP-Initiated SSO - **spWithMultipleIdps:** an ASP.NET Core website that can authenticate a user using two different SAML Identity Providers -- **IdentityServer4** - - **idp:** an IdentityServer4 implementation configured to act as a SAML Identity Provider with Service Provider configuration loaded from memory - - **idpWithEf:** an IdentityServer4 implementation configured to act as a SAML Identity Provider with Service Provider configuration loaded from a database - - **idpWithIdpInitiated:** an IdentityServer4 implementation configured to send unsolicited SAML assertions using IdP-Initiated SSO - - **sp:** an IdentityServer4 implementation configured to act as both a SAML Identity Provider and a SAML Service Provider - **DuendeIdentityServer** - - **DuendeIdP:** a Duende.IdentityServer implementation configured to act as a SAML Identity Provider with Service Provider configuration loaded from memory. This uses the Duende Automatic Key Management feature for signing key + - **DuendeIdP:** a Duende.IdentityServer implementation configured to act as a SAML Identity Provider with Service Provider configuration loaded from memory. This uses the Duende Automatic Key Management feature for signing key material. - **DuendeDynamicProviders:** A Duende.IdentityServer implementation acting as a SAML Service Provider with in-memory dynamic identity providers - **OpenIddictIdP:** an OpenIddict implementation configured to act as an SAML Identity Provider with Service Provider configuration loaded from an SQL Server database using EntityFrameworkCore. @@ -29,5 +25,17 @@ The [master](https://github.com/RockSolidKnowledge/Samples.IdentityServer4.Saml2 - [Documentation](https://www.identityserver.com/documentation/saml2p/) ## License Keys +If you are using IdentityServer and would like a demo license, please sign up on our [products page]( https://www.identityserver.com/products/saml2p). Alternative for a demo license using OpenIddict use [this](https://www.openiddictcomponents.com/products/saml2p) link. You can also reach out to . + + +## Launch urls +The launch urls for the sample projects are as follows: -For a demo license, please sign up on our [products page](https://www.identityserver.com/products/saml2p), or reach out to . +|Project|Launch Url| +|---|---| +|duende.idp|https://localhost:5003| +|OpenIddict.Idp|https://localhost:55031| +|Duende Dynamic providers|https://localhost:5004| +|SPWithIdpInitiated|https://localhost:5001| +|SpWithMultipleIds|https://localhost:5002| +|SpWithSingleIdp|https://localhost:5002| \ No newline at end of file diff --git a/saml.slnf b/saml.slnf new file mode 100644 index 0000000..4d196e4 --- /dev/null +++ b/saml.slnf @@ -0,0 +1,17 @@ +{ + "solution": { + "path": "Saml.sln", + "projects": [ + "DuendeIdentityServer\\DuendeDynamicProviders\\DuendeDynamicProviders.csproj", + "DuendeIdentityServer\\DuendeIdP\\DuendeIdP.csproj", + "DuendeIdentityServer\\SLO\\SamlOidcSLO\\IdentityServer\\IdentityServer.csproj", + "DuendeIdentityServer\\SLO\\SamlOidcSLO\\WebClient.OIDC\\WebClient.OIDC.csproj", + "DuendeIdentityServer\\SLO\\SamlOidcSLO\\WebClient.SAML.1\\WebClient.SAML.1.csproj", + "DuendeIdentityServer\\SLO\\SamlOidcSLO\\WebClient.SAML.2\\WebClient.SAML.2.csproj", + "OpenIddict\\OpenIddictIdP\\OpenIddictIdP.csproj", + "spWithIdpInitiated\\spWithIdpInitiated.csproj", + "spWithMultipleIdps\\spWithMultipleIdps.csproj", + "spWithSingleIdp\\spWithSingleIdp.csproj" + ] + } +} \ No newline at end of file diff --git a/spWithIdpInitiated/spWithIdpInitiated.csproj b/spWithIdpInitiated/spWithIdpInitiated.csproj index e56abed..ba34f12 100644 --- a/spWithIdpInitiated/spWithIdpInitiated.csproj +++ b/spWithIdpInitiated/spWithIdpInitiated.csproj @@ -6,7 +6,7 @@ - + diff --git a/spWithMultipleIdps/spWithMultipleIdps.csproj b/spWithMultipleIdps/spWithMultipleIdps.csproj index 3cbcf4c..6aa51b8 100644 --- a/spWithMultipleIdps/spWithMultipleIdps.csproj +++ b/spWithMultipleIdps/spWithMultipleIdps.csproj @@ -6,7 +6,7 @@ - + diff --git a/spWithSingleIdp/spWithSingleIdp.csproj b/spWithSingleIdp/spWithSingleIdp.csproj index e4797b7..c60b5b2 100644 --- a/spWithSingleIdp/spWithSingleIdp.csproj +++ b/spWithSingleIdp/spWithSingleIdp.csproj @@ -8,6 +8,6 @@ - + \ No newline at end of file