Add sample code in docs to handle URL-encoded client certs, eg. on NGINX / Kubernetes NGINX Ingress (#22484)

pull/22612/head
Ray 2021-06-25 20:45:01 +08:00 committed by GitHub
parent 34376d55eb
commit 1ed406ace8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 73 additions and 0 deletions

View File

@ -311,6 +311,79 @@ private static byte[] StringToByteArray(string hex)
}
```
If the app is reverse proxied by NGINX with the configuration `proxy_set_header ssl-client-cert $ssl_client_escaped_cert` or deployed on Kubernetes using NGINX Ingress, the client certificate is passed to the app in [URL-encoded form](https://developer.mozilla.org/docs/Glossary/percent-encoding). To use the certificate, decode it as follows:
::: moniker range=">= aspnetcore-5.0"
In `Startup.ConfigureServices` (`Startup.cs`):
```csharp
services.AddCertificateForwarding(options =>
{
options.CertificateHeader = "ssl-client-cert";
options.HeaderConverter = (headerValue) =>
{
X509Certificate2 clientCertificate = null;
if (!string.IsNullOrWhiteSpace(headerValue))
{
string certPem = WebUtility.UrlDecode(headerValue);
clientCertificate = X509Certificate2.CreateFromPem(certPem);
}
return clientCertificate;
};
});
```
::: moniker-end
::: moniker range="< aspnetcore-5.0"
Add the namespace for <xref:System.Net?displayProperty=fullName> to the top of `Startup.cs`:
```csharp
using System.Net;
```
In `Startup.ConfigureServices`:
```csharp
services.AddCertificateForwarding(options =>
{
options.CertificateHeader = "ssl-client-cert";
options.HeaderConverter = (headerValue) =>
{
X509Certificate2 clientCertificate = null;
if (!string.IsNullOrWhiteSpace(headerValue))
{
var bytes = UrlEncodedPemToByteArray(headerValue);
clientCertificate = new X509Certificate2(bytes);
}
return clientCertificate;
};
});
```
Add the `UrlEncodedPemToByteArray` method:
```csharp
private static byte[] UrlEncodedPemToByteArray(string urlEncodedBase64Pem)
{
var base64Pem = WebUtility.UrlDecode(urlEncodedBase64Pem);
var base64Cert = base64Pem
.Replace("-----BEGIN CERTIFICATE-----", string.Empty)
.Replace("-----END CERTIFICATE-----", string.Empty)
.Trim();
return Convert.FromBase64String(base64Cert);
}
```
::: moniker-end
The `Startup.Configure` method then adds the middleware. `UseCertificateForwarding` is called before the calls to `UseAuthentication` and `UseAuthorization`:
```csharp