Ya estoy inscrito ¿Todavía no tienes acceso? Nuestros Planes
Ya estoy inscrito ¿Todavía no tienes acceso? Nuestros Planes
2
respuestas

403 Forbidden

Hola.

He seguido los paso de los filter para las autenticaciones y aunque este el codigo igual me arroja el siguiente error:

com.auth0.jwt.exceptions.JWTDecodeException: The input is not a valid base 64 encoded string.
2023-05-15T18:19:32.152-05:00 ERROR 14892 --- [nio-8080-exec-2] o.a.c.c.C.[.[.[/].[dispatcherServlet]    : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception

java.lang.RuntimeException: Verifier invalido

Aqui dejo el codigo del SecurityFilter y del SecurityConfigurations

package med.voll.api.infra.security;

import java.io.IOException;

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 jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import med.voll.api.domain.usuarios.UsuarioRepository;

@Component
public class SecurityFilter extends OncePerRequestFilter {

    @Autowired
    private TokenService tokenService;

    @Autowired
    private UsuarioRepository usuarioRepository;

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
            throws ServletException, IOException {
        //Obtener el Token del Header
        var authHeader = request.getHeader("Authorization");

        if(authHeader != null ) {
            var token = authHeader.replace("Bearer", "");
            var nombreUsuario = tokenService.getSubject(token);
            if(nombreUsuario != null) {
                //Token Valido
                var usuario = usuarioRepository.findByLogin(nombreUsuario);
                var authentication = new UsernamePasswordAuthenticationToken(usuario, null, 
                        usuario.getAuthorities()); // Forzar inicio de sesion
                SecurityContextHolder.getContext().setAuthentication(authentication);
            }
        }
        filterChain.doFilter(request, response);
    }
}
package med.voll.api.infra.security;

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.authentication.UsernamePasswordAuthenticationToken;
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.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

@Configuration
@EnableWebSecurity
public class SecurityConfigurations {

    @Autowired
    private SecurityFilter securityFilter;

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

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

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



}
2 respuestas

Hola Juan, espero que estés bien!

Creo que falta un cambio en la clase SecurityFilter: el método de reemplazo no elimina tiene un espacio despúes del Bearer, como el profesor utiliza en el video. ¡Haz la prueba con este cambio y dime si funcionó!

De:

var token = authHeader.replace("Bearer", "");

Para:

var token = authHeader.replace("Bearer ", "");

Saludos y buenos estudios!

Si este post te ayudó, por favor, marca como solucionado ✓. Continúa con tus estudios!

Eso te pasa porque de alguna manera te está entrando al TokenService y el verifir te tira eu es inválido. Fiajte primero que tu clase esté bien, en caso de persistir el error, hacete, por ejemplo: un System.out.println("hasta acá todo bien!"); y seguite el paso a paso de la ejecución. De esta manera podar testear y hacer el debug.

Esta es la clase TokenService.java

package med.voll.api.infra.security;

import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTCreationException;
import com.auth0.jwt.exceptions.JWTVerificationException;
import com.auth0.jwt.interfaces.DecodedJWT;
import med.voll.api.domain.usuario.Usuario;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

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

@Service
public class TokenService {


@Value("${api.security.secret}")
private String apiSecret;
public String generarToken(Usuario usuario){
    String token = null;
    try {
        Algorithm algorithm = Algorithm.HMAC256(apiSecret);
        token = JWT.create()
                .withIssuer("voll med")
                .withSubject(usuario.getLogin())
                .withClaim("id", usuario.getId())
                .withExpiresAt(generarFechaExpiracion())
                .sign(algorithm);
    } catch (JWTCreationException exception){
        throw new RuntimeException();
    }
    return token;
}

public String getSubject(String token) {
    DecodedJWT verifier = null;
    try {
        Algorithm algorithm = Algorithm.HMAC256(apiSecret);
        verifier = JWT.require(algorithm)
                .withIssuer("voll med")
                .build()
                .verify(token);
        verifier.getSubject();
    } catch (JWTVerificationException exception) {
        //nada
    }
    if(verifier.getSubject() == null){
        throw new RuntimeException("El Verifier es inválido!");
    }
    return verifier.getSubject();
}

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