diff --git a/.gitignore b/.gitignore
index 18539b1..2409aa6 100644
--- a/.gitignore
+++ b/.gitignore
@@ -8,3 +8,4 @@
/examplesUsingCertificateAuthentication/AspNetCoreChained/_chainedServerLogs.txt
/examplesUsingCertificateAuthentication/AspNetCoreChained/_clientLogs.txt
/examplesUsingCertificateAuthentication/AzureCertAuth/certauth.txt
+**/_logs-*
diff --git a/examplesUsingCertificateAuthentication/AzureCertAuth/AzureCertAuth/AzureCertAuth.csproj b/examplesUsingCertificateAuthentication/AzureCertAuth/AzureCertAuth/AzureCertAuth.csproj
index 5b5ea5d..92b36df 100644
--- a/examplesUsingCertificateAuthentication/AzureCertAuth/AzureCertAuth/AzureCertAuth.csproj
+++ b/examplesUsingCertificateAuthentication/AzureCertAuth/AzureCertAuth/AzureCertAuth.csproj
@@ -7,20 +7,15 @@
-
-
-
-
-
-
-
-
-
+
+
+
-
-
- PreserveNewest
-
+
+
+
+
+
diff --git a/examplesUsingCertificateAuthentication/AzureCertAuth/AzureCertAuth/Program.cs b/examplesUsingCertificateAuthentication/AzureCertAuth/AzureCertAuth/Program.cs
index 40c71ac..c0e920c 100644
--- a/examplesUsingCertificateAuthentication/AzureCertAuth/AzureCertAuth/Program.cs
+++ b/examplesUsingCertificateAuthentication/AzureCertAuth/AzureCertAuth/Program.cs
@@ -1,54 +1,34 @@
-using Serilog;
-using Serilog.Events;
-using Serilog.Sinks.SystemConsole.Themes;
-
-namespace AzureCertAuth;
-
-public class Program
-{
- public static int Main(string[] args)
- {
- Log.Logger = new LoggerConfiguration()
- .MinimumLevel.Debug()
- .MinimumLevel.Override("Microsoft", LogEventLevel.Debug)
- .Enrich.FromLogContext()
- .CreateLogger();
-
- try
- {
- Log.Information("Starting web host");
- CreateHostBuilder(args).Build().Run();
- return 0;
- }
- catch (Exception ex)
- {
- Log.Fatal(ex, "Host terminated unexpectedly");
- return 1;
- }
- finally
- {
- Log.CloseAndFlush();
- }
- }
-
- public static IHostBuilder CreateHostBuilder(string[] args) =>
- Host.CreateDefaultBuilder(args)
- .UseSerilog((hostingContext, loggerConfiguration) => loggerConfiguration
- .ReadFrom.Configuration(hostingContext.Configuration)
- .MinimumLevel.Override("Microsoft", LogEventLevel.Verbose)
- .MinimumLevel.Verbose()
- .Enrich.FromLogContext()
- .WriteTo.File(
- //$@"../certauth.txt",
- $@"D:\home\LogFiles\Application\{Environment.UserDomainName}.txt",
- fileSizeLimitBytes: 1_000_000,
- rollOnFileSizeLimit: true,
- shared: true,
- flushToDiskInterval: TimeSpan.FromSeconds(1))
- .WriteTo.Console(theme: AnsiConsoleTheme.Code)
- )
- .ConfigureWebHostDefaults(webBuilder =>
- {
- webBuilder.UseStartup();
- });
-}
+using AzureCertAuth;
+using Serilog;
+
+Log.Logger = new LoggerConfiguration()
+ .WriteTo.Console()
+ .CreateBootstrapLogger();
+
+Log.Information("Starting up OpeniddictServer");
+
+try
+{
+ var builder = WebApplication.CreateBuilder(args);
+
+ builder.Host.UseSerilog((context, loggerConfiguration) => loggerConfiguration
+ .WriteTo.Console(outputTemplate: "[{Timestamp:HH:mm:ss} {Level}] {SourceContext}{NewLine}{Message:lj}{NewLine}{Exception}{NewLine}")
+ .WriteTo.File("../_logs-DownstreamApiCertAuth.txt")
+ .Enrich.FromLogContext()
+ .ReadFrom.Configuration(context.Configuration));
+
+ var app = builder
+ .ConfigureServices()
+ .ConfigurePipeline();
+
+ app.Run();
+}
+catch (Exception ex) when (ex.GetType().Name is not "StopTheHostException" && ex.GetType().Name is not "HostAbortedException")
+{
+ Log.Fatal(ex, "Unhandled exception");
+}
+finally
+{
+ Log.Information("Shut down complete");
+ Log.CloseAndFlush();
+}
\ No newline at end of file
diff --git a/examplesUsingCertificateAuthentication/AzureCertAuth/AzureCertAuth/Properties/launchSettings.json b/examplesUsingCertificateAuthentication/AzureCertAuth/AzureCertAuth/Properties/launchSettings.json
index 1483d57..79833e0 100644
--- a/examplesUsingCertificateAuthentication/AzureCertAuth/AzureCertAuth/Properties/launchSettings.json
+++ b/examplesUsingCertificateAuthentication/AzureCertAuth/AzureCertAuth/Properties/launchSettings.json
@@ -1,27 +1,11 @@
{
"$schema": "http://json.schemastore.org/launchsettings.json",
- "iisSettings": {
- "windowsAuthentication": false,
- "anonymousAuthentication": true,
- "iisExpress": {
- "applicationUrl": "https://localhost:44361",
- "sslPort": 44361
- }
- },
"profiles": {
- "IIS Express": {
- "commandName": "IISExpress",
- "launchBrowser": true,
- "launchUrl": "weatherforecast",
- "environmentVariables": {
- "ASPNETCORE_ENVIRONMENT": "Development"
- }
- },
"AzureCertAuth": {
"commandName": "Project",
"launchBrowser": true,
"launchUrl": "weatherforecast",
- "applicationUrl": "https://localhost:5001;http://localhost:5000",
+ "applicationUrl": "https://localhost:5009",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
diff --git a/examplesUsingCertificateAuthentication/AzureCertAuth/AzureCertAuth/Startup.cs b/examplesUsingCertificateAuthentication/AzureCertAuth/AzureCertAuth/StartupExtensions.cs
similarity index 60%
rename from examplesUsingCertificateAuthentication/AzureCertAuth/AzureCertAuth/Startup.cs
rename to examplesUsingCertificateAuthentication/AzureCertAuth/AzureCertAuth/StartupExtensions.cs
index 21f19b0..ba666fd 100644
--- a/examplesUsingCertificateAuthentication/AzureCertAuth/AzureCertAuth/Startup.cs
+++ b/examplesUsingCertificateAuthentication/AzureCertAuth/AzureCertAuth/StartupExtensions.cs
@@ -1,103 +1,130 @@
-using System.Security.Claims;
-using System.Security.Cryptography.X509Certificates;
-using Microsoft.AspNetCore.Authentication.Certificate;
-
-namespace AzureCertAuth;
-
-public class Startup
-{
- public Startup(IConfiguration configuration)
- {
- Configuration = configuration;
- }
-
- public IConfiguration Configuration { get; }
-
- public void ConfigureServices(IServiceCollection services)
- {
- services.AddSingleton();
-
- services.AddCertificateForwarding(options =>
- {
- options.CertificateHeader = "X-ARR-ClientCert";
- options.HeaderConverter = (headerValue) =>
- {
-
- X509Certificate2? clientCertificate = null;
- if (!string.IsNullOrWhiteSpace(headerValue))
- {
- byte[] bytes = Convert.FromBase64String(headerValue);
- clientCertificate = new X509Certificate2(bytes);
- }
-
- return clientCertificate;
- };
- });
-
- services.AddAuthentication(CertificateAuthenticationDefaults.AuthenticationScheme)
- .AddCertificate(options => // code from ASP.NET Core sample
- {
- // https://docs.microsoft.com/en-us/aspnet/core/security/authentication/certauth
- options.AllowedCertificateTypes = CertificateTypes.SelfSigned;
-
- // Default values
- //options.AllowedCertificateTypes = CertificateTypes.Chained;
- //options.RevocationFlag = X509RevocationFlag.ExcludeRoot;
- //options.RevocationMode = X509RevocationMode.Online;
- //options.ValidateCertificateUse = true;
- //options.ValidateValidityPeriod = true;
-
- options.Events = new CertificateAuthenticationEvents
- {
- OnCertificateValidated = context =>
- {
- var validationService =
- context.HttpContext.RequestServices.GetService();
-
- if (validationService!.ValidateCertificate(context.ClientCertificate))
- {
- var claims = new[]
- {
- new Claim(ClaimTypes.NameIdentifier, context.ClientCertificate.Subject, ClaimValueTypes.String, context.Options.ClaimsIssuer),
- new Claim(ClaimTypes.Name, context.ClientCertificate.Subject, ClaimValueTypes.String, context.Options.ClaimsIssuer)
- };
-
- context.Principal = new ClaimsPrincipal(new ClaimsIdentity(claims, context.Scheme.Name));
- context.Success();
- }
- else
- {
- context.Fail("invalid cert");
- }
-
- return Task.CompletedTask;
- }
- };
- });
-
- services.AddAuthorization();
- services.AddControllers();
- }
-
- // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
- public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
- {
- if (env.IsDevelopment())
- {
- app.UseDeveloperExceptionPage();
- }
-
- app.UseHttpsRedirection();
-
- app.UseRouting();
-
- //app.UseCertificateForwarding();
- app.UseAuthentication();
- app.UseAuthorization();
-
- app.UseEndpoints(endpoints =>
- {
- endpoints.MapControllers();
- });
- }
-}
+using Microsoft.AspNetCore.Authentication.Certificate;
+using Microsoft.AspNetCore.Server.Kestrel.Https;
+using Microsoft.IdentityModel.JsonWebTokens;
+using Microsoft.IdentityModel.Logging;
+using Serilog;
+using System.Security.Claims;
+using System.Security.Cryptography.X509Certificates;
+
+namespace AzureCertAuth;
+
+internal static class StartupExtensions
+{
+ public static WebApplication ConfigureServices(this WebApplicationBuilder builder)
+ {
+ var services = builder.Services;
+ var configuration = builder.Configuration;
+
+ if(builder.Environment.IsDevelopment())
+ {
+ builder.WebHost.ConfigureKestrel((context, serverOptions) =>
+ {
+ serverOptions.ConfigureHttpsDefaults(listenOptions =>
+ {
+ listenOptions.ClientCertificateMode = ClientCertificateMode.RequireCertificate;
+ listenOptions.AllowAnyClientCertificate();
+ });
+ });
+ }
+
+ services.AddSingleton();
+
+ services.AddCertificateForwarding(options =>
+ {
+ options.CertificateHeader = "X-ARR-ClientCert";
+ options.HeaderConverter = (headerValue) =>
+ {
+ Console.WriteLine("headerValue: " + headerValue);
+
+ X509Certificate2? clientCertificate = null;
+ if (!string.IsNullOrWhiteSpace(headerValue))
+ {
+ byte[] bytes = Convert.FromBase64String(headerValue);
+ clientCertificate = new X509Certificate2(bytes);
+ }
+
+ return clientCertificate!;
+ };
+ });
+
+ services.AddAuthentication(CertificateAuthenticationDefaults.AuthenticationScheme)
+ .AddCertificate(options => // code from ASP.NET Core sample
+ {
+ // https://docs.microsoft.com/en-us/aspnet/core/security/authentication/certauth
+ options.AllowedCertificateTypes = CertificateTypes.All;
+
+ // Default values
+ //options.AllowedCertificateTypes = CertificateTypes.Chained;
+ //options.RevocationFlag = X509RevocationFlag.ExcludeRoot;
+ options.RevocationMode = X509RevocationMode.NoCheck;
+ options.ValidateCertificateUse = false;
+ options.ValidateValidityPeriod = false;
+
+ options.Events = new CertificateAuthenticationEvents
+ {
+ OnCertificateValidated = context =>
+ {
+ var validationService =
+ context.HttpContext.RequestServices.GetService();
+
+ if (validationService!.ValidateCertificate(context.ClientCertificate))
+ {
+ var claims = new[]
+ {
+ new Claim(ClaimTypes.NameIdentifier, context.ClientCertificate.Subject, ClaimValueTypes.String, context.Options.ClaimsIssuer),
+ new Claim(ClaimTypes.Name, context.ClientCertificate.Subject, ClaimValueTypes.String, context.Options.ClaimsIssuer)
+ };
+
+ context.Principal = new ClaimsPrincipal(new ClaimsIdentity(claims, context.Scheme.Name));
+ context.Success();
+ }
+ else
+ {
+ context.Fail("invalid cert");
+ }
+
+ return Task.CompletedTask;
+ },
+ OnAuthenticationFailed = new Func(context =>
+ {
+ Console.WriteLine("OnAuthenticationFailed: " + context.Exception.Message);
+ return Task.CompletedTask;
+ })
+ };
+ });
+
+ services.AddAuthorization();
+ services.AddControllers();
+
+ return builder.Build();
+ }
+
+ public static WebApplication ConfigurePipeline(this WebApplication app)
+ {
+ IdentityModelEventSource.ShowPII = true;
+ JsonWebTokenHandler.DefaultInboundClaimTypeMap.Clear();
+
+ app.UseSerilogRequestLogging();
+
+ if (app.Environment.IsDevelopment())
+ {
+ app.UseDeveloperExceptionPage();
+ }
+
+ app.UseHttpsRedirection();
+
+ app.UseRouting();
+
+ if (app.Environment.IsDevelopment())
+ {
+ app.UseCertificateForwarding();
+ }
+
+ app.UseAuthentication();
+ app.UseAuthorization();
+
+ app.MapControllers();
+
+ return app;
+ }
+}
\ No newline at end of file
diff --git a/examplesUsingCertificateAuthentication/AzureCertAuth/AzureCertAuth/server.pfx b/examplesUsingCertificateAuthentication/AzureCertAuth/AzureCertAuth/server.pfx
deleted file mode 100644
index 0a16db7..0000000
Binary files a/examplesUsingCertificateAuthentication/AzureCertAuth/AzureCertAuth/server.pfx and /dev/null differ
diff --git a/examplesUsingCertificateAuthentication/AzureCertAuth/AzureCertAuthClientConsole/Program.cs b/examplesUsingCertificateAuthentication/AzureCertAuth/AzureCertAuthClientConsole/Program.cs
index c6ff016..be75d95 100644
--- a/examplesUsingCertificateAuthentication/AzureCertAuth/AzureCertAuthClientConsole/Program.cs
+++ b/examplesUsingCertificateAuthentication/AzureCertAuth/AzureCertAuthClientConsole/Program.cs
@@ -22,7 +22,7 @@ private static async Task GetApiDataUsingHttpClientHandler()
handler.ClientCertificates.Add(cert);
var client = new HttpClient(handler);
- var url = "https://localhost:44361/WeatherForecast";
+ var url = "https://localhost:5009/WeatherForecast";
//var url = "https://azurecertauth20201108214641.azurewebsites.net/WeatherForecast";
var request = new HttpRequestMessage()
{