I'm trying to get spring security with JWT to work with an app. I've read many tutorials and examples but nothing really fits my use case. We do not authorize via username/password, we use twilio to authenticate a mobile number, I then want to create a simple JWT token given a mobile number as the subject. I've been able to do that
here is a simple endpoint that exists in /api/v1/jwt
@GetMapping("/jwt")
fun jwt(@RequestParam(value = "number", required = true) number: String): String? {
val jwtToken = Jwts.builder().setSubject(number).claim("roles", "user").setIssuedAt(Date()).signWith(SignatureAlgorithm.HS256, Base64.getEncoder().encodeToString("secret".toByteArray())).compact()
return jwtToken
}
which returns a valid JWT token.
My security config isn't working anymore though, now all endpoints seem protected,
@Configuration
@EnableWebSecurity
class SecurityConfig : WebSecurityConfigurerAdapter() {
@Bean
override fun authenticationManagerBean(): AuthenticationManager {
return super.authenticationManagerBean()
}
override fun configure(web: WebSecurity) {
web.ignoring().antMatchers("/v2/api-docs",
"/configuration/ui",
"/swagger-resources/**",
"/configuration/security",
"/swagger-ui.html",
"/webjars/**");
}
override fun configure(http: HttpSecurity) {
http.csrf()
.disable()
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.authorizeRequests()
.antMatchers("/api/v1/auth/**").permitAll()
.anyRequest().authenticated()
.and()
.addFilterBefore(JwtFilter(), UsernamePasswordAuthenticationFilter::class.java)
}
}
JWT Filter
@Throws(IOException::class, ServletException::class)
override fun doFilter(req: ServletRequest, res: ServletResponse, chain: FilterChain) {
val request = req as HttpServletRequest
val response = res as HttpServletResponse
val authHeader = request.getHeader("authorization")
if ("OPTIONS" == request.method) {
response.status = HttpServletResponse.SC_OK
chain.doFilter(req, res)
} else {
if (authHeader == null || !authHeader.startsWith("Bearer ")) {
throw ServletException("Missing or invalid Authorization header")
}
val token = authHeader.substring(7)
try {
val claims = Jwts.parser().setSigningKey(Base64.getEncoder().encodeToString("secret".toByteArray())).parseClaimsJws(token).body
request.setAttribute("claims", claims)
} catch (e: SignatureException) {
throw ServletException("Invalid token")
}
chain.doFilter(req, res)
}
}
}
It seems the filter gets hit any time regardless of the permitall above it. Shouldn't the filter get ignored on any api/v1/auth/ path? I think im missing something.
Second question is there a way to apply this filter without having to addbefore or after and not extend https://docs.spring.io/spring-security/site/docs/current/api/org/springframework/security/web/authentication/AbstractAuthenticationProcessingFilter.html
edit: antPathRequestMatcher isn't firing for configure, but I even added the path to websecurity configure, i get this logging
2019-12-30 14:44:44.792 DEBUG 81181 --- [nio-8080-exec-2] o.s.security.web.FilterChainProxy : /api/v1/auth/request?number=5555555 has an empty filter list```
If you find that specific auto-configure classes are being applied that you don't want, you can use the exclude attribute of @EnableAutoConfiguration to disable them. If the class is not on the classpath, you can use the excludeName attribute of the annotation and specify the fully qualified name instead.
Use Method-level Authorization To Restrict An Endpoint This tells Spring to check that the authenticated user has the Admin authority, and if not, deny the request. Run the app: ./gradlew bootRun . Navigate to http://localhost:8080/restricted . You'll get a 403 / Unauthorized whitepage error.
You need to declare SecurityFilterChain and WebSecurityCustomizer beans instead of overriding methods of WebSecurityConfigurerAdapter class.
anyRequest(). authenticated() is that any request must be authenticated otherwise my Spring app will return a 401 response.
You may use configure(web: WebSecurity)
, which will bypass the spring security filters and endpoints can be accessed publicly.
override fun configure(web: WebSecurity) {
web.ignoring().antMatchers("/api/v1/auth/**",
"/v2/api-docs",
"/configuration/ui",
"/swagger-resources/**",
"/configuration/security",
"/swagger-ui.html",
"/webjars/**");
}
You might use configure(http: HttpSecurity)
for session management and role-based authentication. You may see HttpSecurity vs WebSecurity.
For custom filters which have @Component
(or any flavor of @Bean), WebSecurityConfigurerAdapter
will tell Spring Security to ignore any filters added through it. The filter was then still being invoked because the @Component
(or any flavor of @Bean) annotation told Spring to add the filter (again) outside of the security chain. So while the filter was being ignored in the security chain, it was not being ignored by the other (non-security?) chain. (See Here)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With