From a9aa1424e3c37bd0213c63df10173acadade761c Mon Sep 17 00:00:00 2001 From: Scott Addie <10702007+scottaddie@users.noreply.github.com> Date: Thu, 14 Nov 2019 14:45:42 -0600 Subject: [PATCH] Replace cert authN README content with link to official doc (#16906) --- .../Certificate/src/README-IISConfig.png | Bin 10168 -> 0 bytes .../Authentication/Certificate/src/README.md | 205 +----------------- 2 files changed, 2 insertions(+), 203 deletions(-) delete mode 100644 src/Security/Authentication/Certificate/src/README-IISConfig.png diff --git a/src/Security/Authentication/Certificate/src/README-IISConfig.png b/src/Security/Authentication/Certificate/src/README-IISConfig.png deleted file mode 100644 index 3af15e9d0652fba1a66b1704d7990e68ba98bba3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10168 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 M%34b03g)5z3t&Zgy#N3J diff --git a/src/Security/Authentication/Certificate/src/README.md b/src/Security/Authentication/Certificate/src/README.md index b5654819e6..a589666e0a 100644 --- a/src/Security/Authentication/Certificate/src/README.md +++ b/src/Security/Authentication/Certificate/src/README.md @@ -1,206 +1,5 @@ # Microsoft.AspNetCore.Authentication.Certificate - + This project sort of contains an implementation of [Certificate Authentication](https://tools.ietf.org/html/rfc5246#section-7.4.4) for ASP.NET Core. Certificate authentication happens at the TLS level, long before it ever gets to ASP.NET Core, so, more accurately this is an authentication handler that validates the certificate and then gives you an event where you can resolve that certificate to a ClaimsPrincipal. -You **must** [configure your host](#configuring-your-host-to-require-certificates) for certificate authentication, be it IIS, Kestrel, Azure Web Applications or whatever else you're using. - -## Getting started - -First acquire an HTTPS certificate, apply it and then [configure your host](#configuring-your-host-to-require-certificates) to require certificates. - -In your web application add a reference to the package, then in the `ConfigureServices` method in `startup.cs` call `app.AddAuthentication(CertificateAuthenticationDefaults.AuthenticationScheme).UseCertificateAuthentication(...);` with your options, providing a delegate for `OnValidateCertificate` to validate the client certificate sent with requests and turn that information into an `ClaimsPrincipal`, set it on the `context.Principal` property and call `context.Success()`. - -If you change your scheme name in the options for the authentication handler you need to change the scheme name in `AddAuthentication()` to ensure it's used on every request which ends in an endpoint that requires authorization. - -If authentication fails this handler will return a `403 (Forbidden)` response rather a `401 (Unauthorized)` as you might expect - this is because the authentication should happen during the initial TLS connection - by the time it reaches the handler it's too late, and there's no way to actually upgrade the connection from an anonymous connection to one with a certificate. - -You must also add `app.UseAuthentication();` in the `Configure` method, otherwise nothing will ever get called. - -For example: - -```c# -public void ConfigureServices(IServiceCollection services) -{ - services.AddAuthentication(CertificateAuthenticationDefaults.AuthenticationScheme) - .AddCertificate(); - // All the other service configuration. -} - -public void Configure(IApplicationBuilder app, IHostingEnvironment env) -{ - app.UseAuthentication(); - - // All the other app configuration. -} -``` - -In the sample above you can see the default way to add certificate authentication. The handler will construct a user principal using the common certificate properties for you. - -## Configuring Certificate Validation - -The `CertificateAuthenticationOptions` handler has some built in validations that are the minimum validations you should perform on a certificate. Each of these settings are turned on by default. - -### ValidateCertificateChain - -This check validates that the issuer for the certificate is trusted by the application host OS. If you are going to accept self-signed certificates you must disable this check. - -### ValidateCertificateUse - -This check validates that the certificate presented by the client has the Client Authentication extended key use, or no EKUs at all (as the specifications say if no EKU is specified then all EKUs are valid). - -### ValidateValidityPeriod - -This check validates that the certificate is within its validity period. As the handler runs on every request this ensures that a certificate that was valid when it was presented has not expired during its current session. - -### RevocationFlag - -A flag which specifies which certificates in the chain are checked for revocation. - -Revocation checks are only performed when the certificate is chained to a root certificate. - -### RevocationMode - -A flag which specifies how revocation checks are performed. - -Specifying an on-line check can result in a long delay while the certificate authority is contacted. - -Revocation checks are only performed when the certificate is chained to a root certificate. - -### Can I configure my application to require a certificate only on certain paths? - -Not possible, remember the certificate exchange is done that the start of the HTTPS conversation, it's done by the host, not the application. Kestrel, IIS, Azure Web Apps don't have any configuration for this sort of thing. - -## Handler events - -The handler has two events, `OnAuthenticationFailed()`, which is called if an exception happens during authentication and allows you to react, and `OnValidateCertificate()` which is called after certificate has been validated, passed validation, abut before the default principal has been created. This allows you to perform your own validation, for example checking if the certificate is one your services knows about, and to construct your own principal. For example: - -```c# -services.AddAuthentication(CertificateAuthenticationDefaults.AuthenticationScheme) - .AddCertificate(options => - { - options.Events = new CertificateAuthenticationEvents - { - OnValidateCertificate = context => - { - 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(); - - return Task.CompletedTask; - } - }; - }); -``` - -If you find the inbound certificate doesn't meet your extra validation call `context.Fail("failure Reason")` with a failure reason. - -For real functionality you will probably want to call a service registered in DI which talks to a database or other type of user store. You can grab your service by using the context passed into your delegates, like so - -```c# -services.AddAuthentication(CertificateAuthenticationDefaults.AuthenticationScheme) - .AddCertificate(options => - { - 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(); - } - - return Task.CompletedTask; - } - }; - }); -``` - -Note that conceptually the validation of the certification is an authorization concern, and putting a check on, for example, an issuer or thumbprint in an authorization policy rather -than inside OnCertificateValidated() is perfectly acceptable. - -## Configuring your host to require certificates - -### Kestrel - -In program.cs configure `UseKestrel()` as follows. - -```c# -public static IWebHost BuildWebHost(string[] args) - => WebHost.CreateDefaultBuilder(args) - .UseStartup() - .ConfigureKestrel(options => - { - options.ConfigureHttpsDefaults(opt => - { - opt.ClientCertificateMode = ClientCertificateMode.RequireCertificate; - }); - }) - .Build(); -``` - -You must set the `ClientCertificateValidation` delegate to `CertificateValidator.DisableChannelValidation` in order to stop Kestrel using the default OS certificate validation routine and, instead, letting the authentication handler perform the validation. - -### IIS - -In the IIS Manager: - -1. Select your Site in the Connections tab. -2. Double click the SSL Settings in the Features View window. -3. Check the `Require SSL` Check Box and select the `Require` radio button under Client Certificates. - -![Client Certificate Settings in IIS](README-IISConfig.png "Client Certificate Settings in IIS") - -### Azure - -See the [Azure documentation](https://docs.microsoft.com/azure/app-service/app-service-web-configure-tls-mutual-auth) to configure Azure Web Apps then add the following to your application startup method, `Configure(IApplicationBuilder app)` add the following line before the call to `app.UseAuthentication();`: - -```c# -app.UseCertificateHeaderForwarding(); -``` - -### Random custom web proxies - -If you're using a proxy which isn't IIS or Azure's Web Apps Application Request Routing you will need to configure your proxy to forward the certificate it received in an HTTP header. In your application startup method, `Configure(IApplicationBuilder app)`, add the following line before the call to `app.UseAuthentication();`: - -```c# -app.UseCertificateForwarding(); -``` - -You will also need to configure the Certificate Forwarding middleware to specify the header name. In your service configuration method, `ConfigureServices(IServiceCollection services)` add the following code to configure the header the forwarding middleware will build a certificate from: - -```c# -services.AddCertificateForwarding(options => -{ - options.CertificateHeader = "YOUR_CUSTOM_HEADER_NAME"; -}); -``` - -Finally, if your proxy is doing something weird to pass the header on, rather than base 64 encoding it (looking at you nginx (╯°□°)╯︵ ┻━┻) you can override the converter option to be a func that will perform the optional conversion, for example - -```c# -services.AddCertificateForwarding(options => -{ - options.CertificateHeader = "YOUR_CUSTOM_HEADER_NAME"; - options.HeaderConverter = (headerValue) => - { - var clientCertificate = - /* some weird conversion logic to create an X509Certificate2 */ - return clientCertificate; - } -}); -``` +For more information, see [Configure certificate authentication in ASP.NET Core](https://docs.microsoft.com/aspnet/core/security/authentication/certauth).