i'm trying to build a Restful API with Spring-boot and oauth2 using hibernate.
i've made a CustomAuthenticationProvider to authenticate users from a database but im having the following response of the server
NOTE: json response.
error": "unauthorized",
"error_description": "No AuthenticationProvider found for org.springframework.security.authentication.UsernamePasswordAuthenticationToken"
}
here is my CustomAuthenticationProvider:
#Component
public class CustomAuthenticationProvider implements AuthenticationProvider {
public CustomAuthenticationProvider() {
super();
}
#Autowired
private UsuarioDAO user;
#Override
public Authentication authenticate(Authentication auth) throws AuthenticationException {
String username = String.valueOf(auth.getName());
String password = String.valueOf(auth.getCredentials().toString());
Usuarios us = null;
try {
us = user.userAuthentication(username, password);
} catch (Exception ex) {
}
if (us != null) {
final List<GrantedAuthority> grantedAuths = new ArrayList<>();
grantedAuths.add(new SimpleGrantedAuthority("ROLE_ADMIN"));
final UserDetails principal = new User(username, password, grantedAuths);
final Authentication authentication = new UsernamePasswordAuthenticationToken(principal, password, grantedAuths);
us = null;
return authentication;
} else {
throw new BadCredentialsException("Bad Credentials");
}
}
#Override
public boolean supports(Class<? extends Object> authentication) {
return (UsernamePasswordAuthenticationToken.class.isAssignableFrom(authentication));
}
}
Here is my WebSecurityConfiguration:
#Configuration
#EnableWebSecurity
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {
#Override
#Bean
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
}
You have to configure Spring Security to use your custom authentication provider.
Add the following code to your WebSecurityConfiguration class:
#Autowired
CustomAuthenticationProvider customAuthenticationProvider;
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(customAuthenticationProvider);
}
Related
In order to protect my Rest API endpoints, I implemented Spring Security using JWT authentication. My code "works" without any issues/exceptions but it would be great if I could get my implementation validated to ensure it is implemented as expected.
WebSecurityConfig.java
#Configuration
#EnableWebSecurity
#RequiredArgsConstructor
public class WebSecurityConfig {
private final CustomAuthenticationManager customAuthenticationManager;
private final AuthTokenFilter authTokenFilter;
private final AuthEntryPoint authEntryPoint;
#Value("${api.prefix}")
private String apiPrefix;
#Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.cors().and().csrf().disable()
.exceptionHandling().authenticationEntryPoint(null).and()
.authenticationManager(customAuthenticationManager)
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.authorizeRequests()
.antMatchers(apiPrefix + "/auth/**").permitAll()
.antMatchers(apiPrefix + "/test/**").permitAll()
.anyRequest().authenticated()
.and()
.exceptionHandling(
httpSecurityExceptionHandlingConfigurer -> httpSecurityExceptionHandlingConfigurer
.authenticationEntryPoint(authEntryPoint)
);
http.addFilterBefore(authTokenFilter, UsernamePasswordAuthenticationFilter.class);
return http.build();
}
}
AuthTokenFilter.java
#Slf4j
#Component
#RequiredArgsConstructor
public class AuthTokenFilter extends OncePerRequestFilter {
private final JwtUtils jwtUtils;
private final UserDAO userDAO;
#Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
String jwt = parseJwt(request);
if (Objects.isNull(jwt)) {
throw new AuthenticationCredentialsNotFoundException("Unable to extract JWT token from authentication header");
}
try {
if (jwtUtils.validateJwtToken(jwt)) {
String username = jwtUtils.getUserNameFromJwtToken(jwt);
UserDetails userDetails = userDAO.loadUserByUsername(username);
UsernamePasswordAuthenticationToken authentication = UsernamePasswordAuthenticationToken.authenticated(userDetails, null, new ArrayList<>()); // please check this line
authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
SecurityContextHolder.getContext().setAuthentication(authentication);
filterChain.doFilter(request, response);
}
} catch (AuthenticationException e) {
throw e;
} catch (Exception e) {
log.error("Cannot set user authentication: {}", e.getMessage(), e);
throw new CustomRTException("Error while validating jwt token", HttpStatus.UNAUTHORIZED);
}
}
private String parseJwt(HttpServletRequest request) {
String headerAuth = request.getHeader("Authorization");
if (StringUtils.hasText(headerAuth) && headerAuth.startsWith("Bearer ")) {
return headerAuth.substring(7);
}
return null;
}
}
CustomAuthenticationManager.java
#Slf4j
#Component
#RequiredArgsConstructor
public class CustomAuthenticationManager implements AuthenticationManager {
private final UserDAO userDAO;
#Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
#Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
UserDetails userDetails = userDAO.loadUserByUsername(authentication.getName());
if (passwordEncoder().matches(authentication.getCredentials().toString(), userDetails.getPassword())) {
throw new BadCredentialsException("Wrong Password");
}
return new UsernamePasswordAuthenticationToken(userDetails, userDetails.getPassword());
}
}
(If any other classes such as UserDAO or AuthEntryPoint is required, let me know. I just shared the classes that I thought were relevant since others were fairly straightforward)
One of the biggest issues that I had was, in AuthTokenFilter even after validating the JWT token, Spring tries to call CustomAuthenticationManager#authenticate again which caused a NullPointerException at this line
authentication.getCredentials().toString() // credentials is null because after parsing the JWT token, I am unable to get the password
This issue was fixed in this line
UsernamePasswordAuthenticationToken authentication = UsernamePasswordAuthenticationToken.authenticated(userDetails, null, new ArrayList<>());
(authorities is empty list as I am currently do not need to grant any)
This code was pieced together following some migration guides from the now deprecated WebSecurityConfigurerAdapter therefore I just want to make sure everything is correct.
I am facing problem related to Session ID. I am using Spring Boot + Mongo DB Authentication.
Below is code and Configuration set:
application.properties
spring.session.store-type=mongodb
SecurityConfig.java
#Configuration
#EnableWebSecurity
#EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter{
#Autowired
private PasswordEncoder passwordEncoder;
#Bean
public UserDetailsService mongoUserDetails() {
return new UserDetailsServiceImpl();
}
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
UserDetailsService userDetailsService = mongoUserDetails();
auth
.userDetailsService(userDetailsService)
.passwordEncoder(passwordEncoder);
}
#Override
public void configure(HttpSecurity http) throws Exception {
http
.csrf().disable()
.authorizeRequests()
.antMatchers("/api/auth/login", "/api/auth/signup")
.permitAll().anyRequest()
.authenticated();
}
#Override
#Bean
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
}
PasswordConfig.java
#Configuration
public class PasswordConfig {
#Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder(10);
}
}
HttpSessionConfig.java
//This is to enable Mongo Http Session
#EnableMongoHttpSession(maxInactiveIntervalInSeconds = 5*60)
#Configuration
public class HttpSessionConfig {
#Bean
public JdkMongoSessionConverter jdkMongoSessionConverter() {
//This duration does not work for setting the Inactive Time for Mongo Session
return new JdkMongoSessionConverter(Duration.ofMinutes(30));
}
}
UserDetailsServiceImpl.java
#Service
public class UserDetailsServiceImpl implements UserDetailsService {
#Autowired
private UserRepository userRepository;
#Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
User user = userRepository.findByUsername(username);
if (user != null) {
List<GrantedAuthority> authorities = getUserAuthority(user.getRoles());
return buildUserForAuthentication(user, authorities);
} else {
throw new UsernameNotFoundException("username not found");
}
}
private UserDetails buildUserForAuthentication(User user, List<GrantedAuthority> authorities)
{
return new org.springframework.security.core.userdetails.User(user.getUsername(), user.getPassword(), authorities);
}
private List<GrantedAuthority> getUserAuthority(Set<Role> userRoles) {
Set<GrantedAuthority> roles = new HashSet<>();
userRoles.forEach((role) -> {
for (GrantedAuthority grantedAuthority : role.getRole().getGrantedAuthorities()) {
roles.add(grantedAuthority);
}
});
List<GrantedAuthority> grantedAuthorities = new ArrayList<>(roles);
return grantedAuthorities;
}
}
AuthController.java
#RestController
#RequestMapping("/api/auth")
public class AuthController {
private final static int IDX_USERNAME = 0;
private final static int IDX_PWD = 1;
#Autowired
private UserService userService;
#Autowired
private AuthenticationManager authenticationManager;
#PostMapping("/login")
public ResponseEntity<?> authenticateUser(HttpServletRequest req,
#RequestHeader("Authorization") String encUser) {
byte[] decoded = Base64.getDecoder().decode(encUser);
String decodedStr = new String(decoded, StandardCharsets.UTF_8);
String[] userCred = decodedStr.split(":");
String username = userCred[IDX_USERNAME];
String pwd = userCred[IDX_PWD];
Authentication authentication;
try {
authentication = authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(username, pwd));
} catch (BadCredentialsException e) {
return new ResponseEntity(e.getMessage(), HttpStatus.FORBIDDEN);
}
SecurityContext sc = SecurityContextHolder.getContext();
sc.setAuthentication(authentication);
HttpSession session = req.getSession(true);
session.setAttribute(SPRING_SECURITY_CONTEXT_KEY, sc);
return new ResponseEntity(HttpStatus.NO_CONTENT);
}
#PostMapping("/logout")
public ResponseEntity<?> logoutUser(HttpServletRequest request, HttpSession session) {
// SecurityContextHolder.getContext().setAuthentication(null);
// SecurityContextHolder.clearContext();
if (session != null) {
session.invalidate();
}
Cookie[] cookies = request.getCookies();
if (cookies != null && cookies.length > 0) {
for (int i = 0; i < cookies.length; i++) {
cookies[i].setMaxAge(0);
}
}
return new ResponseEntity(HttpStatus.NO_CONTENT);
}
}
EmployeeController
#RestController
#RequestMapping("/employee")
public class EmployeeController {
#Autowired
private EmployeeService service;
#GetMapping("/leaves")
#PreAuthorize("hasAnyRole('ROLE_USER')")
public ResponseEntity showLeaves(#RequestParam String user) {
System.out.println("User: " + user);
Employee emp = service.findLeaves(user);
if (emp == null) {
return new ResponseEntity(HttpStatus.NOT_FOUND);
}
return new ResponseEntity(emp, HttpStatus.OK);
}
}
I Login using /api/auth/login API(AuthController.java) using manual authentication(not using httpBasic) by passing base64 ecnryption of username:password in Authorization Header. Authentication works using mongoDB user table and Spring will return the SESSION in the "set-cookie"
Concern 1
Till this point, its ok. Now when i send the request to /employee/leaves (EmployeeController.java) by sending SESSION received from login response in the Authorization Header, spring boot always returns "Forbidden" even though SESSION object is present in the DB before it does land in to the api
Concern 2
If i send login on the already login user, spring boot generates new session id which is also wrong. I tried using SessionManagement().setMaxSession(1) but did not work. I feel this is happening because of using manual authentication. Just a guess.
NOTE: I want to support login for different users(may be not from the same machine).
One Wierd behavior observed that once in while /employee/leaves works. I don't know how it happened.
I seacrhed a lot and spent around 2-3 days but did not get anything.
Any guidance will be great.
Thanks a lot in Advance
my problem is that I get nothing in response after sending requests with wrong login credentials or when accessing the endpoint without authentication.
This is how it looks when I send a good request:
Good Response screen
And this is how it looks when the request body is invalid:
Invalid credentials request
MyUserDetails class:
public class MyUserDetailService implements UserDetailsService {
#Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
return new User("foo", "foo", List.of());
}
}
Security configure class:
public class SecurityConfigurer extends WebSecurityConfigurerAdapter {
#Autowired
private MyUserDetailService myUserDetailService;
#Autowired
private JwtFilter jwtFilter;
#Override
public void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(myUserDetailService);
}
#Bean
public PasswordEncoder passwordEncoder() {
return NoOpPasswordEncoder.getInstance();
}
#Override
#Bean
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/auth").permitAll()
.anyRequest().authenticated()
.and().sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and().csrf().disable();
http.addFilterBefore(jwtFilter, UsernamePasswordAuthenticationFilter.class);
}
}
Jwt Filter class:
#Component
public class JwtFilter extends OncePerRequestFilter {
#Autowired
private JwtUtil jwtUtil;
#Autowired
private MyUserDetailService myUserDetailService;
#Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
final String authHeader = request.getHeader("Authorization");
String username = null;
String requestToken = null;
if(authHeader != null && authHeader.startsWith("Bearer ")) {
requestToken = authHeader.substring(7);
username = jwtUtil.getUsernameFromToken(requestToken);
}
if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {
UserDetails userDetails = myUserDetailService.loadUserByUsername(username);
if(jwtUtil.validateToken(requestToken, userDetails)) {
UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken =
new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
usernamePasswordAuthenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
SecurityContextHolder.getContext().setAuthentication(usernamePasswordAuthenticationToken);
}
}
filterChain.doFilter(request, response);
}
And finally my controller:
#PostMapping("/auth")
public AuthResponse auth(#RequestBody AuthRequest authRequest) throws Exception {
try {
authenticationManager.authenticate(
new UsernamePasswordAuthenticationToken(authRequest.getUsername(), authRequest.getPassword())
);
} catch (BadCredentialsException e) {
throw new Exception("Invalid Credentials", e);
}
final UserDetails userDetails = myUserDetailService.loadUserByUsername(authRequest.getUsername());
final String token = jwtUtil.generateToken(userDetails);
return new AuthResponse(token);
}
EDIT:
I forgot to paste dependancies.
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.boot:spring-boot-starter-security'
implementation 'io.jsonwebtoken:jjwt:0.9.1'
implementation 'javax.xml.bind:jaxb-api:2.2.4'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
}
I also have AuthRequest and AuthResponse class which holds username, password, jwt token and all the constructors, getters and setters ( not worth to past it here imo)
You got to throw an exception while validating(following is what I use, just grab the concept, your classes and libraries might be different):
Jwts.parser().setSigningKey(your_jwt_secret).parseClaimsJws(token);
so if your token cannot get parsed throw this and send an error response:
httpServletResponse.setContentType("application/json");
httpServletResponse.getWriter().write("your_custom_error");
httpServletResponse.getWriter().flush();
I'm making a spring boot webserver which has spring security and jwt for user authentication/authorization via username and password. But seems like spring recognize /api/users/signup and /api/users/signin
as must-be-authenticated URL.
UserController.java:
#PostMapping("/signin")
public ResponseEntity<String> login(#ApiParam("Username") #RequestParam String username, //
#ApiParam("Password") #RequestParam String password) {
return ResponseEntity.ok(userService.signin(username, password));
}
#PostMapping("/signup")
public void signUp(#ApiParam("SignUp User") #RequestBody SignUpRequest request) {
User user = User.of(request.getUsername(), bCryptPasswordEncoder.encode(request.getPassword()), request.getEmail());
Role userRole = roleRepository.findByName(RoleName.ROLE_MEMBER).orElse(null);
user.setRoles(Collections.singleton(userRole));
userRepository.save(user);
}
WebSecurityConfig.java
#Configuration
#EnableWebSecurity
#EnableGlobalMethodSecurity(
prePostEnabled = true
)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
private final JwtTokenProvider jwtTokenProvider;
public WebSecurityConfig(JwtTokenProvider jwtTokenProvider) {
this.jwtTokenProvider = jwtTokenProvider;
}
#Override
protected void configure(HttpSecurity http) throws Exception {
// Disable CSRF (cross site request forgery)
http.csrf().disable();
// No session will be created or used by spring security
http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
// Entry points
http.authorizeRequests()//
.antMatchers("/api/users/signin").permitAll()//
.antMatchers("/api/users/signup").permitAll()//
.antMatchers("/api/test/**").permitAll()
.antMatchers("/h2-console/**/**").permitAll()
// Disallow everything else..
.anyRequest().authenticated();
// If a user try to access a resource without having enough permissions
http.exceptionHandling().accessDeniedPage("/login");
// Apply JWT
http.apply(new JwtTokenFilterConfigurer(jwtTokenProvider));
http.cors().disable();
// Optional, if you want to test the API from a browser
// http.httpBasic();
super.configure(http);
}
#Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder(10);
}
#Override
#Bean
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
}
JwtTokenFilter.java:
public class JwtTokenFilter extends OncePerRequestFilter {
private JwtTokenProvider jwtTokenProvider;
public JwtTokenFilter(JwtTokenProvider jwtTokenProvider) {
this.jwtTokenProvider = jwtTokenProvider;
}
#Override
protected void doFilterInternal(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, FilterChain filterChain) throws ServletException, IOException {
String token = jwtTokenProvider.resolveToken(httpServletRequest);
try {
if (token != null && jwtTokenProvider.validateToken(token)) {
Authentication auth = jwtTokenProvider.getAuthentication(token);
SecurityContextHolder.getContext().setAuthentication(auth);
}
} catch (CustomException ex) {
//this is very important, since it guarantees the user is not authenticated at all
SecurityContextHolder.clearContext();
httpServletResponse.sendError(ex.getHttpStatus().value(), ex.getMessage());
return;
}
filterChain.doFilter(httpServletRequest, httpServletResponse);
}
}
MyUserDetailsService.java:
#Service
public class MyUserDetailsService implements UserDetailsService {
#Autowired
private UserRepository userRepository;
#Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
final User user = userRepository.findByUsername(username).orElseThrow(() -> new CustomException("User doesn't exist", HttpStatus.NOT_FOUND));
List<GrantedAuthority> authorities = user.getRoles().stream().map(role ->
new SimpleGrantedAuthority(role.getName().getAuthority())
).collect(Collectors.toList());
if (user == null) {
throw new UsernameNotFoundException("User '" + username + "' not found");
}
return org.springframework.security.core.userdetails.User//
.withUsername(username)
.password(user.getPassword())
.authorities(authorities)
.accountExpired(false)
.accountLocked(false)
.credentialsExpired(false)
.disabled(false)
.build();
}
}
When I request to both of these links as I told above. It's done quickly by giving me 401 HTTP error code while testing on postman.
Both this link and this link are not helpful at all.
You might want to try excluding these URLs from the WebSecurity section, instead, so that they do not get processed by Spring Security and your JwtTokenFilter at all.
#Configuration
#EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Override
public void configure(final WebSecurity web) throws Exception {
web.ignoring()
.antMatchers("/api/users/signin").antMatchers("/api/users/signup");
}
}
I want to secure my API's based on the user role, but #PreAuthorize Annotations seem to not work properly. No matter what role the user has the server throws a 403 error. How to make this work ?
This is where I retrieve the User Details in my custom authentication provider:
#Override
protected UserDetails retrieveUser(String userName, UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken){
final String password = (String) usernamePasswordAuthenticationToken.getCredentials();
if (!StringUtils.hasText(password)) {
this.logger.warn("Username {}: no password provided", userName);
}
userName = parseCredentials(userName);
try {
DirContext ctx = ldapConfiguration.openConnection(userName, password);
ctx.close();
} catch (NamingException e) {
throw new LdapException("User not found in Active Directory", e);
} catch (NullPointerException e) {
throw new CredentialsNotProvidedException("Entered data may be null", e);
}
User user = userRepository.findOneByLogin(userName);
if (user == null) {
this.logger.warn("Username {}: user not found", userName);
throw new BadCredentialsException("Invalid Username/Password for user " + userName);
}
final List<GrantedAuthority> auths = new ArrayList<GrantedAuthority>();
GrantedAuthority r = (GrantedAuthority) () -> "ROLE_" + user.getRole().getName().toUpperCase();
auths.add(r);
// enabled, account not expired, credentials not expired, account not locked
UserDetails userDetails = new org.springframework.security.core.userdetails.User(userName, password, true, true, true, true, auths);
return userDetails;
}
This is the controller:
#PreAuthorize("hasRole('ROLE_HR')") //I don't have acces even if I am HR
#RestController
public class SettingsController {
#Autowired
private LocationRepository locationRepository;
#Autowired
private DepartmentRepository departmentRepository;
#Autowired
private RoleRepository roleRepository;
#RequestMapping(value = "/api/locations", method = RequestMethod.POST)
public ResponseEntity addLocation(#RequestBody Location location) {
if (location == null) {
return new ResponseEntity(HttpStatus.BAD_REQUEST);
}
locationRepository.save(new Location(location.getName()));
return new ResponseEntity(HttpStatus.CREATED);
}
#RequestMapping(value = "/api/roles", method = RequestMethod.POST)
public ResponseEntity addRole(#RequestBody Role role) {
if (role == null) {
return new ResponseEntity(HttpStatus.BAD_REQUEST);
}
roleRepository.save(new Role(role.getName()));
return new ResponseEntity(HttpStatus.CREATED);
}
#RequestMapping(value = "/api/departments", method = RequestMethod.POST)
public ResponseEntity addDepartment(#RequestBody Department department) {
if (department == null) {
return new ResponseEntity(HttpStatus.BAD_REQUEST);
}
departmentRepository.save(new Department(department.getName()));
return new ResponseEntity(HttpStatus.CREATED);
}
}
And security config:
#Configuration
#EnableWebSecurity
#EnableGlobalMethodSecurity(prePostEnabled = true)
#Order(SecurityProperties.ACCESS_OVERRIDE_ORDER)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
private DatabaseAuthenticationProvider authenticationProvider;
#Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/js/**", "/css/**", "/img/**");
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.formLogin().loginPage("/login").failureUrl("/login").defaultSuccessUrl("/")
.and().logout().logoutSuccessUrl("/login")
.and().authorizeRequests().antMatchers("/login").permitAll()
/*.antMatchers("/settings.html").access("hasRole('HR')")
.antMatchers("/pendingRequests.html").access("hasRole('MANAGER')")
.antMatchers("/settings.html","/pendingRequests.html").access("hasRole('ADMIN')")*/
.anyRequest().authenticated().and().csrf().disable();
}
#Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(authenticationProvider).eraseCredentials(false);
}
}
According to your commented line in security config class
.antMatchers("/settings.html").access("hasRole('HR')") user role is HR.
If role is HR then you should use
#PreAuthorize("hasRole('HR')")
and also #PreAuthorize should be placed first and then mention #RestController
#RestController
#PreAuthorize("hasRole('HR')")
public class SettingsController