ASP.NET Core 3.1 - CRUD : Web API com EF Core e Tokens JWT


Hoje teremos um roteiro básico para criar Web APIs para realizar o CRUD com ASP .NET Core 3.1 e EF Core usando Tokens JWT.

Continuando a terceira parte do artigo vamos iniciar a implementação da segurança em nossa API gerando o token JWT.

Implementando a segurança : Criando o token JWT

Do jeito que esta qualquer um pode acessar a nossa Web API, basta conhecer o endpoint (api/produtos) para poder realizar todas as operações.

Vamos então implementar a segurança iniciando com a criação do token JWT, e, para fazer isso vamos seguir o  roteiro abaixo:

Vamos iniciar definindo no arquivo appsettings.json do projeto a configuração Jwt para poder gerar o token:

{
  "ConnectionStrings": {
    "DefaultConnection": "Data Source=Macoratti;Initial Catalog=InventarioDB;Integrated Security=True"
  },
  "Jwt": {
    "Key": "lkdjfp753243çlkjadfs%$#%$#$PloIu$3@fgJu",
    "Issuer": "InventarioNeTAuthenticationServer",
    "Audience": "InventarioNeTPostmanClient",
    "Subject": "InventarioNeTAcessToken"
  },
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information"
    }
  },
  "AllowedHosts": "*"
}

Na seção Jwt temos a chave secreta, uma chave privada, definida em Key será usada para poder gerar o Token e vamos ter que acessar este arquivo para obter este valor que somente a nossa aplicação conhece.

A seguir vamos criar o controlador TokenController na pasta Controllers com o seguinte código:

using InventarioNET.Models;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.IdentityModel.Tokens;
using System;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Text;
using System.Threading.Tasks;
namespace InventarioNET.Controllers
{
    [Route("api/[controller]")]
    [ApiController]
    public class TokenController : Controller
    {
        public IConfiguration _configuration;
        private readonly AppDbContext _context;
        public TokenController(IConfiguration config, AppDbContext context)
        {
            _configuration = config;
            _context = context;
        }
        [HttpPost]
        public async Task<IActionResult> AutenticaUsuario(Usuario _usuario)
        {
            if (_usuario != null && _usuario.Email != null && _usuario.Senha != null)
            {
                var usuario = await GetUsuario(_usuario.Email, _usuario.Senha);
                if (usuario != null)
                {
                    //cria claims baseado nas informações do usuário
                    var claims = new[] {
                    new Claim(JwtRegisteredClaimNames.Sub, _configuration["Jwt:Subject"]),
                    new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()),
                    new Claim(JwtRegisteredClaimNames.Iat, DateTime.UtcNow.ToString()),
                    new Claim("Id", usuario.UsuarioId.ToString()),
                    new Claim("Nome", usuario.Nome),
                    new Claim("Login", usuario.Login),
                    new Claim("Email", usuario.Email)
                   };
                    var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_configuration["Jwt:Key"]));
                    var signIn = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
                    var token = new JwtSecurityToken(_configuration["Jwt:Issuer"],
                                 _configuration["Jwt:Audience"], claims,
                                 expires: DateTime.UtcNow.AddDays(1), signingCredentials: signIn);
                    return Ok(new JwtSecurityTokenHandler().WriteToken(token));
                }
                else
                {
                    return BadRequest("Credenciais inválidas");
                }
            }
            else
            {
                return BadRequest();
            }
        }
        private async Task<Usuario> GetUsuario(string email, string password)
        {
            return await _context.Usuarios.FirstOrDefaultAsync(u => u.Email == email && u.Senha == password);
        }
    }
}

No método AutenticaUsuario, após verificar as credenciais do usuário, realizamos as seguintes operações:

Observe que ao gerar a chave usando a criptografia simétrica estamos obtendo uma chave JWT:key do arquivo de configuração appsettings.json.

Note que definimos um tempo de expiração(expires) do token de 1 dia. Você pode alterar para um tempo menor se desejar.

Nota: Se você quiser pode definir neste controlador um método para Registro e Login do usuário e na autenticação realizar a geração do token como eu já mostrei neste artigo: ASP .NET Core - Implementando e consumindo JWT

Testando a geração do Token via Postman

Vamos executar o projeto e a seguir abrir o Postman e definir uma requisição POST passando o Email e a Senha do usuário que cadastramos na tabela Usuarios:

Pronto, vemos o Token gerado no response ao nosso POST.

Para verificar se o token é válido vamos acessar o site https://jwt.io/ e copiar este token gerado para validar a assinatura:

Observe que precisamos informar a chave secreta definida pela chave Key no arquivo appsettings.json para validar a assinatura.

Agora que já podemos gerar um Token de autenticação no próximo artigo vamos implementar a autenticação via token Jwt ou bearer authentication em nossa aplicação.

"Não vos prendais a um jugo desigual com os infiéis; porque, que sociedade tem a justiça com a injustiça? E que comunhão tem a luz com as trevas?"
2 Coríntios 6:14

Referências:


José Carlos Macoratti