How to manage/use the token returned (on successful login) by a webapi provider?

ssruk2019

New member
Joined
Jun 13, 2019
Messages
3
Programming Experience
3-5
Hi,
I am trying to add online appointment booking functionality to an existing website which is built using Umbraco. And using a third party web api service to implement this booking functionality. This web-api provider also handles the login part to authenticate the user and returns the XSRF-TOKEN which i need to use(implicitly) to call their other APIs. So far i am able to get this token and add it to DefaultRequestHeaders (inside the same controller)like:
public class AccountController : SurfaceController
{
HttpClient client;
CookieContainer cookies = new CookieContainer();
string token;
public AccountController()
{
HttpClientHandler handler = new HttpClientHandler();
handler.CookieContainer = cookies;
client = new HttpClient(handler);
client.BaseAddress = new Uri("url");
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new
MediaTypeWithQualityHeaderValue("application/json"));
}

public async Task<bool> ValidateLogin(LoginModel model)
{
HttpResponseMessage responseMessage = await client.PostAsJsonAsync("url", model);
Uri uri = new Uri("url");
IEnumerable<Cookie> responseCookies = cookies.GetCookies(uri).Cast<Cookie>();

token = responseCookies.FirstOrDefault(x => x.Name == "XSRF-TOKEN").Value;
if (!String.IsNullOrWhiteSpace(token))
{
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("X-XSRF-TOKEN", token);
client.DefaultRequestHeaders.Add("X-XSRF-TOKEN", token);
return true;
}
return false;
}

public async Task<ActionResult> GetUserDetails()
{
HttpResponseMessage responseMessage = await client.GetAsync("url");
if (responseMessage.IsSuccessStatusCode)
{
MyViewModel model = new MyViewModel();
var responseData = responseMessage.Content.ReadAsStringAsync().Result;//Getting an unauthorised response back here since the token is not handled as required

model.UserDetails = JsonConvert.DeserializeObject<MyViewModel>(responseData);
model.Appointments = await GetAppointmentsByUser();
return PartialView("_UserDetails", model);
}
return CurrentUmbracoPage();
}

private Task<object> GetAppointmentsByUser()
{
//Code
}

So now the real problem is how to manage/handle this token so the logged user can get authenticated to use other GET, PUT,POST requests?
I'm new to webAPI and MVC authentication so detailed explanation to the solution will be appreciated.
Can you guide me to implement this in a proper way please?
Thanks in advance.
 

Skydiver

Well-known member
Joined
Apr 6, 2019
Messages
214
Location
Virginia Beach, VA
Programming Experience
10+
How do you know that the same instance of your AccountControllercontroller is being used between for the call to ValidateLogin() and GetUserDetails() ?

Right now you are stashing the XSRF-TOKEN into client.DefaultRequestHeaders, but client is an instance variable. If two different instances of the controller are in play, then they will not share their instance variables. Let me warn you know that using a static class variable is not the correct solution because now all instances will share the same client which is likely not what you want to happen when two different people are logging in at the same time.
 

ssruk2019

New member
Joined
Jun 13, 2019
Messages
3
Programming Experience
3-5
Yes thanks but I know this already, this is why I was looking for a help. I'm also aware know this is not correct implementation. Actually I am a newbie in API development and never done this part of the HTTP configuration before so expecting sort of guide/Reference/pointer where I can find the proper implementation solution for this.
 

Skydiver

Well-known member
Joined
Apr 6, 2019
Messages
214
Location
Virginia Beach, VA
Programming Experience
10+
I was actually trying my best to avoid alluding to that code project article (I ran across it several years ago) because it is dealing with things at the "application" level vs. your current code which is doing things at the "controller" level. Furthermore, the common theme in that article was that he is recycling each of the HttpClient because he is using them in a more or less stateless manner. Any state he sets up is shared state. In your case, you need a per-user-login state is my understanding.

Notice that at the end of the article, he has shows how to deal with just a shared HttpClient but the actual message being send has varying content (
HttpRequestMessage
). In your case, your content needs that X-XSRF-TOKEN set. Which brings you back to the original problem, where do you store the per-user value of XSRF-TOKEN so that you can set X-XSRF-TOKEN at the appropriate time?
 
Top Bottom