I am trying to secure/authorize my endpoints with JWT. The token is to be generated after successful login. The problem is anytime I call the login endpoint http://localhost:8080/login and pass in the credentials, it returns a 403 response. Here is my spring security configuration
@Configuration
public class SecurityConfig {
@Autowired
private UserDetailsServiceImpl userDetailsService;
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http.authorizeHttpRequests((authz) -> authz.anyRequest().authenticated()).httpBasic(withDefaults());
return http.build();
}
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception
{
auth.userDetailsService(userDetailsService).passwordEncoder(new BCryptPasswordEncoder());
}
@Bean
public AuthenticationManager getAuthenticationManager(AuthenticationConfiguration authenticationConfiguration) throws Exception {
return authenticationConfiguration.getAuthenticationManager();
}
protected void configure(HttpSecurity http) throws Exception{
http.cors().and().csrf().disable().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and().authorizeRequests().antMatchers(HttpMethod.POST, "/login").permitAll().anyRequest().authenticated();
}
}
Here is my LoginController
@RestController
public class LoginController {
@Autowired
private JwtService jwtService;
@Autowired
AuthenticationManager authenticationManager;
@RequestMapping(value="/login", method=RequestMethod.POST)
public ResponseEntity<?> getToken(@RequestBody AccountCredentials credentials) {
// Generate token and send it in the response
//Authorization
// header
UsernamePasswordAuthenticationToken creds = new UsernamePasswordAuthenticationToken(credentials.getUsername(), credentials.getPassword());
Authentication auth = authenticationManager.authenticate(creds);
String jwts = jwtService.getToken(auth.getName());
return ResponseEntity.ok().header(HttpHeaders.AUTHORIZATION, "Bearer " jwts).
header(HttpHeaders.ACCESS_CONTROL_EXPOSE_HEADERS, "Authorization").build();
}
}
Here is my UserServiceImplementation
@Service
public class UserDetailsServiceImpl implements UserDetailsService {
@Autowired
private UserRepository repository;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
Optional<User> user =
repository.findByUsername(username);
UserBuilder builder = null;
if (user.isPresent()) {
User currentUser = user.get();
builder =
org.springframework.security.core.userdetails.
User.withUsername(username);
builder.password(currentUser.getPassword());
builder.roles(currentUser.getRole());
} else {
throw new UsernameNotFoundException("User not found.");
}
return builder.build();
}
}
If I visit http://localhost:8080/api in the browser and authenticate, it works.
I enabled debug, Here are the logs when the endpoint gets called.
I don't know what I am doing wrong, Kindly Help.
CodePudding user response:
Move the csrf.disable() and other configurations from the protected void configure(HttpSecurity http) method to the SecurityFilterChain filterChain(HttpSecurity http) method.
Explainaiton:
The problem here is your SecurityConfig class. Since, your class is not extending the the WebSecurityConfigurerAdapter, protected void configure(HttpSecurity http) will not have any effect on your applicaiton. All the configuation are applied from the @Bean of SecurityFilterChain filterChain(HttpSecurity http) method.
CodePudding user response:
replace this code with configure (HttpSecurity).
protected void configure(HttpSecurity http) throws Exception{
http.cors().and().csrf().disable().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and().authorizeRequests().antMatchers(HttpMethod.POST, "/login").permitAll().and().httpBasic();
}
CodePudding user response:
Change the below method from
protected void configure(HttpSecurity http) throws Exception{
http.cors().and().csrf().disable().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and().authorizeRequests().antMatchers(HttpMethod.POST, "/login").permitAll().anyRequest().authenticated();
}
to :
protected void configure(HttpSecurity http) throws Exception{
http.cors().and().csrf().disable().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and().authorizeRequests().httpBasic().and().antMatchers(HttpMethod.POST, "/login").permitAll().anyRequest().authenticated();
}
You have to add httpBasic() to this method
Also you send the username and password from authorization tab in postman directly by selecting basic auth option . And try accessing any protected link.
[This will show how to select basic auth]