I have multiple clients registered for my oauth2 auth server. I want to get the user authorities based on the clientId. Let's say USER-1 has authorities ADMIN for CLIENT-1 and for CLIENT-2 the USER-1 has USER authority.
I have tried this issue. But I always get a null request.
final HttpServletRequest request = ((ServletRequestAttributes)
RequestContextHolder.getRequestAttributes()).getRequest();
I have also added a WebListner, but with no luck.
#Configuration
#WebListener
public class MyRequestContextListener extends RequestContextListener {
}
#Service
public class DomainUserDetailsService implements UserDetailsService {
#Autowired
private UserRepository userRepository;
#Autowired
private AuthorityRepository authorityRepository;
#Override
#Transactional
public UserDetails loadUserByUsername(final String email) throws UsernameNotFoundException {
User user = userRepository.findUserByUserName(email);
if (user == null) {
new UsernameNotFoundException("Username not found");
}
String clientId = "?"; // How to get clientId here?
List<String> roles = authorityRepository.getUserAuthorities(email, clientId);
return new DomainUser(email, user.getCredential(), user.getId(), fillUserAuthorities(roles));
}
public Collection<SimpleGrantedAuthority> fillUserAuthorities(Collection<String> roles) {
Collection<SimpleGrantedAuthority> authorties = new ArrayList<SimpleGrantedAuthority>();
for (String role : roles) {
authorties.add(new SimpleGrantedAuthority(role.toUpperCase()));
}
return authorties;
}
}
If I am going in the wrong direction, any suggestions are acceptable.
Currently, I am using a Custom JWT Token Enhancer to achieve the requirement. But I am not sure if this is the right way of doing this. I am not sure why I'm thinking it is the wrong way. But you can achieve this using the below solution.
public class CustomTokenEnhancer implements TokenEnhancer {
#Autowired
private AuthorityRepository authRepository;
#Override
public OAuth2AccessToken enhance(OAuth2AccessToken accessToken, OAuth2Authentication authentication) {
Map<String, Object> additionalInfo = new HashMap<>();
DomainUser authPrincipal = (DomainUser) authentication.getPrincipal();
List<String> clientBasedRoles = authRepository.getUserAuthorities(authPrincipal.getId(),
authentication.getOAuth2Request().getClientId());
additionalInfo.put("authorities", clientBasedRoles);
((DefaultOAuth2AccessToken) accessToken).setAdditionalInformation(additionalInfo);
return accessToken;
}
}
Then, in your AuthorizationServerConfigurerAdapter.
#Configuration
#EnableAuthorizationServer
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
#Bean
public TokenEnhancer tokenEnhancer() {
return new CustomTokenEnhancer();
}
#Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
TokenEnhancerChain tokenEnhancerChain = new TokenEnhancerChain();
tokenEnhancerChain.setTokenEnhancers(Arrays.asList(tokenEnhancer(), accessTokenConverter()));
endpoints.authenticationManager(this.authenticationManager).accessTokenConverter(accessTokenConverter())
.tokenEnhancer(tokenEnhancerChain);
}
}
Related
I'm struggling with 401 unuathorized in postman while i try to enter a secured endpoint, I'm passing correct data, but spring security doesn't pass me on, I think I might miss something in DetailsService or somewhere Creating new user
Trying to authorize
Security config
#EnableWebSecurity
#RequiredArgsConstructor
#EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig {
private final CustomAuthProvider provider;
private final AuthenticationFailureHandler failureHandler;
#Bean
public AuthenticationManager authenticationManager (HttpSecurity http) throws Exception {
AuthenticationManagerBuilder builder = http.getSharedObject(AuthenticationManagerBuilder.class);
builder.authenticationProvider(provider);
return builder.build();
}
#Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http.csrf().disable().authorizeRequests(auth -> {
auth.antMatchers(HttpMethod.POST, "/register").permitAll();
auth.antMatchers(HttpMethod.POST, "/login").hasRole("USER");
auth.antMatchers("/user/**").permitAll();
auth.antMatchers("/getusers").hasRole("USER");
auth.antMatchers("/moderator/**").hasRole("MODERATOR");
auth.antMatchers("/admin/**").hasRole("ADMIN");
})
.httpBasic(withDefaults())
.sessionManagement()
.sessionCreationPolicy(STATELESS);
return http.build();
}
Details Service
#Service
#RequiredArgsConstructor // Generates a constructor with required arguments.
public class DetailsService implements UserDetailsService {
private final UserService userService;
#Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
var user = userService.findByUsername(username);
if (user == null) {
throw new UsernameNotFoundException("Couldn't find \""+ username +"\" username");
}
if (user.getRoles() == null || user.getRoles().isEmpty()) {
throw new RuntimeException("User \"" + username + "\" has no roles");
}
Collection<GrantedAuthority> authorities = user.getRoles().stream()
.map(role -> new SimpleGrantedAuthority(role.getName()))
.collect(Collectors.toList());
return new User(user.getUsername(), user.getPassword(), user.isActive(),
!user.isExpired(), !user.isCredentialsexpired(), !user.isBlocked(), authorities);
}
Method with creating roles
#RequiredArgsConstructor
#Component
public class ApplicationStartRunner implements CommandLineRunner {
private final RoleRepository roleRepository;
#Override
public void run(String... args) throws Exception {
Role roleUser = new Role(1L, "123", "ROLE_USER");
Role roleModerator = new Role(2L, "456", "ROLE_MODERATOR");
Role roleAdmin = new Role(3L, "789", "ROLE_ADMIN");
roleRepository.saveAll(List.of(roleUser, roleAdmin, roleModerator));
}
EDIT: That's my password encoder bean
#Configuration
public class SecurityConfig {
#Bean
PasswordEncoder encoder() {
return new BCryptPasswordEncoder();
}
}
And register method
#Override
public UserDTO createUser(RegisterDTO user) {
if (user.equals(userRepository.findByUsername(user.getUsername()))) {
throw new RuntimeException("This nickname is already taken");
}
if (user.equals(userRepository.findByEmail(user.getEmail()))) {
throw new RuntimeException("This email is already taken");
}
// Encoding password
user.setPassword(encoder.encode(user.getPassword()));
// On creating new Account it's going to have USER role
Role role = roleRepository.findByName("ROLE_USER");
String username = user.getUsername();
String password = user.getPassword();
String email = user.getEmail();
User dto = buildUser(username, password, email, role);
userRepository.save(dto);
return UserDTO.builder()
.username(username)
.password(password)
.email(email)
.build();
}
I think this is pretty clear.
That /getusers endpoint is protected and user must have USER role which obviously don't have. By default I think it should be ROLE_USER as spring is using that ROLE_ prefix. But you can specify any role that should be fetched from DB during user authorization.
So I followed some guides on spring security with usernames and passwords, however most of them show using "InMemoryUserDetailsManager" which they say should not be used in production:
#Bean
public InMemoryUserDetailsManager userDetailsManager(){
UserDetails admin = User.withDefaultPasswordEncoder()
.username("ADMIN")
.password("123")
.roles("ADMIN").build();
return new InMemoryUserDetailsManager(admin);
}
My questions, so how should a production level version of this be setup? Is it just not using the default password encoder because it is deprecated or should I use an entirely different method of adding and storing users?
You should implement jdbc authentication DaoAuthenticationProvider. Checkout https://www.baeldung.com/spring-security-jdbc-authentication.
Your user details must be stored in permanent storage, not temporary storage. Also, passwords must be encrypted to avoid compromising security. So using permanent storage you can take backup or data and run queries out of it.
You can implement custom user details service instead of using default.
#Service
public class CustomUserDetailsServiceImpl implements UserDetailsService {
private final UserRepository userRepository;
#Autowired
private PasswordEncoder passwordEncoder;
#Autowired
public CustomUserDetailsServiceImpl(UserRepository userRepository) {
this.userRepository = userRepository;
}
#Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
User user = userRepository.findByUsername(username);
if(user == null) {
throw ApiExceptionFactory.getApiException(ApiExceptionType.NOT_FOUND, "user");
}
return new org.springframework.security.core.userdetails.User(
user.getUsername(),
user.getPassword(),
user.getEnabled(),
true,
true,
true,
getAuthorities(user));
}
public Boolean isTokenValid(String token) {
try {
Jws<Claims> claimsJws = Jwts.parser().setSigningKey(SECRET.getBytes()).parseClaimsJws(token);
return true;
} catch (SignatureException | MalformedJwtException | UnsupportedJwtException | IllegalArgumentException ex) {
throw ApiExceptionFactory.getApiException(ApiExceptionType.LOGIN_FAILURE, "invalid credentials");
} catch (ExpiredJwtException ex) {
throw ApiExceptionFactory.getApiException(ApiExceptionType.LOGIN_FAILURE, "token expired");
}
}
#Transactional
public Boolean save(User user){
if(StringUtils.isEmpty(user.getUsername())) {
throw ApiExceptionFactory.getApiException(ApiExceptionType.BAD_REQUEST, "username");
}
if(StringUtils.isEmpty(user.getPassword())) {
throw ApiExceptionFactory.getApiException(ApiExceptionType.BAD_REQUEST, "password");
}
if(StringUtils.isEmpty(user.getEmail())) {
throw ApiExceptionFactory.getApiException(ApiExceptionType.BAD_REQUEST, "email");
}
User registeredUser = new User();
registeredUser.setUsername(user.getUsername());
registeredUser.setPassword(passwordEncoder.encode(user.getPassword()));
registeredUser.setEmail(user.getEmail());
registeredUser.setEnabled(true);
registeredUser.setRoles(user.getRoles());
User savedUser = userRepository.save(registeredUser);
Inventory userInventory = inventoryService.saveInventoryForUser(savedUser.getUsername());
return userInventory != null;
}
private Set<GrantedAuthority> getAuthorities(User user){
Set<GrantedAuthority> authorities = new HashSet<>();
for(Role role : user.getRoles()) {
GrantedAuthority grantedAuthority = new SimpleGrantedAuthority(role.getName().getRole());
authorities.add(grantedAuthority);
}
return authorities;
}
}
You can save user details into your repository.
#Repository
public interface UserRepository extends BaseRepository<User> {
User findByUsername(String username);
Boolean existsByUsername(String username);
Boolean existsByEmail(String email);
}
Finally add your user details into authentication manager with password encoder.
#Configuration
#EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
private UserRepository userRepository;
#Override
public void configure(AuthenticationManagerBuilder authenticationManagerBuilder) throws Exception {
authenticationManagerBuilder.userDetailsService(userDetailsServiceBean()).passwordEncoder(passwordEncoder());
}
#Override
public UserDetailsService userDetailsServiceBean() {
return new CustomUserDetailsServiceImpl(userRepository);
}
#Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}
For more details check my github repository
Hello Please Code as the following coding
#Bean
public InMemoryUserDetailsManager createUserDetailsManager() {
UserDetails userDetails1 = createNewUser("username1", "dummy");
UserDetails userDetails2 = createNewUser("username2", "dummydummy");
return new InMemoryUserDetailsManager(userDetails1, userDetails2);
}
private UserDetails createNewUser(String username, String password) {
Function<String, String> passwordEncoder
= input -> passwordEncoder().encode(input);
UserDetails userDetails = User.builder()
.passwordEncoder(passwordEncoder)
.username(username)
.password(password)
.roles("USER","ADMIN")
.build();
return userDetails;
}
Hope it help you
I'm working on Spring Boot Application that exposes a bundle of REST-APIS, was trying to apply a SecurityFilter, it wokred successfully but not entirely, i'm trying to consume those web services by roles and authorities, yet once logged in it doesn't care wether i have the access to that resource or not.
Spring Boot - Spring Security
Here is my Security code:
#Configuration
#EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
private UserDetailsService userDetailsService;
#Autowired
private BCryptPasswordEncoder bCyptPasswordEncoder;
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService).passwordEncoder(bCyptPasswordEncoder);
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable();
http.formLogin();
http.authorizeRequests().antMatchers("/login/**", "/register/**").permitAll();
http.authorizeRequests().antMatchers(HttpMethod.POST, "/studentResource/**").hasAuthority("ADMIN");
http.authorizeRequests().anyRequest().authenticated();
}
}
#Service
public class UserDetalsServiceImpl implements UserDetailsService {
#Autowired
private UnivAccountService accountService;
#Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
AppUser user = accountService.findByUsername(username);
if (user == null)
throw new UsernameNotFoundException(username);
Collection<GrantedAuthority> authorities = new ArrayList<>();
user.getAuRoles().forEach(r -> authorities.add(new SimpleGrantedAuthority(r.getRole())));
return new User(user.getAuUsername(), user.getAuPassword(), authorities);
}
}
My REST-API
#RestController
#RequestMapping(value = "/studentResource")
public class UnivStudentApi {
#Autowired
private UnivStudentService studentService;
#PostMapping(value = "/getStudentsBySearchCriteria")
public <T> Pagination<UnivStudentDto> getStudentsBySearchCriteria(#RequestBody SearchRequest searchRequest,
#RequestParam int page, #RequestParam int size) {
return studentService.getStudentsBySearchCriteria(searchRequest, page, size);
}
#PostMapping(value = "/getStudentByIden/{stdIden}")
public UnivStudentDto getStudent(String stdIden) {
return studentService.getStudent(stdIden);
}
#PostMapping(value = "/addLaboratory")
public UnivOperationResponse persistNewLaboratory(#RequestBody UnivLaboratoryDto univLab) {
return studentService.persistNewLaboratory(univLab);
}
#PostMapping(value = "/add")
public UnivOperationResponse persistStudent(#RequestBody UnivStudentDto student) {
return studentService.persistStudent(student, student.getUstLab().getUlaIden());
}
#PostMapping(value = "/merge")
public UnivOperationResponse mergeStudent(#RequestBody UnivStudentDto student) {
return studentService.mergeStudent(student);
}
#PostMapping(value = "/delete")
public UnivOperationResponse deleteStudent(#RequestBody Long studentIden) {
return studentService.deleteStudent(studentIden);
}
#GetMapping(value = "/getStudents")
public Pagination<UnivStudentDto> getStudents(#RequestParam int page, #RequestParam int size) {
return studentService.getStudents(page, size);
}
#GetMapping(value = "/getStudentsByKW/{KW}")
public <T> Pagination<UnivStudentDto> getStudentsByKeyWord(#PathVariable("KW") T t, #RequestParam int page,
#RequestParam int size) {
return studentService.getStudentsByKeyWord(t, page, size);
}
#PostMapping(value = "/findPhdDoc")
public UnivStudentDto getStudent(#RequestBody Long studentIden) {
return studentService.getStudent(studentIden.toString());
}
}
I have one User in my database : username : user, password user, ROLE : USER
For example if would want to access the following URL After a successful login:
http://localhost:8080/studentResource/getStudents?page=0&size=3
I expect 403 Forbidden Response Code, but it doesn't stop me, it renders the results as if i'm allowed to consume that method.
Thanks in advance for any answers, solutions.
I have successfully integrated Spring Security OAuth2 with my Open ID Connect provider (Forgerock OpenAM). I can see the access token being retrieved. How can I access the id_token and refresh_token which are part of the response from the /token endpoint?
Finally figured out answer and posting in case it is useful for someone with the same problem. After session is authenticated by Spring Security OAuth2, there is an Authentication Object setup. It needs to get casted to an instance of OAuth2Authentication. That object has the token.
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
if (auth instanceof OAuth2Authentication) {
Object details = auth.getDetails();
OAuth2AccessToken token = oauth2Ctx.getAccessToken();
if (token != null && !token.isExpired()) {
// Do Stuff
}
A complete example of an alternative approach (using Spring Boot and disabling part of its autoconfiguration).
application.properties:
security.oauth2.client.client-id=client-id
security.oauth2.client.client-secret=client-secret
security.oauth2.client.access-token-uri=http://my-oidc-provider/auth/oauth2/token
security.oauth2.client.user-authorization-uri=http://my-oidc-provider/auth/oauth2/authorize
security.oauth2.resource.token-info-uri=http://my-oidc-provider/auth/oauth2/check_token
security.oauth2.client.scope=openid,email,profile
security.oauth2.resource.jwk.key-set-uri=http://my-oidc-provider/auth/oidc/jwks
/**
* Extending the AuthorizationServerEndpointsConfiguration disables the Spring
* Boot ResourceServerTokenServicesConfiguration.
*/
#Configuration
#EnableOAuth2Sso
public class OAuth2Config extends AuthorizationServerEndpointsConfiguration {
#Value("${security.oauth2.resource.jwk.key-set-uri}")
private String keySetUri;
#Value("${security.oauth2.resource.token-info-uri}")
private String checkTokenEndpointUrl;
#Value("${security.oauth2.client.client-id}")
private String clientId;
#Value("${security.oauth2.client.client-secret}")
private String clientSecret;
#Bean
public RemoteTokenServices resourceServerTokenServices() {
RemoteTokenServices tokenService = new RemoteTokenServices();
DefaultAccessTokenConverter accessTokenConverter = new DefaultAccessTokenConverter();
accessTokenConverter.setUserTokenConverter(new CustomIdTokenConverter(keySetUri));
tokenService.setAccessTokenConverter(accessTokenConverter);
tokenService.setCheckTokenEndpointUrl(checkTokenEndpointUrl);
tokenService.setClientId(clientId);
tokenService.setClientSecret(clientSecret);
return tokenService;
}
#Bean
public ClientDetailsService clientDetailsService() {
return new InMemoryClientDetailsService();
}
#Bean
public UserInfoRestTemplateFactory userInfoRestTemplateFactory(
ObjectProvider<List<UserInfoRestTemplateCustomizer>> customizers,
ObjectProvider<OAuth2ProtectedResourceDetails> details,
ObjectProvider<OAuth2ClientContext> oauth2ClientContext) {
return new DefaultUserInfoRestTemplateFactory(customizers, details,
oauth2ClientContext);
}
}
public class CustomIdTokenConverter extends DefaultUserAuthenticationConverter {
private final JwkTokenStore jwkTokenStore;
public CustomIdTokenConverter(String keySetUri) {
this.jwkTokenStore = new JwkTokenStore(keySetUri);
}
#Override
public Authentication extractAuthentication(Map<String, ?> map) {
String idToken = (String) map.get("id_token");
OAuth2AccessToken token = jwkTokenStore.readAccessToken(idToken);
Map<String, Object> claims = token.getAdditionalInformation();
OAuth2RefreshToken refreshToken = token.getRefreshToken();
String principal = (String) claims.get("sub");
List<GrantedAuthority> authorities = AuthorityUtils.createAuthorityList("ROLE_USER");
return new CustomAuthenticationData(principal, claims, authorities);
}
}
public class CustomAuthenticationData extends UsernamePasswordAuthenticationToken {
private final Map<String, Object> attributes;
public CustomAuthenticationData(String username, Map<String, Object> attributes, Collection<? extends GrantedAuthority> authorities) {
super(username, "N/A", authorities);
this.attributes = attributes;
}
public Map<String, Object> getAttributes() {
return attributes;
}
}
I am using DaoAuthenticationProvider for authenciation but when I submit form loadUserByUsername is called twice by super.authenticate(authentication) intially it throws BadCredentialsException and then next time it login successfully
This process is working fine if I do not use passwordencoder but when I use it loadUserByUsername method is called twice.
Below is my code:
SecurityConfig
#Configuration
#EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
#Qualifier("authenticationProvider")
AuthenticationProvider authenticationProvider;
#Autowired
#Qualifier("userDetailsService")
UserDetailsService userDetailsService;
#Bean
public PasswordEncoder passwordEncoder() {
PasswordEncoder encoder = new BCryptPasswordEncoder();
return encoder;
}
#Autowired
public void configureGlobal(AuthenticationManagerBuilder auth)
throws Exception {
auth.authenticationProvider(authenticationProvider)
.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().antMatchers("/admin/**")
.access("hasRole('ROLE_ADMIN')").and().formLogin()
.loginPage("/login").failureUrl("/login?error")
.usernameParameter("username").passwordParameter("password")
.and().logout().logoutSuccessUrl("/login?logout").and().csrf()
.and().exceptionHandling().accessDeniedPage("/403");
}
}
Authentication class
#Component("authenticationProvider")
public class LimitLoginAuthenticationProvider extends DaoAuthenticationProvider {
#Autowired
#Qualifier("userDetailsService")
#Override
public void setUserDetailsService(UserDetailsService userDetailsService) {
super.setUserDetailsService(userDetailsService);
}
#Override
public Authentication authenticate(Authentication authentication)
throws AuthenticationException {
try {
System.out.println("inside authenticate");
Authentication auth = super.authenticate(authentication);
return auth;
} catch (BadCredentialsException be) {
System.out.println("First call comes here ");
throw be;
} catch (LockedException e) {
throw e;
}
}
}
MyUserdetailsService class implments UserDetailsService
#Service("userDetailsService")
public class MyUserDetailsService implements UserDetailsService {
#Autowired
private UserDao userDao;
/* below method is called twice if I am using passwordencoder,
initially authentication fails and then again immediately
on second call authentication succeed */
#Transactional(readOnly=true)
#Override
public UserDetails loadUserByUsername(final String username) throws UsernameNotFoundException {
com.mkyong.users.model.User user = userDao.findByUserName(username);
List<GrantedAuthority> authorities = buildUserAuthority(user.getUserRole());
return buildUserForAuthentication(user, authorities);
}
private User buildUserForAuthentication(com.mkyong.users.model.User user, List<GrantedAuthority> authorities) {
MyUserDetails myUserDetails = new MyUserDetails (user.getUsername(), user.getPassword(), user.isEnabled(), user.isAccountNonExpired(), user.isAccountNonLocked(), user.isCredentialsNonExpired(), user.getEmailId(),authorities);
return myUserDetails;
}
private List<GrantedAuthority> buildUserAuthority(Set<UserRole> userRoles) {
Set<GrantedAuthority> setAuths = new HashSet<GrantedAuthority>();
// Build user's authorities
for (UserRole userRole : userRoles) {
setAuths.add(new SimpleGrantedAuthority(userRole.getRole()));
}
List<GrantedAuthority> Result = new ArrayList<GrantedAuthority>(setAuths);
return Result;
}
}
Can some please help me. I believe there is some change needed in SecurityConfig class but exactly where I am not able to figure out.
Finally after help from java_dude and SergeBallesta I got the resolution for my query.
After a lot of debug I saw that when isPasswordValid method was getting called inside DaoAuthenticationProvider class instead of calling method 1 it was calling method 2 from org.springframework.security.authentication.encoding.PlaintextPasswordEncoder which one is depreciated and on second call it was calling proper isPasswordValid
method 1.
Method 1
public boolean isPasswordValid(String encPass, String rawPass, Object salt) {
checkSalt(salt);
return delegate.matches(rawPass, encPass);
}
Method 2
public boolean isPasswordValid(String encPass, String rawPass, Object salt) {
String pass1 = encPass + "";
// Strict delimiters is false because pass2 never persisted anywhere
// and we want to avoid unnecessary exceptions as a result (the
// authentication will fail as the encodePassword never allows them)
String pass2 = mergePasswordAndSalt(rawPass, salt, false);
if (ignorePasswordCase) {
// Note: per String javadoc to get correct results for Locale insensitive, use English
pass1 = pass1.toLowerCase(Locale.ENGLISH);
pass2 = pass2.toLowerCase(Locale.ENGLISH);
}
return PasswordEncoderUtils.equals(pass1,pass2);
}
To work authentication properly just add below code in your SecurityConfig class in addittion to my current code in question.
#Bean
public DaoAuthenticationProvider authProvider() {
// LimitLoginAuthenticationProvider is my own class which extends DaoAuthenticationProvider
final DaoAuthenticationProvider authProvider = new LimitLoginAuthenticationProvider();
authProvider.setUserDetailsService(userDetailsService);
authProvider.setPasswordEncoder(passwordEncoder());
return authProvider;
}
** and change this method code**
#Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(authProvider())
.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
}