Solucionado (ver solução)
Solucionado
(ver solução)
10
respostas

[Dúvida] erro 403

Então, eu fiz tudo certinho com o que é passado na aula, consigo gerar o token mas quando vou fazer uma requisição apos colocar ele na header de authorization, da esse erro 403 e continua com isso aqui:


java.lang.RuntimeException: Token JWT inválido ou expirado!
...
Caused by: com.auth0.jwt.exceptions.JWTDecodeException: The input is not a valid base 64 encoded string.
...
Caused by: java.lang.IllegalArgumentException: Illegal base64 character 20

Eu estou utilizando o java 8 e tive que fazer algumas coisas de outra forma que o professor fez no curso, mas ainda sim nao consigo entender o motivo desse erro... vou mandar aqui os codigos da token service, securityfilter e securityConfigurations

10 respostas

SecurityConfigurations

package med.voll.api;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;


@Configuration
@EnableWebSecurity
public class SecurityConfigurations extends WebSecurityConfigurerAdapter {

    
    @Autowired
    private SecurityFilter securityFilter;
    
     @Override
        protected void configure(HttpSecurity http) throws Exception {
         http.csrf().disable()
         .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
         .and().authorizeRequests()
         .antMatchers(HttpMethod.POST, "/login").permitAll()
         .anyRequest().authenticated()
         .and().addFilterBefore(securityFilter, UsernamePasswordAuthenticationFilter.class);
         //.build();
            
        }
     
//	 @Bean
//	 public 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  //O @Bean seve parar exportar uma classe para o Spring,fazendo com que ele consiga carregá-la e realize a sua injeção de depencência em outras classes.
    public AuthenticationManager authenticationManager(AuthenticationConfiguration configuration) throws Exception {
        return configuration.getAuthenticationManager();
    }

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

SecurityFilter

package med.voll.api;


import java.io.IOException;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;

import lombok.experimental.var;
import med.voll.api.usuario.UsuarioRepository;

@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;
        }
        
        return null;
    }

}

TokenService

package med.voll.api;

import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneOffset;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import com.auth0.jwt.JWT;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTCreationException;
import com.auth0.jwt.exceptions.JWTVerificationException;

import lombok.var;
import med.voll.api.usuario.Usuario;

@Service
public class TokenService {
    
    @Value("${api.security.token.secret}")
    private String secret;
    
    
    public String gerarToken(Usuario usuario) {
        System.out.println(secret);
        try {
            var algoritmo =  Algorithm.HMAC256(secret);
            return JWT.create()
                    .withIssuer("API voll.med")
                    .withSubject(usuario.getLogin())
                    .withExpiresAt(dataExpiracao())
                    .sign(algoritmo);
        } catch (JWTCreationException exception) {
            throw new RuntimeException("erro ao gerar token jwt", exception);
        }
    }

    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!", exception);
        }
    }

    
    private Instant dataExpiracao() {
        
        return LocalDateTime.now().plusHours(2).toInstant(ZoneOffset.of("-03:00"));	}
}

o problema aparenta estar na validação do token, mas nao sei realmente como resolver

Oi!

Dá uma olhada aqui: https://cursos.alura.com.br/course/spring-boot-aplique-boas-praticas-proteja-api-rest/task/130894

oi boa tarde, eu ja tentei todos esses metodos que tinha nesse topico da aula, ja usei com replace, sem replace, meu issuer igual, ja verifiquei a senha no select e ta codificada tambem, alterei o metodo no autenticacaoController como sugeria la tambem e ainda sim continua o mesmo erro, mudei tambem pra imprimir o tokenJWT no console e ele imprime certinho, mas ainda continua dizendo quando eu mando uma requisição esse erro:

Caused by: com.auth0.jwt.exceptions.JWTDecodeException: The input is not a valid base 64 encoded string.
    at com.auth0.jwt.JWTDecoder.<init>(JWTDecoder.java:46) ~[java-jwt-4.2.1.jar:4.2.1]
    at com.auth0.jwt.JWTVerifier.verify(JWTVerifier.java:444) ~[java-jwt-4.2.1.jar:4.2.1]
    at med.voll.api.TokenService.getSubject(TokenService.java:45) ~[classes/:na]
    ... 51 common frames omitted
