Spring Security 6, Angular 13 CORS problem OPTIONS request

Discussão em 'Angular' iniciado por Matteo Vigilante, Novembro 8, 2024.

  1. i have this application in Springboot for the backend and the angular app as frontend my problem is that when i perform a http get call from angular to the backend it response me with a

    'Access to XMLHttpRequest at 'http://localhost:8080/operator/getall' from origin 'http://localhost:4200' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.'

    to understand more here some pics of my backend and fronted project of the interceptor and all security configuration stuff

    @Configuration
    @EnableWebSecurity
    @EnableMethodSecurity
    @RequiredArgsConstructor
    public class SecurityConfiguration {

    private final JwtAuthenticationFilter jwtAuthenticationFilter;
    private final UserService userService;

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {

    http.csrf(AbstractHttpConfigurer::disable)
    .cors(AbstractHttpConfigurer::disable)
    .authorizeHttpRequests(request -> request.requestMatchers("/auth/**")
    .permitAll().requestMatchers("/operator/**").hasAnyRole("ADMIN").anyRequest().authenticated())
    .sessionManagement(manager -> manager.sessionCreationPolicy(STATELESS))
    .authenticationProvider(authenticationProvider()).addFilterBefore(
    jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class);
    return http.build();
    }

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

    @Bean
    public AuthenticationProvider authenticationProvider() {
    DaoAuthenticationProvider authProvider = new DaoAuthenticationProvider();
    authProvider.setUserDetailsService(userService.userDetailService());
    authProvider.setPasswordEncoder(passwordEncoder());
    return authProvider;
    }

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


    @RestController
    @RequestMapping(path = "/operator")
    @CrossOrigin(origins = "http://localhost:4200/", maxAge = 3600)
    @RequiredArgsConstructor
    @PreAuthorize("hasRole('ADMIN')")
    public class OperatoreController {

    @Autowired
    private OperatoreService operatoreService;

    @GetMapping(path = "/getall")
    public ResponseEntity<List<Operatore>> getAllOperatore(){
    return ResponseEntity.ok(operatoreService.getAll());
    }

    }


    @RestController
    @RequestMapping(path = "/auth")
    @CrossOrigin(origins = "http://localhost:4200", maxAge = 3600)
    @RequiredArgsConstructor
    public class AuthenticationController {

    @Autowired
    private OperatoreService operatoreService;

    @Autowired
    private final AuthenticationServiceImpl authenticationService;

    @PostMapping("/login")
    public ResponseEntity<JwtAuthenticationResponse> Login(@RequestBody LoginRequest request) {
    return ResponseEntity.ok(authenticationService.signin(request));
    }
    }


    the frontend service that performs the call

    @Injectable({
    providedIn: 'root'
    })
    export class HomeService {

    constructor(private http: HttpClient) { }

    getAll() {
    console.log(`${environment.apiUrl}/${environment.servizi.api.getAll}`)
    return this.http.get(`${environment.apiUrl}/${environment.servizi.api.getAll}`)
    }

    }


    the interceptor

    @Injectable()
    export class JwtInterceptor implements HttpInterceptor {
    constructor(private authenticationService: AuthService) {}

    intercept(
    request: HttpRequest<any>,
    next: HttpHandler
    ): Observable<HttpEvent<any>> {
    // add authorization header with jwt token if available
    const currentUser = this.authenticationService.currentUserValue;
    if (currentUser && currentUser.token) {

    console.log("SEEET token "+ currentUser.token)
    /**request = request.clone({
    headers: request.headers.append("Authorization",`Bearer ${currentUser.token}`)
    });**/
    request = request.clone({
    setHeaders: {
    Authorization: `Bearer ${currentUser.token}`
    },
    });
    }

    return next.handle(request);
    }
    }



    the weirder things is that only on that method in OperatoreController getall does return this error, the authentication works and it return the jwt as expected

    !(https://i.sstatic.net/wzBXk.png)

    and trying on postman and works too

    !(https://i.sstatic.net/xsM7B.png)

    JwtAuthenticationFilter

    @Component


    @AllArgsConstructor public class JwtAuthenticationFilter extends OncePerRequestFilter {

    private final JwtServiceImpl jwtService;
    private final TokenRepository tokenRepository;
    private final UserDetail userService;
    @Override
    protected void doFilterInternal(@NonNull HttpServletRequest request,
    @NonNull HttpServletResponse response, @NonNull FilterChain filterChain)
    throws ServletException, IOException {
    final String authHeader = request.getHeader("Authorization");
    final String jwt;
    final String userEmail;
    if (StringUtils.isEmpty(authHeader) || !StringUtils.startsWith(authHeader, "Bearer ")) {
    filterChain.doFilter(request, response);
    return;
    }
    jwt = authHeader.substring(7);
    userEmail = jwtService.extractUserName(jwt);
    if (StringUtils.isNotEmpty(userEmail)
    && SecurityContextHolder.getContext().getAuthentication() == null) {
    UserDetails userDetails = userService.userDetailService()
    .loadUserByUsername(userEmail);
    var isTokenValid = tokenRepository.findByToken(jwt)
    .map(t -> !t.isExpired() && !t.isRevoked())
    .orElse(false);
    if (jwtService.isTokenValid(jwt, userDetails) && isTokenValid && userDetails.isEnabled()) {
    SecurityContext context = SecurityContextHolder.createEmptyContext();
    UsernamePasswordAuthenticationToken authToken = new UsernamePasswordAuthenticationToken(
    userDetails, null, userDetails.getAuthorities());
    authToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
    context.setAuthentication(authToken);
    SecurityContextHolder.setContext(context);
    }
    }
    filterChain.doFilter(request, response);
    }


    }

    EDIT 1

    after a some modifications i do to my code i figure out that Angular makes a OPTIONS request but to access to request method in /operator/getAll it must to be Authenticated so my JwtAuthenticationFilter discard it and then the CorsError appers infact if we try to move the method in the AuthenticationController that doesnt need the JWT accept the request

    [​IMG]

    [​IMG]

    but i cant add the jwt to OPTIONS request for the CORS policy and i want that to acces to OperatorController the request must be authenticathed so i dont know how to figure out with this problem can someone help me

    Continue reading...

Compartilhe esta Página