Reputation: 842
how can I add cookies to HttpClient
used in injected service (example)? I have created some service ApiService
and that service has HttpClient
injected just like CatalogService
in tutorial. Problem is, in order to communicate with external API, my service and it's HttpClient
must have a token which was previously received by another API called IdentityService
using LoginService
. So, when login is completed in fronted web app:
if (!string.IsNullOrEmpty(user.Token)) {
ClaimsPrincipal principal = ValidateToken(user.Token);
if (principal != null) {
AuthenticationProperties p = new AuthenticationProperties();
p.ExpiresUtc = DateTime.UtcNow.AddDays(7);
p.IsPersistent = Persistant;
p.RedirectUri = Request.Query.ContainsKey("ReturnUrl") ? Request.Query["ReturnUrl"].ToString() : "";
await HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, principal, p);
// those cookies are lost when ApiController is called - new instance of http client replaces this one
var apiService = HttpContext.RequestServices.GetService(typeof(IApiService));
var s = apiService as ApiService;
s.SetClientCookies("token", user.Token);
return new RedirectToPageResult("../Index");
}
}
return BadRequest("Invalid token");
SetClientCookies
currently looks like this but it isn't working because ApiService constructor gets a new instance of HttpClient:
public class ApiService: IApiService {
public static readonly NLog.Logger log = NLog.LogManager.GetCurrentClassLogger();
private HttpClient _client;
static string BaseUrl = "https://localhost:44365/api";
public ApiService(HttpClient client) {
_client = client;
}
public async Task < List < DbTest >> GetAccounts() {
var httpResponse = await _client.GetAsync(BaseUrl + "/account");
if (!httpResponse.IsSuccessStatusCode) {
throw new Exception("Cannot retrieve login");
}
var content = await httpResponse.Content.ReadAsStringAsync();
var accounts = JsonConvert.DeserializeObject < List < DbTest >> (content);
return accounts;
}
public void SetClientCookies(string key, string value) {
_client.DefaultRequestHeaders.Add("Cookie", key + "=" + value);
}
}
Result is, when API is called with HttpClient
, there is no "token" cookie... Any idea how to change this so ApiService
's HttpClient
doesn't lose its cookies which are received on login?
Related Startup.cs
code is this:
services.AddHttpClient<ILoginService, LoginService>("identityServiceClient");
services.AddHttpClient<IApiService, ApiService>("apiServiceClient")
.ConfigureHttpClient(client => {
client.Timeout = TimeSpan.FromSeconds(30);
}).ConfigurePrimaryHttpMessageHandler(() => new HttpClientHandler() {
CookieContainer = new CookieContainer()
});
Upvotes: 7
Views: 3183
Reputation: 247551
A possibility would be to add a cookie container to the service collection
var container = new CookieContainer();
services.AddSingleton(container);
and use that instance when registering the client
services.AddHttpClient<IApiService, ApiService>(client => {
client.Timeout = TimeSpan.FromSeconds(30);
client.BaseAddress = new Uri("https://localhost:44365/api").
}).ConfigurePrimaryHttpMessageHandler(() => new HttpClientHandler() {
CookieContainer = container,
UseCookies = true
});
Now the container can be resolved and manipulated as needed.
var container = HttpContext.RequestServices.GetService<CookieContainer>();
container.Add(BaseUrl, new Cookie("token", user.Token));
Upvotes: 5