Caused by: java.lang.IllegalArgumentException: Illegal base64 character 20
    at java.util.Base64$Decoder.decode0(Base64.java:714) ~[na:1.8.0_271]
    at java.util.Base64$Decoder.decode(Base64.java:526) ~[na:1.8.0_271]
    at java.util.Base64$Decoder.decode(Base64.java:549) ~[na:1.8.0_271]
    at com.auth0.jwt.JWTDecoder.<init>(JWTDecoder.java:41) ~[java-jwt-4.2.1.jar:4.2.1]
    ... 53 common frames omitted

java.lang.RuntimeException: Token JWT inválido ou expirado!
    at med.voll.api.TokenService.getSubject(TokenService.java:48) ~[classes/:na]
    at med.voll.api.SecurityFilter.doFilterInternal(SecurityFilter.java:36) ~[classes/:na]

Seu problema está aqui:

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

    return null;
}

Faltou o replace para tirar o prefixo Bearer do token que chega na requisição.

alterei isso mas ainda sim continua dando erro

java.lang.RuntimeException: Token JWT inválido ou expirado!
    at med.voll.api.TokenService.getSubject(TokenService.java:48) ~[classes/:na]
    at med.voll.api.SecurityFilter.doFilterInternal(SecurityFilter.java:36) ~[classes/:na]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-5.1.2.RELEASE.jar:5.1.2.RELEASE]
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) ~[spring-security-web-5.1.1.RELEASE.jar:5.1.1.RELEASE]
    at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:116) ~[spring-security-web-5.1.1.RELEASE.jar:5.1.1.RELEASE]
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) ~[spring-security-web-5.1.1.RELEASE.jar:5.1.1.RELEASE]
    at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:66) ~[spring-security-web-5.1.1.RELEASE.jar:5.1.1.RELEASE]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-5.1.2.RELEASE.jar:5.1.2.RELEASE]
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) ~[spring-security-web-5.1.1.RELEASE.jar:5.1.1.RELEASE]
    at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:105) ~[spring-security-web-5.1.1.RELEASE.jar:5.1.1.RELEASE]
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) ~[spring-security-web-5.1.1.RELEASE.jar:5.1.1.RELEASE]
...
Caused by: com.auth0.jwt.exceptions.IncorrectClaimException: The Claim 'iss' value doesn't match the required issuer.
    at com.auth0.jwt.JWTVerifier$BaseVerification.lambda$withIssuer$0(JWTVerifier.java:82) ~[java-jwt-4.2.1.jar:4.2.1]
    at com.auth0.jwt.JWTVerifier$BaseVerification.lambda$addCheck$20(JWTVerifier.java:392) ~[java-jwt-4.2.1.jar:4.2.1]
    at com.auth0.jwt.JWTVerifier$BaseVerification$1.verify(JWTVerifier.java:405) ~[java-jwt-4.2.1.jar:4.2.1]
    at com.auth0.jwt.JWTVerifier.verifyClaims(JWTVerifier.java:482) ~[java-jwt-4.2.1.jar:4.2.1]
    at com.auth0.jwt.JWTVerifier.verify(JWTVerifier.java:464) ~[java-jwt-4.2.1.jar:4.2.1]
    at com.auth0.jwt.JWTVerifier.verify(JWTVerifier.java:445) ~[java-jwt-4.2.1.jar:4.2.1]
    at med.voll.api.TokenService.getSubject(TokenService.java:45) ~[classes/:na]
    ... 51 common frames omitted
solução!

Agora é o problema 2) Issuer diferente ao gerar o token citado no link que enviei antes: https://cursos.alura.com.br/course/spring-boot-aplique-boas-praticas-proteja-api-rest/task/130894

realmente era esse problema kkkkk que falta de atenção, um V estava maiusculo e o outro minusculo, mt obg!!