Importante

Você está vendo a versão anterior da nova experiência da Alura que estamos preparando para você. Em breve, ela ganha uma identidade visual novinha totalmente pensada em potencializar seus estudos!

17
respostas

Token JWT inválido ou expirado!

Mesmo quando eu refaço o login, está retornando Token JWT inválido ou expirado.![](Insira aqui a descrição dessa imagem para ajudar na acessibilidade )

17 respostas

Oi Gabriel!

Pode ser outro erro que está acontecendo. Coloca um try/catch no controller:

try {
    var authenticationToken = new UsernamePasswordAuthenticationToken(dados.login(), dados.senha());
    var authentication = manager.authenticate(authenticationToken);

    var tokenJWT = tokenService.gerarToken((Usuario) authentication.getPrincipal());

    return ResponseEntity.ok(new DadosTokenJWT(tokenJWT));
} catch(Exception e) {
    e.printStackTrace();
    return ResponseEntity.badRequest().body(e.getMessage());
}

Agora está dando outro erro. Segue prints:

![](Insira aqui a descrição dessa imagem para ajudar na acessibilidade )

![](Insira aqui a descrição dessa imagem para ajudar na acessibilidade )

Insira aqui a descrição dessa imagem para ajudar na acessibilidade

Teu método recuperarToken da classe SecurityFilter está incorreto. Altere o if e o return para ficar igual demonstrado na aula

O retorno de Token inválido agora aparece até na parte de login. Eu tento fazer o login, mas aparece Token inválido, só que nem está retornando um token.

Confere se sua classe SecurityFilter está assim:

@Component
public class SecurityFilter extends OncePerRequestFilter {

    @Autowired
    private TokenService tokenService;

    @Autowired
    private UsuarioRepository repository;

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        var tokenJWT = recuperarToken(request);

        if (tokenJWT != null) {
            var subject = tokenService.getSubject(tokenJWT);
            var usuario = repository.findByLogin(subject);

            var authentication = new UsernamePasswordAuthenticationToken(usuario, null, usuario.getAuthorities());
            SecurityContextHolder.getContext().setAuthentication(authentication);
        }

        filterChain.doFilter(request, response);
    }

    private String recuperarToken(HttpServletRequest request) {
        var authorizationHeader = request.getHeader("Authorization");
        if (authorizationHeader != null) {
            return authorizationHeader.replace("Bearer ", "");
        }

        return null;
    }

}

E a classe SecurityConfigurations está assim:

@Configuration
@EnableWebSecurity
public class SecurityConfigurations {

    @Autowired
    private SecurityFilter securityFilter;

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        return http.csrf().disable()
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                .and().authorizeHttpRequests()
                .requestMatchers(HttpMethod.POST, "/login").permitAll()
                .anyRequest().authenticated()
                .and().addFilterBefore(securityFilter, UsernamePasswordAuthenticationFilter.class)
                .build();
    }

    @Bean
    public AuthenticationManager authenticationManager(AuthenticationConfiguration configuration) throws Exception {
        return configuration.getAuthenticationManager();
    }

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

}

Agora está retornando o seguinte erro:

org.springframework.security.authentication.InternalAuthenticationServiceException: UserDetailsService returned null, which is an interface contract violation

Esse erro somente acontece se não tiver usuário na tabela com o email que você está tentando fazer login.

Boa tarde Prof,

Também estou com o mesmo erro, onde passo o token na minha request, porém sempre caio na Exception "Token JWT Inválido ou Expirado".

Debuggando o código, percebi que ao passar pelo .verify(TokenJWT) do método getSubject(), caio na exceção.

public String getSubject(String tokenJWT) {

        try {
            var algoritmo =  Algorithm.HMAC256(secret);
            return JWT.require(algoritmo)
                    .withIssuer("API Voll.med")
                    .build()
                    .verify(tokenJWT)
                    .getSubject();

        } catch (JWTVerificationException exception) {
            throw new RuntimeException("Token JWT inválido ou expirado!");
        }

Debugging

Pesquisei o que pode ser, mas ainda não cheguei numa solução definitiva.

Oi Juan!

No seu caso é o token que está inválido mesmo. No segundo print aparece a String e ela está muito grande para ser um token :D

Confere isso

Professor estou com o mesmo problema, estou utilizando o token gerado pela própria API.

Coloquem um try/catch no controller para saber qual exception de fato está ocorrendo:

try {
    var authenticationToken = new UsernamePasswordAuthenticationToken(autenticacao.login(), autenticacao.senha());
    var authentication = authenticationManager.authenticate(authenticationToken);
} catch (Exception e) {
    e.printStackTrace();
}
return ResponseEntity.status(HttpStatus.OK).build();

No meu caso o erro era a string no .withIssuer("String") dos métodos gerarToken() e getSubject() que estavam diferentes, por isso estava caindo no exception, depois que deixei elas iguais voltou a funcionar..

Pessoal, bom dia!

A demonstração do Rodrigo é excelente, mas para nos tornamos ótimos desenvolvedores precisamos aprender a debugar, pois é o que faremos no dia a dia.

No meu caso estava apresentando o mesmo erro reportado acima: Token JWT inválido ou expirado

Porem usando debug voce consegue ve a exception que ele lançou:

debug

Mas tenho a exception, mas e agora? Agora é o ponto de se analisar, ele esta reclamando que a assinatura do token é invalida e diferente da usada no HMAC256, então vem o "estalo" de olhar onde gerei o token, porque la foi onde eu passei a criptografia que ele iria usar.

E "voala" kkkk

No meu codigo esta gerando o token com o secret usando uma String e na hora de verificar esta usando o meu secrete que pega do properties.

Insira aqui a descrição dessa imagem para ajudar na acessibilidade

Provavelmente o de voces está desse mesmo jeito, dê uma olhada. Abraço, espero te ajudado.

Boa noite, mesmo fazendo este passo a passo, continua dando erro e tudo está igual.

Se postou se codigo no git envia aqui o link.

No meu caso, era algo bem simples. Estava sem o espaço após o Bearer no método recuperarToken:

Insira aqui a descrição dessa imagem para ajudar na acessibilidade

Corrigida a questão do espaço, foi resolvido o problema:

Insira aqui a descrição dessa imagem para ajudar na acessibilidade

Obrigado Allison, era o meu problema também.