Where to store Bearer Token in MVC from Web API

后端 未结 2 504
故里飘歌
故里飘歌 2020-12-12 18:12

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 t

相关标签:
2条回答
  • 2020-12-12 19:06

    Since you have mentioned 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 the token to Post 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 HttpContext, you will need to take care of the token expiry time which is set in the Web API. Validating the existence of token just in the session won't help since the old token will be invalid after the expiry time.

    0 讨论(0)
  • 2020-12-12 19:15

    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; }
            }
    
        }
    
    0 讨论(0)
提交回复
热议问题