.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.
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.