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