Seguridad JWT en Web API .NET Core
Seguridad JWT en Web API .NET Core
Utilizamos cookies propias y de terceros para mejorar nuestros servicios y ofrecerle una mejor
experiencia de navegación. Si continúa navegando consideramos que acepta su uso.
Privacidad - Condiciones
1 de 23 08/02/2021 11:23 a. m.
JSON Web Token - Seguridad en servicios Web API de .NET Core https://www.rafaelacosta.net/Blog/2019/5/20/json-web-token-seguridad-...
Seguramente, si has decidido leer este artículo, es porque ya conoces la tecnología JSON
Web Token (JWT en adelante), y lo que te interesa es saber cómo implementar en tus
servicios Web API RESTful este sistema de autenticación de usuarios.
Es por esto que pasaremos directamente a desarrollar desde cero nuestro ejemplo de Web
API RESTful con seguridad JWT en ASP.NET Core.
Nota: Existe infinidad de información en Internet acerca de JWT que puedes consultar
si quieres conocer en profundidad el funcionamiento de este estándar, como por
ejemplo este artículo de Wikipedia (https://es.wikipedia.org/wiki/JSON_Web_Token).
En primer lugar, crearemos un nuevo proyecto del tipo Aplicación Web ASP.NET Core, y
seleccionaremos la plantilla API con plataforma de destino .NET Core y Framework ASP.NET
Core 2.2.
Nota: En el caso de querer compilar la aplicación para Windows (IIS), pueden elegir
como plataforma de destino .NET Framework (Fulll framework). Así mismo, también
pueden utilizar el Framework ASP.NET Core 2.1 si así lo estimaran conveniente.
Utilizamos cookies propias y de terceros para mejorar nuestros servicios y ofrecerle una mejor
experiencia de navegación. Si continúa navegando consideramos que acepta su uso.
Más información (/Blog/Cookies) Acepto
2 de 23 08/02/2021 11:23 a. m.
JSON Web Token - Seguridad en servicios Web API de .NET Core https://www.rafaelacosta.net/Blog/2019/5/20/json-web-token-seguridad-...
El Modelo de datos
Antes de crear nuestro Web API RESTful, debemos definir el Modelo de datos sobre el cual
trabajaremos posteriormente.
Para esto, crearemos una nueva carpeta en el proyecto llamada Models , y en su interior
definiremos una nueva clase llamada Pais.cs de la siguiente manera:
[Key]
public Guid Id { get; set; }
[Required]
[StringLength(50, MinimumLength = 3)]
public string Nombre { get; set; }
[Required]
Utilizamospublic
cookies int
propias y de terceros
Habitantes { para
get;mejorar
set; nuestros
} servicios y ofrecerle una mejor
}
experiencia de navegación. Si continúa navegando consideramos que acepta su uso.
Más información (/Blog/Cookies) Acepto
3 de 23 08/02/2021 11:23 a. m.
JSON Web Token - Seguridad en servicios Web API de .NET Core https://www.rafaelacosta.net/Blog/2019/5/20/json-web-token-seguridad-...
El Controlador de API
En este momento, ya podremos crear la clase controladora para nuestro Web API RESTful.
Pera esto, nos situaremos en la carpeta Controllers del proyecto, y con el botón derecho
del ratón accederemos al menú contextual (opción Agregar > Controlador ...) para crear un
nuevo Controlador del tipo Controlador de API con acciones que usan Entity Framework.
Seleccionando esta plantilla, Visual Studio creará por nosotros (Scaffolding) un Controlador
API RESTful con Acciones CRUD que usan Entity Framework.
Utilizamos cookies propias y de terceros para mejorar nuestros servicios y ofrecerle una mejor
experiencia de navegación. Si continúa navegando consideramos que acepta su uso.
Más información (/Blog/Cookies) Acepto
4 de 23 08/02/2021 11:23 a. m.
JSON Web Token - Seguridad en servicios Web API de .NET Core https://www.rafaelacosta.net/Blog/2019/5/20/json-web-token-seguridad-...
Utilizamos cookies propias y de terceros para mejorar nuestros servicios y ofrecerle una mejor
experiencia de navegación. Si continúa navegando consideramos que acepta su uso.
Más información (/Blog/Cookies) Acepto
5 de 23 08/02/2021 11:23 a. m.
JSON Web Token - Seguridad en servicios Web API de .NET Core https://www.rafaelacosta.net/Blog/2019/5/20/json-web-token-seguridad-...
[Route("api/[controller]")]
[ApiController]
public class PaisController : ControllerBase
{
private readonly ApplicationDbContext _context;
// GET: api/Pais
[HttpGet]
public async Task<ActionResult<IEnumerable<Pais>>> GetPais()
{
return await _context.Pais.ToListAsync();
}
// GET: api/Pais/5
[HttpGet("{id}")]
public async Task<ActionResult<Pais>> GetPais(Guid id)
{
var pais = await _context.Pais.FindAsync(id);
if (pais == null)
{
return NotFound();
}
return pais;
}
// PUT: api/Pais/5
[HttpPut("{id}")]
public async Task<IActionResult> PutPais(Guid id, Pais pais)
{
if (id != pais.Id)
{
return BadRequest();
}
_context.Entry(pais).State = EntityState.Modified;
try
Utilizamos cookies
{ propias y de terceros para mejorar nuestros servicios y ofrecerle una mejor
await _context.SaveChangesAsync();
experiencia de navegación. Si continúa navegando consideramos que acepta su uso.
Más información (/Blog/Cookies) Acepto
6 de 23 08/02/2021 11:23 a. m.
JSON Web Token - Seguridad en servicios Web API de .NET Core https://www.rafaelacosta.net/Blog/2019/5/20/json-web-token-seguridad-...
}
catch (DbUpdateConcurrencyException)
{
if (!PaisExists(id))
{
return NotFound();
}
else
{
throw;
}
}
return NoContent();
}
// POST: api/Pais
[HttpPost]
public async Task<ActionResult<Pais>> PostPais(Pais pais)
{
_context.Pais.Add(pais);
await _context.SaveChangesAsync();
// DELETE: api/Pais/5
[HttpDelete("{id}")]
public async Task<ActionResult<Pais>> DeletePais(Guid id)
{
var pais = await _context.Pais.FindAsync(id);
if (pais == null)
{
return NotFound();
}
_context.Pais.Remove(pais);
await _context.SaveChangesAsync();
return pais;
}
7 de 23 08/02/2021 11:23 a. m.
JSON Web Token - Seguridad en servicios Web API de .NET Core https://www.rafaelacosta.net/Blog/2019/5/20/json-web-token-seguridad-...
"ConnectionStrings": {
"ApplicationDbContext": "Server=(localdb)\\mssqllocaldb;
Database=ApplicationDbContext-2dfbdd2b-470c-4bd4-99fe
Trusted_Connection=True;
MultipleActiveResultSets=true"
}
...
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("ApplicationDbContex
}
...
Llegados a este
Utilizamos punto,
cookies solo faltaría
propias crear nuestra
y de terceros Basenuestros
para mejorar de Datos y comenzar
servicios a implementar
y ofrecerle una mejorla
seguridadexperiencia
JWT, perode antes,
navegación. Si continúa
crearemos navegando
una serie consideramos
de datos de prueba que
queacepta
serán su uso.
insertados
en la tabla de Países a la horaMásde crear la base
información de datos. Acepto
(/Blog/Cookies)
8 de 23 08/02/2021 11:23 a. m.
JSON Web Token - Seguridad en servicios Web API de .NET Core https://www.rafaelacosta.net/Blog/2019/5/20/json-web-token-seguridad-...
Ahora ya podemos crear nuestra base de datos, y esto lo haremos a través de Migraciones
de Entity Framework Core (Code First (https://docs.microsoft.com/es-es/ef/core/get-started
/aspnetcore/new-db?tabs=visual-studio)).
PM> Update-Database
Si todo ha ido bien, ya tendremos creada la base de datos y la tabla de países con los datos
de prueba.
Para probar el correcto funcionamiento del Web API, podemos realizar una petición GET
Utilizamos cookies propias y de terceros para mejorar nuestros servicios y ofrecerle una mejor
desde nuestro explorador (/api/pais), obteniendo el siguiente resultado:
experiencia de navegación. Si continúa navegando consideramos que acepta su uso.
Más información (/Blog/Cookies) Acepto
9 de 23 08/02/2021 11:23 a. m.
JSON Web Token - Seguridad en servicios Web API de .NET Core https://www.rafaelacosta.net/Blog/2019/5/20/json-web-token-seguridad-...
Para ello, "decoraremos" las Acciones del Controlador que requieran seguridad con el
atributo [Authorize] . Esto hará que de momento, las peticiones dirigidas a los elementos
afectados (Acciones) retornen un HTTP 401 Unauthorized (acceso no autorizado).
...
// GET: api/Pais
[HttpGet]
[Authorize] // SOLO USUARIOS AUTENTICADOS
public async Task<ActionResult<IEnumerable<Pais>>> GetPais()
{
return await _context.Pais.ToListAsync();
}
...
Issuer: Debe indicar quien es un emisor válido para el Token. Normalmente indicaremos el
Dominio desde el cual se emite el Token.
Audience: Debe indicar la audiencia o destinatario a los que se dirige el Token. En nuestro
caso indicaremos la Url de nuestro Web API.
ClaveSecreta: Obviamente
Utilizamos cookies propias es el terceros
y de parámetro parademejorar
configuración
nuestrosmás importante,
servicios ya que
y ofrecerle unaserá la
mejor
Clave que utilizaremos
experiencia tanto paraSi
de navegación. firmar digitalmente
continúa navegandoel Token al enviarlo,
consideramos que como
aceptapara
su uso.
comprobar la validez de la firma al recibirlo.(/Blog/Cookies) Acepto
Más información
10 de 23 08/02/2021 11:23 a. m.
JSON Web Token - Seguridad en servicios Web API de .NET Core https://www.rafaelacosta.net/Blog/2019/5/20/json-web-token-seguridad-...
{
...
"JWT": {
"ClaveSecreta": "OLAh6Yh5KwNFvOqgltw7",
"Issuer": "www.rafaelacosta.net",
"Audience": "www.rafaelacosta.net/api/miwebapi"
}
}
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString(
}
Utilizamos
Una cookies propias
vez configurado y dede
el servicio terceros para mejorar
autenticación JWT, nuestros
debemosservicios
añadir ely ofrecerle
Middlewareuna de
mejor
experiencia
autenticación de navegación.
de ASP.NET Core ( Si continúa navegando consideramos
app.UseAuthentication() quede
) al Pipeline acepta su uso. para
la aplicación
Más información (/Blog/Cookies) Acepto
que vigile las peticiones entrantes.
11 de 23 08/02/2021 11:23 a. m.
JSON Web Token - Seguridad en servicios Web API de .NET Core https://www.rafaelacosta.net/Blog/2019/5/20/json-web-token-seguridad-...
app.UseHttpsRedirection();
app.UseMvc();
}
También necesitamos crear una clase de Modelo UsuarioLogin.cs , que represente las
credenciales de acceso de un usuario determinado. En nuestro caso definiremos las
propiedades Usuario y Password.
Utilizamos cookies propias y de terceros para mejorar nuestros servicios y ofrecerle una mejor
experiencia de navegación. Si continúa navegando consideramos que acepta su uso.
Más información (/Blog/Cookies) Acepto
12 de 23 08/02/2021 11:23 a. m.
JSON Web Token - Seguridad en servicios Web API de .NET Core https://www.rafaelacosta.net/Blog/2019/5/20/json-web-token-seguridad-...
Utilizamos cookies propias y de terceros para mejorar nuestros servicios y ofrecerle una mejor
experiencia de navegación. Si continúa navegando consideramos que acepta su uso.
Más información (/Blog/Cookies) Acepto
13 de 23 08/02/2021 11:23 a. m.
JSON Web Token - Seguridad en servicios Web API de .NET Core https://www.rafaelacosta.net/Blog/2019/5/20/json-web-token-seguridad-...
[Route("api/[controller]")]
[ApiController]
public class LoginController : ControllerBase
{
private readonly IConfiguration configuration;
// POST: api/Login
[HttpPost]
[AllowAnonymous]
public async Task<IActionResult> Login(UsuarioLogin usuarioLogin)
{
var _userInfo = await AutenticarUsuarioAsync(usuarioLogin.Usuario
if (_userInfo != null)
{
return Ok(new { token = GenerarTokenJWT(_userInfo) });
}
else
{
return Unauthorized();
}
}
14 de 23 08/02/2021 11:23 a. m.
JSON Web Token - Seguridad en servicios Web API de .NET Core https://www.rafaelacosta.net/Blog/2019/5/20/json-web-token-seguridad-...
// CREAMOS EL PAYLOAD //
var _Payload = new JwtPayload(
issuer: configuration["JWT:Issuer"],
audience: configuration["JWT:Audience"],
claims: _Claims,
notBefore: DateTime.UtcNow,
// Exipra a la 24 horas.
expires: DateTime.UtcNow.AddHours(24)
);
// GENERAMOS EL TOKEN //
var _Token = new JwtSecurityToken(
_Header,
_Payload
);
15 de 23 08/02/2021 11:23 a. m.
JSON Web Token - Seguridad en servicios Web API de .NET Core https://www.rafaelacosta.net/Blog/2019/5/20/json-web-token-seguridad-...
Una vez que el usuario autenticado haya recibido el Token de acceso, ya podrá acceder con
total seguridad a aquellas Acciones de nuestro Web API que hayan sido protegidas con el
atributo [Authorize] .
Este Token recibido, nos identificará como usuario autenticado en las sucesivas peticiones
que realicemos al servicio Web API, sin necesidad de volvernos a validar en el sistema de
información. Simplemente debemos indicar en la cabecera (Header) de las peticiones HTTP
al Web API, un encabezado Authorization: del tipo bearer con el valor del Token obtenido.
Utilizamos cookies propias y de terceros para mejorar nuestros servicios y ofrecerle una mejor
experiencia de navegación. Si continúa navegando consideramos que acepta su uso.
Más información (/Blog/Cookies) Acepto
16 de 23 08/02/2021 11:23 a. m.
JSON Web Token - Seguridad en servicios Web API de .NET Core https://www.rafaelacosta.net/Blog/2019/5/20/json-web-token-seguridad-...
Por lo tanto, y como requisito inicial, debemos solicitar un Token JWT válido accediendo al
recurso POST: api/Login .
17 de 23 08/02/2021 11:23 a. m.
JSON Web Token - Seguridad en servicios Web API de .NET Core https://www.rafaelacosta.net/Blog/2019/5/20/json-web-token-seguridad-...
En primer lugar crearemos una nueva petición del tipo GET al recurso GET: api/Pais .
Utilizamos cookies propias y de terceros para mejorar nuestros servicios y ofrecerle una mejor
experiencia de navegación. Si continúa navegando consideramos que acepta su uso.
Más información (/Blog/Cookies) Acepto
18 de 23 08/02/2021 11:23 a. m.
JSON Web Token - Seguridad en servicios Web API de .NET Core https://www.rafaelacosta.net/Blog/2019/5/20/json-web-token-seguridad-...
Por ultimo enviaremos la petición al servidor, y veremos como recibimos una respuesta HTTP
200 Ok, con el contenido de los registros de la base de datos en formato JSON.
Utilizamos cookies propias y de terceros para mejorar nuestros servicios y ofrecerle una mejor
experiencia de navegación. Si continúa navegando consideramos que acepta su uso.
Más información (/Blog/Cookies) Acepto
19 de 23 08/02/2021 11:23 a. m.
JSON Web Token - Seguridad en servicios Web API de .NET Core https://www.rafaelacosta.net/Blog/2019/5/20/json-web-token-seguridad-...
Importante: Los Tokens JWT caducan, esto quiere decir que a la hora de generarlos,
podemos indicar un tiempo de validez mediante el parámetro expires: de la
clase JwtPayload() . Por esta razón debemos estar atentos a las respuestas HTTP 401
(acceso no autorizado) del Web API, para volver a solicitar un nuevo Token si fuera
necesario.
A continuación, crearíamos en el cuerpo (Body) de la petición, el nuevo objeto JSON del tipo
Pais.cs que queremos enviar al servidor para ser insertado en la base de datos.
Por último, enviaremos la petición al servidor, y veremos como recibimos una respuesta HTTP
201 Created con el nuevo objeto creado en la base de datos.
Utilizamos cookies propias y de terceros para mejorar nuestros servicios y ofrecerle una mejor
experiencia de navegación. Si continúa navegando consideramos que acepta su uso.
Más información (/Blog/Cookies) Acepto
20 de 23 08/02/2021 11:23 a. m.
JSON Web Token - Seguridad en servicios Web API de .NET Core https://www.rafaelacosta.net/Blog/2019/5/20/json-web-token-seguridad-...
Compartir
Facebook Twitter Más... 1
(https://es.stackoverflow.com/users/139993/rafael-acosta)
Etiquetas
.NET Core (/?tag=.NET%20Core) .NET Framework (/?tag=.NET%20Framework) .NET MVC
Utilizamos cookies propias y de terceros para mejorar nuestros servicios y ofrecerle una mejor
experiencia de navegación. Si continúa navegando consideramos que acepta su uso.
Nuevos Más información (/Blog/Cookies) Acepto
21 de 23 08/02/2021 11:23 a. m.
JSON Web Token - Seguridad en servicios Web API de .NET Core https://www.rafaelacosta.net/Blog/2019/5/20/json-web-token-seguridad-...
Populares
Cómo subir archivos al servidor en una aplicación ASP.NET MVC (/Blog/2018/7
/30/c%C3%B3mo-subir-archivos-al-servidor-en-una-aplicaci%C3%B3n-aspnet-mvc)
Utilizamos cookies propias y de terceros para mejorar nuestros servicios y ofrecerle una mejor
experiencia de navegación. Si continúa navegando consideramos que acepta su uso.
Más información (/Blog/Cookies) Acepto
22 de 23 08/02/2021 11:23 a. m.
JSON Web Token - Seguridad en servicios Web API de .NET Core https://www.rafaelacosta.net/Blog/2019/5/20/json-web-token-seguridad-...
Utilizamos cookies propias y de terceros para mejorar nuestros servicios y ofrecerle una mejor
experiencia de navegación. Si continúa navegando consideramos que acepta su uso.
Más información (/Blog/Cookies) Acepto
23 de 23 08/02/2021 11:23 a. m.