route query attribute c# security session asp.net-mvc-5 asp.net-web-api2

c# - query - Dónde almacenar el token de portador en MVC desde la API web



web api query string parameters (2)

Screnario

Tengo una API web ASP.NET que usa el flujo de contraseña OAuth para proporcionar tokens de portador para obtener acceso a sus recursos.

Ahora estoy en el proceso de crear una aplicación MVC que necesitará usar esta API.

El plan es hacer que los controladores MVC realicen llamadas a la API en nombre del navegador del cliente.

Las solicitudes ajax del navegador golpearán los controladores MVC y luego se realizarán las llamadas API. Los resultados luego son retroalimentados al cliente como JSON y manejados en java-script.

El cliente nunca debe comunicarse directamente con la API.

Autenticarse.

Necesito determinar la mejor manera de manejar el token de portador una vez que se haya recibido en la aplicación MVC a través de una llamada exitosa al punto final del token API.

Necesito usar este token de portador en cualquier llamada posterior a la API.

Mi plan es almacenarlo en System.Web.HttpContext.Current.Session["BearerToken"]

Luego puedo crear un AuthorizationAttribute personalizado que verificará si un BearerToken está presente en el HttpContext actual, si no está presente, el cliente deberá volver a visitar el enken point.

¿Esto parece factible?

Estoy pidiendo la opinión de la gente sobre esto ya que no estoy convencido de que sea la mejor solución para mi proyecto.


Como ha mencionado, está utilizando HttpClient (). Hice algo similar usando HttpClient () -

Obtener 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; }

Usa el token para publicar datos

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

Incluso si almacena el token de portador en HttpContext, deberá ocuparse del tiempo de caducidad del token configurado en la API web. Validar la existencia del token solo en la sesión no ayudará ya que el token antiguo no será válido después del tiempo de caducidad.


He logrado encontrar algo que creo que funcionará bastante bien.

Estoy usando el Owin Middleware para Autenticación de cookies.

Dentro de la aplicación MVC tengo un archivo de inicio Owin donde está configurada la autenticación de cookies: -

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

Luego creé un AccountController con dos métodos de Acción para iniciar y cerrar sesión: -

Iniciar sesión.

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

Saliendo de tu cuenta

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

Protegiendo los recursos

[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; } } }