I am having trouble making authentication API in spring security.
I have the setup for the JWT login and register routes with Spring Security OncePerRequestFilter.
For some reason, When I try to login myself in, it also tries to run doFilter
method.
Meaning, even though the user is trying to login with username and password
, my api looks for jwt Bearer token
.
I have my SecurityConfig.java
as follows but the antMatchers do not work for login
path as I thought.
Can someone help me please?
SecurityConfig.java
@Configuration
@AllArgsConstructor
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
private final AppUserService appUserService;
private final BCryptPasswordEncoder bCryptPasswordEncoder;
@Autowired
private JwtFilter jwtFilter;
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().disable();
http
.authorizeRequests()
.antMatchers("/api-docs", "/swagger").permitAll()
.antMatchers("/api/v0/auth/login").permitAll()
.antMatchers("/h2-console/**").permitAll()
.anyRequest()
.authenticated();
http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
http.addFilterBefore(this.jwtFilter, UsernamePasswordAuthenticationFilter.class);
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(this.daoAuthenticationProvider());
}
@Bean
public DaoAuthenticationProvider daoAuthenticationProvider() {
DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
provider.setPasswordEncoder(this.bCryptPasswordEncoder);
provider.setUserDetailsService(this.appUserService);
return provider;
}
}
@RestController
@AllArgsConstructor
@RequestMapping(path = "/api/v0/auth")
public class AuthController {
@Autowired
private AuthService authService;
@PostMapping("/login")
public ResponseEntity<AuthResponse> login(@RequestBody LoginRequest request) throws Exception {
AuthResponse response = this.authService.login(request);
return ResponseEntity.ok().body(response);
}
// ..... the rest
When I access /api-docs", "/swagger"
, the API does not try to authenticate.
But the API does for /api/v0/auth/login
, because I can see the log I added in doFilter in the log after sending request to /api/v0/auth/login
@Component
public class JwtFilter extends OncePerRequestFilter {
private Logger log = LoggerFactory.getLogger(JwtFilter.class);
@Override
protected void doFilterInternal(
HttpServletRequest request,
HttpServletResponse response,
FilterChain filterChain) throws ServletException, IOException {
String authorization = request.getHeader("Authorization");
String token = null;
String userName = null;
log.info("@@ doFilterInternal: {}", authorization);
// jwt and authentication stuff
filterChain.doFilter(request, response);
}
}
// what I see in the log for login request
// 2023-01-22 09:49:06.716 INFO 15780 --- [nio-8080-exec-1] c.h.s.config.security.filter.JwtFilter : @@ doFilterInternal: null
Since I added a login endpoint in antMatchers, it should not log this and skip the authentication I believe. Can someone help me with what I am missing?
CodePudding user response:
See this post, with a HttpSecurity config for permitAll you are not bypassing filters -> Spring Security with filters permitAll not working. If you do not want to have your filter be called, you can move that url exclude config to WebSecurity set up as below
@Override
public void configure(WebSecurity web) throws Exception {
web
.ignoring()
.antMatchers("/api/v0/auth/login");
}
or you can add url exclude to OncePerRequestFilter as below -
private final RequestMatcher uriMatcher = new AntPathRequestMatcher("/api/v0/auth/login", HttpMethod.GET.name());
@Override
protected boolean shouldNotFilter(HttpServletRequest request) {
return uriMatcher.matches(request);
}
CodePudding user response:
I guess you want to login with POST method, then you need explicitly say it in the method as i shown below
http
.csrf().disable()
.antMatchers("HttpMethod.POST, /api/v0/auth/login").permitAll()
...
You can also try securing only needed endpoints
http
.authorizeRequests()
.antMatchers("/secured").authenticated()
.anyRequest()
.permitAll();