Reputation: 27955
HTTP GET
request is done from ASP.NET Core 9 MVC controller using HttpClientFactory
described in https://learn.microsoft.com/en-us/aspnet/core/fundamentals/http-requests?view=aspnetcore-9.0
Program.cs
:
internal class Program {
public const string LhvClient = "lhvclient";
static void Main(string[] args) {
WebApplicationBuilder builder = WebApplication.CreateBuilder(args);
const string lhvprivaatvoti = @"-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEAtlfiLYZ48IwU3cbJA69m5F9xCiamWzEvkzseP8aAuLHDVdUi
AVIzvKZeILr/M9Sc+wowLYz0azBV64YiFI9qoder4BcfkfvznjRKwPUl6wQhOMUG
hkM79VusdcUAiP31f0pVTtEKhmMqJik5asalB1TFdjylaW3VbrkHqdXVFw91Q3aK
ifrc4Z6KDPt6wqDCXe108mG0QyaSGtc0lBuV0ZoWL3ZNHrbh3NRV4Ojb/O3mAog8
rV0FbAufy0qZnaTse52x8KqZDE2rJjNWr23QLk2OAezt6t7a2ZCOLF3OS+tMqyeu
M8N1lqQIORFo18iYxAXt5Rd9g6Ap6KpE8ahzuQIDAQABAoIBABLtFPJ+u6d+vV0L
mKpY7AgWM/McHIuTPl88yqCkp5BZZcSkm6P2y/HvyWNXpXd+wPskN+idHHLSZd34
DSovJ0qRyoA28OBD038p6acU4Duq27vlug342oysAumHv3d4ofZKrodra86Tv7iN
nNe4CJcLNc0A8cul9ST0muwGNYOaup0wOqLOskfvXmhqYT8gu9h8sbsW40WupIip
OFUwlGXBwtWCycJTD/UdsCKQZZ1oTX/oWpXDslzUyeUwssgaFdJwAw2Y1IQDODLk
oV9pSjr2inWfIz0ILbtm131zSTY7BSMspbW1IKT1WJlrJz5gAYJjOddsoZ8RwUtX
OHnPBFUCgYEA3InyQPWue5MU0j2PSNY3WQaMg/jD1zelmWZ1M65mxihfl/Ctf33I
8mtEGoWzwaNgRcyTgd2SqOxHMUqeJ1b6mVSRgnC8GtSV32AG/k3qpZ6BB/rLZu5E
hOcCoqysdF/ng4y1blVoZeJ4u06VI2tSjrp79M2aHh5WNEyEuZ4xSZsCgYEA06mw
9AXg1LgwsBQJpNbMRwK7UVoJgjMiwKfsMkIDe2keeJo5eD68cseyOyvRjcssft8d
Sxi3AAMa0ymHOi7/m013PHkfzVSeT0nmL2iGZ1s+w9EnVzwzkNXrFL9T9/QPTOTS
75tPcbmWvMxwBxgdE5GouVpI+/PSAXYKoVQPxzsCgYEAyAnkECII2xQFPdISxplv
6LN0/zvEv9E8xxDVXERj+neihdoMNWktvR2oz3nZG9oKOCWg4pnNLqXqyX4KSFqv
wiagObXyGVAchVm/3ilknkdQeKF2n+2dfwNfM5j2cDSRdZRK+UJFCK1Mn3Fe+5qc
btQeHWXk1k7kGFoTxZ4EzOMCgYApA3mZX0Y4kdRFWiygN0rv+5SGZ/bttrDmOeOn
vWjlUfIolmHKbgWgDBf6JTx+yD6/+sW3VnunUfKxthtQ5+h5lGIlYqcJ53qhjIVA
7HUWs/SOhwmjerPXPcxGgehoZG9OjAxfh222cKrHvKl8hmyj7RaPi/IWeCFaTSA0
MJC6HwKBgQDVLOevx/XyYiIkOCNn90kyPBNOhMz7vo8vooE8sHCr7y/NerCZfDxG
1c74EBD8aAyLDbQWh3aoi698TvVhbwtsLwh+KqkajSuGnVKVkhMFm+H6Pny/UF16
jMQa/SSC4BBj5Y8IIPXoJC4HNlqocCBKHUgQHAurmXMR4ExHCq8ROg==
-----END RSA PRIVATE KEY-----";
const string lhvsert = @"-----BEGIN CERTIFICATE-----
MIIE4TCCAsmgAwIBAgIGAZPGzbosMA0GCSqGSIb3DQEBCwUAMGgxCzAJBgNVBAYT
AkVFMREwDwYDVQQIDAhIYXJqdW1hYTEUMBIGA1UECgwLQVMgTEhWIFBhbmsxDTAL
BgNVBAsMBFBTRDIxITAfBgNVBAMMGExIViBQU0QyIEludGVybWVkaWF0ZSBDQTAe
Fw0yNDEyMTQyMDEzMTFaFw0zNDEyMTIyMDEzMTFaMIGFMR0wGwYDVQRhExRQU0RF
RS1MSFZURVNULThmMjBmZTEeMBwGA1UEAxMVUFNEMiB0ZXN0IGNlcnRpZmljYXRl
MRIwEAYDVQQKEwlQU0QyIFRlc3QxEDAOBgNVBAcTB1RhbGxpbm4xETAPBgNVBAgT
CEhhcmp1bWFhMQswCQYDVQQGEwJFRTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC
AQoCggEBALZX4i2GePCMFN3GyQOvZuRfcQomplsxL5M7Hj/GgLixw1XVIgFSM7ym
XiC6/zPUnPsKMC2M9GswVeuGIhSPaqHXq+AXH5H78540SsD1JesEITjFBoZDO/Vb
rHXFAIj99X9KVU7RCoZjKiYpOWrGpQdUxXY8pWlt1W65B6nV1RcPdUN2ion63OGe
igz7esKgwl3tdPJhtEMmkhrXNJQbldGaFi92TR624dzUVeDo2/zt5gKIPK1dBWwL
n8tKmZ2k7HudsfCqmQxNqyYzVq9t0C5NjgHs7ere2tmQjixdzkvrTKsnrjPDdZak
CDkRaNfImMQF7eUXfYOgKeiqRPGoc7kCAwEAAaNzMHEwbwYIKwYBBQUHAQMEYzBh
BgYEAIGYJwIwVzA5MBEGBwQAgZgnAQIMBlBTUF9QSTARBgcEAIGYJwEDDAZQU1Bf
QUkwEQYHBACBmCcBBAwGUFNQX0lDDBNGaW5hbnRzaW5zcGVrdHNpb29uDAVFRS1G
STANBgkqhkiG9w0BAQsFAAOCAgEAhYm3S+mdyR837aTYk5ZGyXQ5d9ocSiHFDRnU
j0AxDRCqJ70/jmj0vur4NfAeOC4yz3YXr2jBl0yPBDaXATUQClbMyYr4QIQJLa0Y
FJ2iDQtN4j6jvi1GcWAyvlW8XSzi1y7mv6ggvkomhkkwd6Ua1EYqduxfrmbu7xOH
bPd9QgJJkGCY5JmbNAAEL9W12ErZVR5zbJqieTxnetl6clApE4ZuSXWjhyNCbztk
UJ/9UEZekMiLUCaxiFHQR81UxH7gMzjawTVL54xszddZZ8Tya5J3ayQ5XwpA6t0C
u2UfhND2f/V8M5N0PaEaXJq+ekeE/eXx8cf/lFr3kesGWCN395NLAfG+W+Ov7d5b
GBlnLBaZMcQ70Kv3GNHSFsILllJbv92NK28c00/Gyoo8bekCyMcVKv4rEy9vxLW4
zUkDJOZJ5cM+w1jqgpfQG52rYHpRr1uY0rZx2R8DnXKp+rZ/m6u0uuEqwi5jTk2+
zjXGocNBGdh5JsDlw31n/SmgzCn4KLH+RPHKCRtBB20oZBcy0ApVvMRCA45T5NKY
K1Pavic5YCgg2jM2APN6xH6SCdmzJhipOXmYOwYVYW5QYIl8du52xIhEGSzzCiEJ
zho4eB9Cgti+BJTdYOq0AV3Ad2EUckEkXhVG5u4N5MdhDHqk2gC3IsEpMAwb8J3b
sT3qlI0=
-----END CERTIFICATE-----";
var lhvhandler = new HttpClientHandler {
ClientCertificateOptions = ClientCertificateOption.Manual,
ServerCertificateCustomValidationCallback = HttpClientHandler.DangerousAcceptAnyServerCertificateValidator
};
var sert1 = X509Certificate2.CreateFromPem(lhvsert, lhvprivaatvoti);
lhvhandler.ClientCertificates.Add(sert1);
var lhv = builder.Services.AddHttpClient(LhvClient);
lhv.ConfigurePrimaryHttpMessageHandler(() = >lhvhandler);
}
}
Controller:
[Authorize]
public class LhvController(IHttpClientFactory httpClientFactory) : Controller {
public async Task < IActionResult > Index() {
HttpClient client = httpClientFactory.CreateClient(Program.LhvClient);
var tulem = await client.GetStringAsync("https://api.lhv.eu/psd2/v1/accounts-list?onlyActive=true");
return new ContentResult() {
Content = tulem,
ContentType = "text/json"
};
}
}
In controller different certificate is required depending on production/sandbox environment and tenant in multi-tenant application. Certificates are stored in the database and fetched using EF Core.
HttpClient
does not have method to set certificate. Tried also to create HttpRequestMessage
in controller, but HttpRequestMessage
also does not allow to set certificate.
How to use specify certificate in controller before making GET
requests?
Upvotes: 1
Views: 86
Reputation: 1526
Option#1
Create a pool of the preconfigured handlers with your custom certs, and then follow this guideline to create the client:
Option#2
Just a draft but the idea behind should be clear:
class MyCustomBuilder : HttpMessageHandlerBuilder
{
public override string? Name { get; set; }
public override HttpMessageHandler PrimaryHandler { get; set; }
public MyCustomBuilder(HttpMessageHandler primaryHandler)
{
PrimaryHandler = primaryHandler;
}
public override IList<DelegatingHandler> AdditionalHandlers { get; } = new List<DelegatingHandler>();
public override HttpMessageHandler Build()
{
//TODO:see DefaultHttpMessageHandlerBuilder impl
}
}
...
services.AddTransient<HttpMessageHandlerBuilder, MyCustomBuilder>(sp =>
{
//have a pool of builders, like one per your tenant or wharever
return pool.GetOrAdd("tenantId", (n) => new MyCustomBuilder(
new HttpClientHandler()));
});
Option#3
Use named clients, one per tenant -
services.AddHttpClient("tenant1")
.ConfigurePrimaryHttpMessageHandler((sp) =>
{
return new HttpClientHandler();
});
services.AddHttpClient("tenant2")
.ConfigurePrimaryHttpMessageHandler((sp) =>
{
return new HttpClientHandler();
});
...
IServiceProvider sp = services.BuildServiceProvider();
IHttpClientFactory factory = sp.GetRequiredService<IHttpClientFactory>();
var client1 = factory.CreateClient("tenant1");
var client2 = factory.CreateClient("tenant2");
Upvotes: 0