Context: I am building an API using spring
, and spring security
to protect my endpoints
.
What I've tried: I create a WebSecurityConfig
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
class WebSecurityConfig : WebSecurityConfigurerAdapter() {
@Autowired
private lateinit var unauthorizedHandler: JwtAuthenticationEntryPoint
@Qualifier("jwtUserDetailsServiceImpl")
@Autowired
private lateinit var userDetailsService: UserDetailsService
@Autowired
@Throws(Exception::class)
fun configureAuthentication(authenticationManagerBuilder: AuthenticationManagerBuilder) {
authenticationManagerBuilder.userDetailsService<UserDetailsService>(this.userDetailsService).passwordEncoder(passwordEncoder())
}
@Bean
@Throws(Exception::class)
fun customAuthenticationManager(): AuthenticationManager {
return authenticationManager()
}
@Bean
fun passwordEncoder(): PasswordEncoder {
return BCryptPasswordEncoder()
}
@Bean
@Throws(Exception::class)
fun authenticationTokenFilterBean(): JwtAuthenticationTokenFilter {
return JwtAuthenticationTokenFilter()
}
@Throws(Exception::class)
override fun configure(httpSecurity: HttpSecurity) {
httpSecurity.csrf().disable()
.exceptionHandling().authenticationEntryPoint(unauthorizedHandler).and()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
.authorizeRequests()
.antMatchers(HttpMethod.POST, "/api/user/**").permitAll()
.antMatchers(
HttpMethod.GET,
"/",
"/*.html",
"/favicon.ico",
"/**/*.html",
"/**/*.css",
"/**/*.js"
).permitAll()
.antMatchers("/api/auth/**").permitAll()
.anyRequest().authenticated()
httpSecurity.addFilterBefore(authenticationTokenFilterBean(), UsernamePasswordAuthenticationFilter::class.java)
httpSecurity.headers().cacheControl()
}
}
My problem: My authenticationTokenFilterBean
is getting called on endpoint started by api/user since I am doing ("/api/user/**").permitAll()
is this supposed to happen? Because this is calling my JwtAuthenticationTokenFilter
(above) and my authToken is always null
because I don't pass anything in the Authorization header(since this is an account creation and thats why I put the permitAll
in this endpoint ("/api/user/**").permitAll()
class JwtAuthenticationTokenFilter : OncePerRequestFilter() {
@Qualifier("jwtUserDetailsServiceImpl")
@Autowired
private lateinit var userDetailsService: UserDetailsService
@Autowired
private lateinit var jwtTokenUtil: JwtTokenUtil
@Throws(ServletException::class, IOException::class)
override fun doFilterInternal(request: HttpServletRequest, response: HttpServletResponse, chain: FilterChain) {
val authToken = request.getHeader("Authorization")
val username = jwtTokenUtil.getUsernameFromToken(authToken)
if (username != null && SecurityContextHolder.getContext().authentication == null) {
val userDetails = this.userDetailsService.loadUserByUsername(username)
if (jwtTokenUtil.validateToken(authToken, userDetails)) {
val authentication = UsernamePasswordAuthenticationToken(
userDetails, null, userDetails.authorities)
authentication.details = WebAuthenticationDetailsSource().buildDetails(request)
logger.info("authenticated user $username, setting security context")
SecurityContextHolder.getContext().authentication = authentication
}
}
chain.doFilter(request, response)
}
}
Objective: Can someone help me discover if its normal that my authenticationTokenFilterBean is being called on non-protected API. And if it is explain how can I do it. Thanks