← todos os artigos

.NET

JWT e Microsoft Identity: como eu entendo a diferença

Eu ficava tratando JWT e Microsoft Identity como escolhas concorrentes. Não são. Um é a bilheteria confirmando quem você é, o outro é a pulseira provando isso em cada brinquedo depois.

JWT e Microsoft Identity: como eu entendo a diferença

Eu ficava tratando JWT e Microsoft Identity como se fossem escolhas concorrentes, como se a pergunta fosse "devo usar Identity ou devo usar JWT". Essa é a pergunta errada. Eles fazem trabalhos diferentes, e na maioria das APIs que eu construo, eles trabalham juntos em vez de um contra o outro.

A versão do parque de diversões

O jeito que isso finalmente fez sentido para mim: pense em construir um sistema para um parque de diversões.

O Microsoft Identity é o database e a bilheteria. Ele lida com quem você é e o que a sua conta contém, as tabelas de usuários, senhas com hash, roles, e claims. É a peça que responde "registrar um novo usuário", "checar se essa senha está correta", ou "travar a conta depois de cinco tentativas de login falhas".

Um JWT é a pulseira. É só um formato para um badge assinado. Assim que a bilheteria verifica quem você é, ela imprime uma pulseira assinada criptograficamente, a string do JWT, e entrega. Você usa essa pulseira em cada brinquedo depois. O operador do brinquedo não liga para a bilheteria toda vez, ele só checa se a pulseira tem uma assinatura válida e deixa você passar.

O que isso mapeia no código

Um request de login vai para o Identity primeiro. Ele encontra o usuário, verifica o hash da senha, e só então o token é criado:

[HttpPost("login")]
public async Task<IActionResult> Login(LoginRequest request)
{
    // Microsoft Identity: the ticket booth
    var user = await _userManager.FindByEmailAsync(request.Email);

    if (user is null || !await _userManager.CheckPasswordAsync(user, request.Password))
    {
        return Unauthorized();
    }

    // JWT: the wristband
    var token = _tokenService.CreateToken(user);
    return Ok(new { accessToken = token });
}

_userManager é o Identity, conversando com o database. _tokenService só empacota as claims que o Identity já confirmou e assina elas.

Esse token volta para o cliente, e todo request depois disso carrega ele no header Authorization em vez do usuário e senha. O middleware que checa isso nunca toca no Identity:

builder.Services
    .AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
    .AddJwtBearer(options =>
    {
        options.TokenValidationParameters = new TokenValidationParameters
        {
            ValidateIssuerSigningKey = true,
            IssuerSigningKey = new SymmetricSecurityKey(key),
            ValidateLifetime = true
        };
    });

Assinatura e expiração, só isso. Nenhuma chamada ao database em todo request que vem depois.

De onde veio a confusão

Acho que misturei os dois porque os dois termos aparecem nas mesmas conversas sobre authentication, então é fácil assumir que são duas opções para o mesmo problema. Assim que passei a ver eles como duas camadas diferentes, a bilheteria confirmando quem você é, e a pulseira provando isso em cada brinquedo depois, a confusão se resolveu.