java – How do I fix CORS Error and 403 on Springboot App to Heroku?

I try my springboot app to Heroku and I get error 403 whenever I try to access any of the endpoints. I have read resources and materials I can lay my hands on as touching CORS configuration. They don’t seem to have helped.

Here is what my CORS Config class looks like

@Component
 public class CorsConfig{

    @Bean
    public WebMvcConfigurer corsConfigurer() {

        return new WebMvcConfigurer() {
            @Override
            public void addCorsMappings(CorsRegistry registry) {
                registry
                        .addMapping("/**")
                        .allowedMethods(CorsConfiguration.ALL)
                        .allowedHeaders(CorsConfiguration.ALL)
                        .allowedOriginPatterns(CorsConfiguration.ALL)
                        .allowedHeaders(CorsConfiguration.ALL)
                        .exposedHeaders(CorsConfiguration.ALL)
                        .allowCredentials(true).maxAge(3600);
            }
        };
    }
}

Here is what I did for my websecurity. This seems to be working just fine on Postman before now.

@EnableWebSecurity
@AllArgsConstructor
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {


    private final JwtAuthFilter jwtAuthFilter;
    private final UserDetailsService userDetailsService;


    @Override
    public void configure(HttpSecurity http)throws Exception{
        http.cors().and().
        csrf().disable()
                .authorizeRequests()

                .antMatchers("/api/auth/**", "/browser/**", "/actuator/**").permitAll()
                .antMatchers(HttpMethod.POST,"/api/v1/auth/**").permitAll()
                .antMatchers(HttpMethod.GET,"/api/v1/nest/**").permitAll()
                .antMatchers( "/api/users/**").permitAll()
                .antMatchers( "api/v1/auth/**").permitAll()
                .antMatchers("api/circles/**")
                .permitAll()
                .antMatchers(HttpMethod.POST,"/api/v1/products/").hasRole("ADMIN")
                .antMatchers(HttpMethod.GET,"/api/v1/products/").permitAll()
                .antMatchers("/v2/api-docs",
                        "/configuration/ui",
                        "/swagger-resources/**",
                        "/swagger-ui/*",
                        "/swagger-ui.html",
                        "/configuration/security",
                        "/webjars/**",
                        "v2/**")
                .permitAll()
                .anyRequest()
                .authenticated();

        http.addFilterBefore(jwtAuthFilter,
                UsernamePasswordAuthenticationFilter.class);

       http.cors().configurationSource(request -> new CorsConfiguration().applyPermitDefaultValues());
    }

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

    @Bean(BeanIds.AUTHENTICATION_MANAGER)
    @Override
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }


    @Override
    protected void configure( AuthenticationManagerBuilder authManager) throws Exception{
        authManager.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
    }

    @Override
    public void configure(WebSecurity web) throws Exception {
        web.ignoring().antMatchers("/v2/api-docs",
                "/configuration/ui",
                "/swagger-resources/**",
                "/configuration/security",
                "swagger-ui/**",
                "/swagger-ui.html",
                "/webjars/**");

    }

I have been following the official documentation in writing these lines of codes. I think it is important I also paste my AuthFilter here.

@Component
@AllArgsConstructor
public class JwtAuthFilter extends OncePerRequestFilter {
    private final JwtProvider jwtProvider;
    private final UserDetailsService userDetails;

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
            throws ServletException, IOException {
        String jwtFromRequest = getJwtFromRequest(request);

        if (StringUtils.hasText(jwtFromRequest) && jwtProvider.validateToken(jwtFromRequest)) {
            String username = jwtProvider.getEmailFromToken(jwtFromRequest);

            UserDetails user = userDetails.loadUserByUsername(username);
            UsernamePasswordAuthenticationToken authentication =
                    new UsernamePasswordAuthenticationToken(username, null, user.getAuthorities());
            authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));

            SecurityContextHolder.getContext().setAuthentication(authentication);
        }

        filterChain.doFilter(request, response);
    }

    private String getJwtFromRequest(HttpServletRequest request) {
        String bearerToken = request.getHeader("Authorization");

        if (StringUtils.hasText(bearerToken) && bearerToken.startsWith("Bearer ")) {
            return bearerToken.substring(7);
        } return bearerToken;
    }

}

Like I said earlier now, these endpoints have been working quite fine now on Postman but throws errors whenever it is being consumed on the frontend. But of recent, I have been encountering 403 on all the endpoints.

I will post sample of some of the endpoints here also.

@RestController
@RequestMapping("/api/v1/auth")
@AllArgsConstructor
@Slf4j
public class AuthController {
    private final AuthService auth;
    private final RefreshTokenService tokenService;



    @PostMapping("/signup")
    @PermitAll
    public ResponseEntity<?> signUp(@RequestBody RegisterDto register){
        try {
            return ResponseEntity.ok().body(auth.signup(register));
        }catch (CrossPointException ex){
            log.info(ex.getLocalizedMessage());
            return new ResponseEntity<>("User registration was not successful", HttpStatus.NOT_ACCEPTABLE);
        }
    }

    @GetMapping("accountVerification/{token}")
    @PermitAll
    public ResponseEntity<String> verifyAccount(@PathVariable String token){
        auth.verifyAccount(token);
        return new ResponseEntity<String>("Account activated", HttpStatus.OK);
    }

    @PostMapping("/login")
    @PermitAll
    public AuthenticationResponse login(@RequestBody LoginDto loginRequest){
        return auth.login(loginRequest);
    }

    @PostMapping("refresh/token")
    @PermitAll
    public AuthenticationResponse refreshTokens(@Valid @RequestBody RefreshTokenRequest refreshToken){
        return auth.refreshTokens(refreshToken);
    }

    @RolesAllowed({"ROLE_USER,ROLE_ADMIN"})
    @PostMapping("/logout")
    public ResponseEntity<String> logout(@Valid @RequestBody RefreshTokenRequest refreshToken){
        tokenService.deleteRefreshToken(refreshToken.getRefreshToken());

        return ResponseEntity.status(HttpStatus.OK).body("Token deleted");
    }
}

I am a bit fed up with this error. I have been on it for months now. What do you suggest I do to resolve this problem?

Leave a Comment