Autenticación basada en tokens en la API web sin ninguna interfaz de usuario

Estoy desarrollando una API REST en ASP.Net Web API. Mi API solo será accesible a través de clientes que no estén basados ​​en el navegador. Necesito implementar seguridad para mi API así que decidí ir con la autenticación basada en Token. Tengo una buena comprensión de la autenticación basada en tokens y he leído algunos tutoriales, pero todos tienen alguna interfaz de usuario para iniciar sesión. No necesito ninguna IU para iniciar sesión, ya que el cliente pasará los datos de inicio de sesión a través de HTTP POST, que se autorizará desde nuestra base de datos. ¿Cómo puedo implementar la autenticación basada en tokens en mi API? Tenga en cuenta que se accederá a mi API en alta frecuencia, así que también debo cuidar el rendimiento. Por favor, avíseme si puedo explicarlo mejor.

Creo que hay cierta confusión sobre la diferencia entre MVC y Web Api. En resumen, para MVC puede usar un formulario de inicio de sesión y crear una sesión utilizando cookies. Para Web Api no hay sesión. Es por eso que quieres usar el token.

No necesita un formulario de inicio de sesión. El punto final Token es todo lo que necesitas. Al igual que Win describió, enviará las credenciales al extremo del token donde se maneja.

Aquí hay un código C # del lado del cliente para obtener un token:

//using System; //using System.Collections.Generic; //using System.Net; //using System.Net.Http; //string token = GetToken("https://localhost:/", userName, password); static string GetToken(string url, string userName, string password) { var pairs = new List> { new KeyValuePair( "grant_type", "password" ), new KeyValuePair( "username", userName ), new KeyValuePair ( "Password", password ) }; var content = new FormUrlEncodedContent(pairs); ServicePointManager.ServerCertificateValidationCallback += (sender, cert, chain, sslPolicyErrors) => true; using (var client = new HttpClient()) { var response = client.PostAsync(url + "Token", content).Result; return response.Content.ReadAsStringAsync().Result; } } 

Para usar el token, agréguelo al encabezado de la solicitud:

  //using System; //using System.Collections.Generic; //using System.Net; //using System.Net.Http; //var result = CallApi("https://localhost:/something", token); static string CallApi(string url, string token) { ServicePointManager.ServerCertificateValidationCallback += (sender, cert, chain, sslPolicyErrors) => true; using (var client = new HttpClient()) { if (!string.IsNullOrWhiteSpace(token)) { var t = JsonConvert.DeserializeObject(token); client.DefaultRequestHeaders.Clear(); client.DefaultRequestHeaders.Add("Authorization", "Bearer " + t.access_token); } var response = client.GetAsync(url).Result; return response.Content.ReadAsStringAsync().Result; } } 

Donde Token es:

 //using Newtonsoft.Json; class Token { public string access_token { get; set; } public string token_type { get; set; } public int expires_in { get; set; } public string userName { get; set; } [JsonProperty(".issued")] public string issued { get; set; } [JsonProperty(".expires")] public string expires { get; set; } } 

Ahora para el lado del servidor:

En Startup.Auth.cs

  var oAuthOptions = new OAuthAuthorizationServerOptions { TokenEndpointPath = new PathString("/Token"), Provider = new ApplicationOAuthProvider("self"), AccessTokenExpireTimeSpan = TimeSpan.FromDays(14), // https AllowInsecureHttp = false }; // Enable the application to use bearer tokens to authenticate users app.UseOAuthBearerTokens(oAuthOptions); 

Y en ApplicationOAuthProvider.cs el código que otorga o niega el acceso:

 //using Microsoft.AspNet.Identity.Owin; //using Microsoft.Owin.Security; //using Microsoft.Owin.Security.OAuth; //using System; //using System.Collections.Generic; //using System.Security.Claims; //using System.Threading.Tasks; public class ApplicationOAuthProvider : OAuthAuthorizationServerProvider { private readonly string _publicClientId; public ApplicationOAuthProvider(string publicClientId) { if (publicClientId == null) throw new ArgumentNullException("publicClientId"); _publicClientId = publicClientId; } public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context) { var userManager = context.OwinContext.GetUserManager(); var user = await userManager.FindAsync(context.UserName, context.Password); if (user == null) { context.SetError("invalid_grant", "The user name or password is incorrect."); return; } ClaimsIdentity oAuthIdentity = await user.GenerateUserIdentityAsync(userManager); var propertyDictionary = new Dictionary { { "userName", user.UserName } }; var properties = new AuthenticationProperties(propertyDictionary); AuthenticationTicket ticket = new AuthenticationTicket(oAuthIdentity, properties); // Token is validated. context.Validated(ticket); } public override Task TokenEndpoint(OAuthTokenEndpointContext context) { foreach (KeyValuePair property in context.Properties.Dictionary) { context.AdditionalResponseParameters.Add(property.Key, property.Value); } return Task.FromResult(null); } public override Task ValidateClientAuthentication(OAuthValidateClientAuthenticationContext context) { // Resource owner password credentials does not provide a client ID. if (context.ClientId == null) context.Validated(); return Task.FromResult(null); } public override Task ValidateClientRedirectUri(OAuthValidateClientRedirectUriContext context) { if (context.ClientId == _publicClientId) { var expectedRootUri = new Uri(context.Request.Uri, "/"); if (expectedRootUri.AbsoluteUri == context.RedirectUri) context.Validated(); } return Task.FromResult(null); } } 

Como puede ver, no hay un controlador involucrado en recuperar el token. De hecho, puede eliminar todas las referencias de MVC si solo desea una API web. He simplificado el código del lado del servidor para hacerlo más legible. Puede agregar código para actualizar la seguridad.

Asegúrate de usar solo SSL. Implemente RequireHttpsAttribute para forzar esto.

Puede usar los atributos Autorizar / PermitirAnónimo para proteger su API web. Además, puede agregar filtros (como RequireHttpsAttribute) para que su API web sea más segura. Espero que esto ayude.

ASP.Net Web API ya tiene incorporado el servidor de autorización. Puede verlo dentro de Startup.cs cuando crea una nueva aplicación web ASP.Net con la plantilla de API web.

 OAuthOptions = new OAuthAuthorizationServerOptions { TokenEndpointPath = new PathString("/Token"), Provider = new ApplicationOAuthProvider(PublicClientId), AuthorizeEndpointPath = new PathString("/api/Account/ExternalLogin"), AccessTokenExpireTimeSpan = TimeSpan.FromDays(14), // In production mode set AllowInsecureHttp = false AllowInsecureHttp = true }; 

Todo lo que tienes que hacer es publicar el nombre de usuario y la contraseña codificados en la URL dentro de la cadena de consulta.

 /Token/userName=johndoe%40example.com&password=1234&grant_type=password 

Si desea conocer más detalles, puede ver el registro de usuario y el inicio de sesión: angular de adelante hacia atrás con la API web de Deborah Kurata .