Módulo 4 · APIs e sua Arquitetura — Capítulo 04

Autenticação e Autorização (JWT)

A diferença entre "quem você é" e "o que você pode fazer" — e como JWT carrega essa informação de forma stateless entre requisições.

1. Autenticação vs. autorização

AutenticaçãoAutorização
Pergunta que respondeQuem é você?O que você pode fazer?
Quando aconteceUma vez, no loginA cada requisição, para cada recurso
Falha típica401 Unauthorized403 Forbidden

2. JWT — carregando identidade sem guardar sessão no servidor

Lembrando o capítulo 1 (APIs são stateless): o servidor não guarda "quem está logado" em memória entre requisições. Um JWT (JSON Web Token) resolve isso — é um token assinado digitalmente que carrega a identidade do usuário dentro dele mesmo, verificável sem consultar um banco a cada requisição.

Header algoritmo, tipo Payload Id, nome, roles, expiração Signature prova que não foi alterado

Fig. 1 — Um JWT é as três partes separadas por ponto: header.payload.signature — só o servidor consegue gerar uma assinatura válida.

Nota

O payload de um JWT é legível por qualquer um (é só Base64, não criptografia) — a assinatura garante apenas que ele não foi alterado depois de emitido. Nunca coloque dados sensíveis (senha, número de cartão) dentro do payload.

3. Gerando um token no login

C# gerando um JWT
public string GerarToken(Cliente cliente)
{
    var claims = new List<Claim>
    {
        new(ClaimTypes.NameIdentifier, cliente.Id.ToString()),
        new(ClaimTypes.Name, cliente.Nome),
        new(ClaimTypes.Role, "Cliente"),
    };

    var chave = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_chaveSecreta));
    var credenciais = new SigningCredentials(chave, SecurityAlgorithms.HmacSha256);

    var token = new JwtSecurityToken(
        issuer: "MinhaApi",
        audience: "MeusClientes",
        claims: claims,
        expires: DateTime.UtcNow.AddHours(2),
        signingCredentials: credenciais);

    return new JwtSecurityTokenHandler().WriteToken(token);
}

4. Configurando o ASP.NET Core para validar o token

C# Program.cs
builder.Services
    .AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
    .AddJwtBearer(opcoes =>
    {
        opcoes.TokenValidationParameters = new TokenValidationParameters
        {
            ValidateIssuer = true,
            ValidateAudience = true,
            ValidateLifetime = true,
            ValidateIssuerSigningKey = true,
            ValidIssuer = "MinhaApi",
            ValidAudience = "MeusClientes",
            IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(chaveSecreta)),
        };
    });

builder.Services.AddAuthorization();

var app = builder.Build();
app.UseAuthentication(); // quem é você
app.UseAuthorization();  // o que você pode fazer
Atenção — ordem no pipeline

Assim como no Módulo 3 (capítulo 7), UseAuthentication() precisa vir antes de UseAuthorization() no pipeline. Autorização depende de já saber quem é o usuário.

5. Protegendo endpoints com [Authorize]

C# protegendo endpoints e restringindo por role
[ApiController]
[Route("api/clientes")]
[Authorize] // exige token válido para qualquer endpoint deste controller
public class ClienteController : ControllerBase
{
    [HttpGet]
    public async Task<ActionResult> Listar() { ... } // qualquer usuário autenticado

    [HttpDelete("{id:int}")]
    [Authorize(Roles = "Admin")] // só usuários com a role "Admin"
    public async Task<IActionResult> Excluir(int id) { ... }

    [HttpGet("publico")]
    [AllowAnonymous] // exceção — libera mesmo dentro de um controller [Authorize]
    public IActionResult InfoPublica() => Ok("Sem necessidade de login");
}

6. Enviando o token do lado do cliente

C# chamando um endpoint protegido
httpClient.DefaultRequestHeaders.Authorization =
    new AuthenticationHeaderValue("Bearer", tokenRecebidoNoLogin);

var resposta = await httpClient.GetAsync("api/clientes");

O cabeçalho Authorization: Bearer <token> é o padrão universal — o mesmo formato que você usaria em qualquer chamada fetch do JavaScript com um header customizado.

7. Onde isso te leva

Com segurança coberta, o próximo capítulo trata de algo que toda API precisa: documentação viva, que se mantém sincronizada com o código automaticamente através do OpenAPI/Swagger.

📌 Resumo do capítulo

  • Autenticação responde "quem é você" (401 se falhar); autorização responde "o que você pode fazer" (403 se falhar).
  • JWT carrega identidade de forma verificável e stateless — legível por qualquer um, mas à prova de alteração graças à assinatura.
  • UseAuthentication() sempre antes de UseAuthorization() no pipeline.
  • [Authorize], [Authorize(Roles = "...")] e [AllowAnonymous] controlam acesso por endpoint.

✏️ Praticando

  1. Implemente um endpoint POST /api/login que valida usuário/senha (contra a tabela Cliente do Módulo 2) e devolve um JWT.
  2. Proteja o ClienteController da API com [Authorize] e teste chamar um endpoint sem token (deve devolver 401).
  3. Adicione uma role "Admin" e restrinja o endpoint de exclusão a essa role.