I’m a begginer in ASP .Net MVC/API.
I have an ASP .Net API with a login endpoint that returns a token. My endpoint login returns a json with the token and its expiration date. The usage of the token works perfectly in Postman : I can put another endpoint only accessible if there is a token in the header of the request, and I do get a unauthorized response if I don’t have the token, and a success response if I have the token.
But I can only get to make this work with postman.
I also have a ASP .Net MVC application with a login page, and I don’t know how to simply add my token in a Header for all my futur request.
In my MVC app, I use dependency injection to get a HttpClientFactory in my controller. So in Program.cs, I have :
builder.Services.AddHttpClient ("RestoCommandAPI", httpClient =>
{
httpClient.BaseAddress = new Uri ("http://localhost:5041/api/");
});
Then in my login controller, I get the token like that :
[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult Login ([Bind ("Email,Password")] UserInfo userInfo)
{
userInfo.Id = Guid.NewGuid ().ToString ();
if (ModelState.IsValid)
{
HttpClient client = _httpClientFactory.CreateClient ("RestoCommandAPI");
userInfo.Role = UserRoles.User;
string url = client.BaseAddress + "Authenticate/login";
//_client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", HttpContext.Session.GetString("token"));
try
{
string json = JsonConvert.SerializeObject (userInfo);
HttpResponseMessage response = client.PostAsync (url, new StringContent (json, System.Text.Encoding.UTF8, "application/json")).Result;
if (response.IsSuccessStatusCode)
{
Token? token = JsonConvert.DeserializeObject<Token> (response.Content.ReadAsStringAsync ().Result);
if (token == null)
throw new Exception ("Token null");
IHeaderDictionary result = new HeaderDictionary(new Dictionary<string, Microsoft.Extensions.Primitives.StringValues>());
result.Append("Authorization", new Microsoft.Extensions.Primitives.StringValues("Bearer " + token.Value));
HttpContext.Request.Headers.Authorization = result.Authorization;
// string? tokenValue = HttpContext.Request.Headers["Authorization"];
// client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue ("Bearer", token.Value);
return RedirectToAction ("Index", "Home");
}
else
{
int statusCode = (int) response.StatusCode;
return StatusCode (statusCode, response.ReasonPhrase + "nurl : " + url + "njson " + json);
}
}
catch (Exception e)
{
return StatusCode (500, e.Message);
}
}
return View (userInfo);
}
It does return 200 when I login. I get the token and try to add it in the HTTPContext class. I’ve also tried others stuff, like settings client.DefaultRequestHeaders
, but it’s not working because I want to set my Authorize Header for all HttpClient created by the factory, not only one client.
In another controller, I try to get the token to call a protected endpoint like that :
[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult Edit (string id, [Bind ("Id,Name,Description,Price,Type,ImageUrl")] Product product)
{
if (id != product.Id)
{
return NotFound ("Product with id " + id + " not found");
}
HttpResponseMessage response = null;
if (ModelState.IsValid)
{
Dictionary<string, string?> query = new Dictionary<string, string?>
{ { "Id", product.Id },
{ "Name", product.Name },
{ "Description", product.Description },
{ "Price", product.Price.ToString () },
{ "Type", product.Type.ToString () },
{ "ImageUrl", product.ImageUrl }
};
HttpClient client = _httpClientFactory.CreateClient ("RestoCommandAPI");
string? tokenValue = HttpContext.Request.Headers["Authorization"];
if (tokenValue == null)
return StatusCode (401, "No token found in request header");
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue ("Bearer", tokenValue);
string? requestUri = QueryHelpers.AddQueryString (client.BaseAddress + "product/edit/" + id, query);
HttpRequestMessage request = new HttpRequestMessage (HttpMethod.Put, requestUri);
response = client.SendAsync (request).Result;
}
else
{
return BadRequest (ModelState);
}
if (response == null)
{
return StatusCode (500, "Response is null");
}
if (response.IsSuccessStatusCode)
{
return RedirectToAction (nameof (Index));
}
else
{
int statusCode = (int) response.StatusCode;
return StatusCode (statusCode, response.ReasonPhrase);
}
}
It does not worked, even if I logged before. I get the error “No token found in request header”.
I’ve googled my issue, but didn’t find anything helpfull.
For example, I’ve found this : How to Refresh a token using IHttpClientFactory but I have no clue where their token comes from.
I just want to have Default Header Authentication that I could set in my controllers, I don’t understand why it’s so difficult.
I probably need to have a DelegatingHandler class, but how to store this token that I get from my login endpoint?
Thank you