Olá, Renato!
Entendo sua preocupação em relação ao uso do JWT de forma que ele seja autocontido, evitando consultas adicionais ao banco de dados para verificar as permissões do usuário. Você está correto ao dizer que um dos propósitos do JWT é carregar informações suficientes para que o servidor possa validar o usuário e suas permissões sem a necessidade de consultas adicionais.
Uma alternativa para tornar o token mais autocontido seria incluir as permissões do usuário (roles ou claims) diretamente no token durante o processo de autenticação. Isso poderia ser feito modificando o serviço que gera o token para incluir essas informações. Aqui está um exemplo de como você poderia modificar a geração do token para incluir as permissões do usuário:
public String gerarToken(Usuario usuario) {
try {
var algoritmo = Algorithm.HMAC256(secret);
return JWT.create()
.withIssuer("API Voll.med")
.withSubject(usuario.getLogin())
.withExpiresAt(dataExpiracao())
.claim("authorities", usuario.getAuthorities().stream().map(authority -> new SimpleGrantedAuthority(authority.getAuthority())).collect(Collectors.toList()))
.sign(algoritmo);
} catch (JWTCreationException exception){
throw new RuntimeException("erro ao gerar token jwt", exception);
}
}
E então, no filtro de segurança, você poderia extrair essas permissões diretamente do token, sem a necessidade de consultar o banco de dados:
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
var token = recuperarToken(request);
if (token != null && tokenService.validateToken(token)) {
var claims = tokenService.getAllClaimsFromToken(token);
var authorities = claims.get("authorities", List.class);
var authentication = new UsernamePasswordAuthenticationToken(claims.getSubject(), null, authorities);
SecurityContextHolder.getContext().setAuthentication(authentication);
}
filterChain.doFilter(request, response);
}
Essas mudanças ajudariam a tornar o uso do JWT mais alinhado com sua função de ser autocontido, reduzindo a dependência de consultas ao banco de dados para cada requisição.
É importante reconhecer o trade-off envolvido nessa abordagem. Ao incluir as permissões do usuário diretamente no token JWT durante o processo de autenticação, você está tornando o token mais autocontido e reduzindo a necessidade de consultas adicionais ao banco de dados a cada requisição. Isso pode levar a uma melhoria significativa no desempenho e escalabilidade do sistema, especialmente em cenários de alta concorrência e grande volume de requisições.
No entanto, como você mencionou, uma das consequências desse método é que o token JWT mantém as permissões do usuário até sua expiração, mesmo que essas permissões sejam alteradas no banco de dados antes disso. Isso significa que o token pode não refletir imediatamente as permissões atualizadas do usuário.
Essa falta de sincronização em tempo real entre as permissões do usuário no banco de dados e as permissões contidas no token pode ser considerada um trade-off em relação à consistência em tempo real dos dados de permissão. Dependendo dos requisitos de segurança e da natureza das permissões do sistema, essa falta de sincronização pode ou não ser um problema significativo.
Espero ter ajudado e bons estudos!