Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Where to store Bearer Token in MVC from Web API

Tags:

Scenario

I have an ASP.NET Web API that uses the OAuth Password Flow to provide Bearer Tokens to gain access to its resources.

I'm now in the process of making an MVC app that will need to use this API.

The plan is to have the MVC controllers make calls to the API on behalf of the client browser.

The ajax requests from the browser will hit the MVC controllers and then the API calls are made. Results are then fed back to the client as JSON and handles in java-script.

The client should never communicate directly with the API.

Getting Authenticated.

I need to find the best way to handle the Bearer Token once it has been received in the MVC app via a successful call to the web api token endpoint.

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

My plan is to store it in the System.Web.HttpContext.Current.Session["BearerToken"]

I can then create a custom AuthorizationAttribute that will check to see if a BearerToken is present in the current HttpContext, if it is not present, the client will need to revisit the token endpoint.

Does this seem feasible?

I'm asking for peoples opinion on this as I am not convinced this the best solution for my project.

like image 983
Derek Avatar asked Sep 13 '16 08:09

Derek


People also ask

Where should I store bearer token?

If any of the third-party scripts you include in your page is compromised, it can access all your users' tokens. To keep them secure, you should always store JWTs inside an httpOnly cookie. This is a special kind of cookie that's only sent in HTTP requests to the server.

Where is token stored in Web API?

By default the token is not stored by the server. Only your client has it and is sending it through the authorization header to the server. If you used the default template provided by Visual Studio, in the Startup ConfigureAuth method the following IAppBuilder extension is called: app.

What is bearer token in Web API?

Bearer token. A particular type of access token, with the property that anyone can use the token. In other words, a client doesn't need a cryptographic key or other secret to use a bearer token. For that reason, bearer tokens should only be used over a HTTPS, and should have relatively short expiration times.


1 Answers

I've managed to come up with something that i think will work quite well.

I'm using the Owin Middleware for Cookie Authentication.

Within the MVC Application i have an Owin Startup file where the 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"),              });         }     } 

I then made an AccountController with two Action methods for Logging In and Logging out :-

Logging In.

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");         } 

Logging Out

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

Protecting the Resources

    [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; }         }      } 
like image 91
Derek Avatar answered Oct 01 '22 19:10

Derek