Where to store the carrier token in MVC from the web API

Screnario

I have an ASP.NET web API that uses an OAuth password stream to provide media tokens to access its resources.

Now I am making an MVC application that will have to use this API.

The plan is for MVCs to make API calls on behalf of the client’s browser.

Ajax requests from the browser will go to MVC controllers, and then API calls. The results are then passed back to the client as JSON and processed in java-script.

The client should not communicate directly with the API.

Obtaining Authentication.

I need to best handle the carrier token as soon as it was received in the MVC application through a successful API token endpoint call.

I need to use this bearer token in any subsequent api calls.

My plan is to save it to System.Web.HttpContext.Current.Session["BearerToken"]

Then I can create a custom AuthorizationAttribute that will check if the BearerToken is present in the current HttpContext, if it is not there, the client will need to revise the token access point.

Is it possible?

I ask people for this opinion, because I’m not convinced that this is the best solution for my project.

+8
security c # session asp.net-mvc-5 asp.net-web-api2
source share
2 answers

I managed to come up with something that, in my opinion, would work well.

I use Owin middleware for cookie authentication.

In the MVC application, I have an Owin launcher file in which Cookie authentication is configured: -

  public class Startup { public void Configuration(IAppBuilder app) { // For more information on how to configure your application, visit http://go.microsoft.com/fwlink/?LinkID=316888 app.UseCookieAuthentication(new CookieAuthenticationOptions() { AuthenticationType = "ApplicationCookie", LoginPath = new PathString("/Account/Login"), }); } } 

Then I created an AccountController with two Action methods for logging in and logging out: -

Login to the system.

 public ActionResult Login(LoginModel model,string returnUrl) { var getTokenUrl = string.Format(ApiEndPoints.AuthorisationTokenEndpoint.Post.Token, ConfigurationManager.AppSettings["ApiBaseUri"]); using (HttpClient httpClient = new HttpClient()) { HttpContent content = new FormUrlEncodedContent(new[] { new KeyValuePair<string, string>("grant_type", "password"), new KeyValuePair<string, string>("username", model.EmailAddress), new KeyValuePair<string, string>("password", model.Password) }); HttpResponseMessage result = httpClient.PostAsync(getTokenUrl, content).Result; string resultContent = result.Content.ReadAsStringAsync().Result; var token = JsonConvert.DeserializeObject<Token>(resultContent); AuthenticationProperties options = new AuthenticationProperties(); options.AllowRefresh = true; options.IsPersistent = true; options.ExpiresUtc = DateTime.UtcNow.AddSeconds(int.Parse(token.expires_in)); var claims = new[] { new Claim(ClaimTypes.Name, model.EmailAddress), new Claim("AcessToken", string.Format("Bearer {0}", token.access_token)), }; var identity = new ClaimsIdentity(claims, "ApplicationCookie"); Request.GetOwinContext().Authentication.SignIn(options, identity); } return RedirectToAction("Index", "Home"); } 

Sign Out

  public ActionResult LogOut() { Request.GetOwinContext().Authentication.SignOut("ApplicationCookie"); return RedirectToAction("Login"); } 

Resource Protection

  [Authorize] public class HomeController : Controller { private readonly IUserSession _userSession; public HomeController(IUserSession userSession) { _userSession = userSession; } // GET: Home public ActionResult Index() { ViewBag.EmailAddress = _userSession.Username; ViewBag.AccessToken = _userSession.BearerToken; return View(); } } public interface IUserSession { string Username { get; } string BearerToken { get; } } public class UserSession : IUserSession { public string Username { get { return ((ClaimsPrincipal)HttpContext.Current.User).FindFirst(ClaimTypes.Name).Value; } } public string BearerToken { get { return ((ClaimsPrincipal)HttpContext.Current.User).FindFirst("AcessToken").Value; } } } 
+7
source share

Since you mentioned that you are using HttpClient (). I did a similar thing using HttpClient () -

Get token -

  static Dictionary<string, string> GetTokenDetails(string userName, string password) { Dictionary<string, string> tokenDetails = null; try { using (var client = new HttpClient()) { var login = new Dictionary<string, string> { {"grant_type", "password"}, {"username", userName}, {"password", password}, }; var resp = client.PostAsync("http://localhost:61086/token", new FormUrlEncodedContent(login)); resp.Wait(TimeSpan.FromSeconds(10)); if (resp.IsCompleted) { if (resp.Result.Content.ReadAsStringAsync().Result.Contains("access_token")) { tokenDetails = JsonConvert.DeserializeObject<Dictionary<string, string>>(resp.Result.Content.ReadAsStringAsync().Result); } } } } catch (Exception ex) { } return tokenDetails; } 

Use token to send data

 static string PostData(string token, List<KeyValuePair<string, string>> lsPostContent) { string response = String.Empty; try { using (var client = new HttpClient()) { FormUrlEncodedContent cont = new FormUrlEncodedContent(lsPostContent); client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token); var resp = client.PostAsync("https://localhost:61086/api/<your API controller>/", cont); resp.Wait(TimeSpan.FromSeconds(10)); if (resp.IsCompleted) { if (resp.Result.StatusCode == HttpStatusCode.Unauthorized) { Console.WriteLine("Authorization failed. Token expired or invalid."); } else { response = resp.Result.Content.ReadAsStringAsync().Result; Console.WriteLine(response); } } } } catch (Exception ex) { } return response; } 

Even if you store the Bearer token in the HttpContext, you will need to take care of the token expiration time set in the web API. Checking for a token only in the session will not help, because the old token will be invalid after the expiration date.

+1
source share

All Articles