0

I'm deploying Angular app inside resources/static Spring app folder to have just one package to share with clients. The app will then be accessible via http://production-url.com:8080. The deployment is well made but the pages are 'blocked' due to the use of JWT authentication, and the blocking of the first item that the page try to get : the favicon: enter image description here

In my development environment, all is working fine.

I share the most important method that takes care of ignoring urls in WebSecurityConfigurerAdapter extending class :

@Override
    protected void configure(HttpSecurity http) throws Exception {
        http.cors().and().csrf().disable().
                authorizeRequests()
                .antMatchers("/generate-token", "/signup","/config","/saveConfig/","/get/file/*").permitAll()
                .anyRequest().authenticated()
                .and()
                .exceptionHandling().authenticationEntryPoint(unauthorizedHandler).and()
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
        http
                .addFilterBefore(authenticationTokenFilterBean(), UsernamePasswordAuthenticationFilter.class);
    }

Do you have an idea of why JWT is blocking getting static files of the Angular app ?

EDIT : Full class

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
@CrossOrigin("*")
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Resource(name = "userService")
    private UserDetailsService userDetailsService;

    @Autowired
    private JwtAuthenticationEntryPoint unauthorizedHandler;

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

    @Autowired
    public void globalUserDetails(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsService)
                .passwordEncoder(passwordEncoder());
    }

    @Bean
    public JwtAuthenticationFilter authenticationTokenFilterBean() throws Exception {
        return new JwtAuthenticationFilter();
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.cors().and().csrf().disable().
                authorizeRequests()
                .requestMatchers(PathRequest.toStaticResources().atCommonLocations()).permitAll()
                .antMatchers("/css/**", "/js/**", "/images/**").permitAll()
                .antMatchers("/resources/**").permitAll().anyRequest().permitAll()
                .antMatchers("/generate-token", "/signup","/config","/saveConfig/","/get/file/*").permitAll()
                .anyRequest().authenticated()
                .and()
                .exceptionHandling().authenticationEntryPoint(unauthorizedHandler).and()
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
        http
                .addFilterBefore(authenticationTokenFilterBean(), UsernamePasswordAuthenticationFilter.class);
    }

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

EDIT : Added JwtAuthenticationFilter class

public class JwtAuthenticationFilter extends OncePerRequestFilter {

    @Autowired
    private UserDetailsService userDetailsService;

    @Autowired
    private JwtTokenUtil jwtTokenUtil;

    @Override
    protected void doFilterInternal(HttpServletRequest req, HttpServletResponse res, FilterChain chain) throws IOException, ServletException {
        String header = req.getHeader(HEADER_STRING);
        String username = null;
        String authToken = null;
        if (header != null && header.startsWith(TOKEN_PREFIX)) {
            authToken = header.replace(TOKEN_PREFIX,"");
            try {
                username = jwtTokenUtil.getUsernameFromToken(authToken);
            } catch (IllegalArgumentException e) {
                logger.error("an error occured during getting username from token", e);
            } catch (ExpiredJwtException e) {
                logger.warn("the token is expired and not valid anymore", e);
            } catch(SignatureException e){
                logger.error("Authentication Failed. Username or Password not valid.");
            }
        } else {
            logger.warn("couldn't find bearer string, will ignore the header");
        }
        if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {

            UserDetails userDetails = userDetailsService.loadUserByUsername(username);

            if (jwtTokenUtil.validateToken(authToken, userDetails)) {
                UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userDetails, null, Arrays.asList(new SimpleGrantedAuthority("ROLE_ADMIN")));
                authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(req));
                //logger.info("authenticated user " + username + ", setting security context");
                SecurityContextHolder.getContext().setAuthentication(authentication);
            }
        }

        chain.doFilter(req, res);
    }
}
androniennn
  • 3,117
  • 11
  • 50
  • 107
  • 2
    Possible duplicate of [Serving static web resources in Spring Boot & Spring Security application](https://stackoverflow.com/questions/24916894/serving-static-web-resources-in-spring-boot-spring-security-application) – lealceldeiro Jul 17 '18 at 15:48
  • 1
    Also, see https://stackoverflow.com/questions/25368535/when-spring-security-enabled-resoucescss-or-js-cant-be-loaded and https://stackoverflow.com/questions/22823863/access-static-content-in-secured-spring-boot-application – lealceldeiro Jul 17 '18 at 15:48
  • @lealceldeiro Thank you for this useful links. I've got the favicon, but the whole page is blocked ! http://dev.kepler.com.tn:8080/. That's really weird as there is no errors showing in console. – androniennn Jul 17 '18 at 16:12
  • @androniennn: Ok, your filter seems to be okay. But you didn' allow access for `favicon.ico`. You have to add `.antMatchers("/favicon.ico").permitAll()` – dur Jul 18 '18 at 11:00
  • @dur I no longer have a problem with favicon as it gets retrieved. But I don't know why it can't access the default page(login) and it tells me that it needs a full authentication... – androniennn Jul 18 '18 at 11:10
  • @androniennn: Same reason, you didn't allow it. – dur Jul 18 '18 at 11:13
  • @dur I added `/login` to `antMatchers` array, but I have the same problem. – androniennn Jul 18 '18 at 11:23
  • @dur I allowed all requests and I'm having now a strange login and password basic form screen. – androniennn Jul 18 '18 at 11:41
  • @dur https://imgur.com/a/x3TtVP2 it seems that's the basic Spring login page. My login page is totally different... – androniennn Jul 18 '18 at 11:54
  • @androniennn: Yes, that's SPring Security's default login. You didn't configure a custom logn page, so get the default one. Nothing strange. – dur Jul 18 '18 at 11:55
  • @dur I already have my custom login page at `/login` path but it gives me the default Spring one. I'm totally disoriented... That's another problem. My main problem is to enable security and to show my login page that Spring is blocking it. I'm surely doing something wrong. – androniennn Jul 18 '18 at 12:00
  • @dur : I'm just doing the following: configured Angular to generate its static files into the `/resources/static` directory and then I run `mvnw package` to package a fat JAR file. Normally when I run myurl:8080, I get my first page (login) – androniennn Jul 18 '18 at 12:02

0 Answers0