Dorinel Panaite
Dorinel Panaite

Reputation: 582

Spring Filters not being called

I've been following this tutorial to get JWT authentication in Spring, but for some reason, the filters are not working for me. I have downloaded the tutorial project from Github and it works, but mine doesn't and I can't figure out why...

I'll post some code below (don't mind the Kotlin + Java mix, I tried to implement the security config in java, thought maybe that was a problem)

Initializer.kt

class Initializer : WebApplicationInitializer {
@Throws(ServletException::class)
override fun onStartup(container: ServletContext) {
    val context = AnnotationConfigWebApplicationContext()
    context.scan("com.newyorkcrew.server.config")
    context.scan("com.newyorkcrew.server.domain")

    val dispatcher = container.addServlet("dispatcher", DispatcherServlet(context))
    dispatcher.setLoadOnStartup(1)
    dispatcher.addMapping("/api/*")
}
}

WebConfig.kt

@Bean
fun propertySourcesPlaceholderConfigurer(): PropertySourcesPlaceholderConfigurer {
return PropertySourcesPlaceholderConfigurer()
 }

@Configuration
@Import(JPAConfig::class)
@EnableWebMvc
@ComponentScan("com.newyorkcrew.server")
@PropertySources(PropertySource(value = ["classpath:local/db.properties",     "classpath:local/security.properties"]))
open class WebConfig {

@Bean
open fun corsConfigurer(): WebMvcConfigurer {
    return object : WebMvcConfigurer {
        override fun addCorsMappings(registry: CorsRegistry?) {
            registry!!.addMapping("/**")
                    .allowedOrigins("http://localhost:4200", "http://localhost:8080", "http://localhost:8081")
                    .allowedMethods("GET", "PUT", "POST", "DELETE")
        }
    }
}
}

WebSecurity.java

    @Configuration
@EnableWebSecurity
@ComponentScan("com.newyorkcrew.server.config")
public class WebSecurity extends WebSecurityConfigurerAdapter {
    public static String SECRET;

    @Value("{security.secret}")
    private void setSECRET(String value) {
        SECRET = value;
    }

    @Value("{security.expiration}")
    public static long EXPIRATION_TIME;

    @Value("{security.header}")
    public static String HEADER;

    @Value("{security.prefix}")
    public static String PREFIX;

    public static String SIGN_UP_URL;

    @Value("${security.signupurl}")
    private void setSignUpUrl(String value) {
        SIGN_UP_URL = value;
    }

    @Autowired
    private UserDetailsService userDetailsService;

    public WebSecurity(UserDetailsService userDetailsService) {
        this.userDetailsService = userDetailsService;
    }

    @Bean
    public BCryptPasswordEncoder bCryptPasswordEncoder() {
        return new BCryptPasswordEncoder();
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.cors().and().csrf().disable().authorizeRequests()
                .antMatchers(HttpMethod.POST, SIGN_UP_URL).permitAll()
                .anyRequest().authenticated()
                .and()
                .addFilter(new JWTAuthenticationFilter(authenticationManager()))
                .addFilter(new JWTAuthorizationFilter(authenticationManager()));
    }

    @Override
    public void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsService).passwordEncoder(bCryptPasswordEncoder());
    }

    @Bean
    CorsConfigurationSource corsConfigurationSource() {
        final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/api/**", new CorsConfiguration().applyPermitDefaultValues());
        return source;
    }

}

I also have implemented the UserDetailService, the JWTAuthenticationFilter and JWTAuthorizationFilter, but as long they're not hit, I don't think that they matter very much.

I've worked with the configs for some time now and they worked, but when the SecurityConfig was added, it's initialised, but the filters don't work for some reason.

If more code is required, I'll post.

EDIT: As requested, the implementation of JWTAuthenticationFilter.

open class JWTAuthenticationFilter(private val authManager: AuthenticationManager) : UsernamePasswordAuthenticationFilter() {
    override fun attemptAuthentication(request: HttpServletRequest?, response: HttpServletResponse?): Authentication {
        try {
            // Build the user DTO from the request
            val userDTO = Gson().fromJson(convertInputStreamToString(request?.inputStream), UserDTO::class.java)

            // Build the user from the DTO
            val user = UserConverter().convertDtoToModel(userDTO)

            // Try to authenticate
            return authManager.authenticate(UsernamePasswordAuthenticationToken(user.email, user.password, ArrayList()))
        } catch (e: Exception) {
            throw RuntimeException(e)
        }
    }

    override fun successfulAuthentication(request: HttpServletRequest?, response: HttpServletResponse?,
                                          chain: FilterChain?, authResult: Authentication?) {
        val token = Jwts.builder()
                .setSubject(authResult?.principal.toString())
                .setExpiration(Date(System.currentTimeMillis() + EXPIRATION_TIME))
                .signWith(SignatureAlgorithm.HS512, SECRET.toByteArray())
                .compact()
        response?.addHeader(HEADER, "$PREFIX $token")
    }
}

Any help is appreciated.

Upvotes: 2

Views: 885

Answers (1)

Dorinel Panaite
Dorinel Panaite

Reputation: 582

The solution that worked for me was to give up Kotlin. Started a fresh Spring project with the same configurations and it simply worked. I'm quite sad as I wanted to do this project in Kt, but maybe I was doing something wrong..

Upvotes: 1

Related Questions