Collectives™ on Stack Overflow
Find centralized, trusted content and collaborate around the technologies you use most.
Learn more about Collectives
Teams
Q&A for work
Connect and share knowledge within a single location that is structured and easy to search.
Learn more about Teams
I use SpringSecurity in my web-project. When I try to login with username and password, I have this error in my stacktrace :
class org.springframework.security.core.userdetails.User cannot be cast to class com.cesi.cuberil.service.JwtUser (org.springframework.security.core.userdetails.User and com.cesi.cuberil.service.JwtUser are in unnamed module of loader 'app')
at com.cesi.cuberil.controller.AuthController.login(AuthController.java:116) ~[classes/:na]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:na]
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
at java.base/java.lang.reflect.Method.invoke(Method.java:566) ~[na:na]
at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:197) ~[spring-web-5.3.2.jar:5.3.2]
Below, I will put classes where I think the problem comes from.
Here my JwtUser.java :
package com.cesi.cuberil.service;
import com.cesi.cuberil.model.User;
import lombok.Data;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import java.util.Collection;
@Data
public class JwtUser implements UserDetails {
private final String username;
private final String password;
private final boolean enabled;
private final Collection<? extends GrantedAuthority> authorities;
private static final long serialVersionUID = 1L;
private User user;
public JwtUser(String username, String password, Boolean enabled, Collection<? extends GrantedAuthority> authorities) {
this.username = username;
this.password = password;
this.enabled = enabled;
this.authorities = authorities;
public User getUser() {
return user;
public void setUser(User user) {
this.user = user;
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return authorities;
@Override
public String getPassword() {
return password;
@Override
public String getUsername() {
return username;
@Override
public boolean isAccountNonExpired() {
return true;
@Override
public boolean isAccountNonLocked() {
return true;
@Override
public boolean isCredentialsNonExpired() {
return true;
@Override
public boolean isEnabled() {
return enabled;
Here my AuthController.java :
@RestController
@RequestMapping("/api/v1/auth")
@AllArgsConstructor
public class AuthController {
@Autowired
AuthenticationManager authenticationManager;
@Autowired
PasswordEncoder encoder;
@Autowired
JwtUtils jwtUtils;
@PostMapping("/login")
public ResponseEntity<?> login(@Valid @RequestBody LoginRequest loginRequest) {
Authentication authentication = authenticationManager.authenticate(
new UsernamePasswordAuthenticationToken(loginRequest.getUsername(), loginRequest.getPassword()));
SecurityContextHolder.getContext().setAuthentication(authentication);
String jwt = jwtUtils.generateJwtToken(authentication);
JwtUser myUserDetails = (JwtUser) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
List<String> roles = myUserDetails.getAuthorities().stream()
.map(item -> item.getAuthority())
.collect(Collectors.toList());
return ResponseEntity.ok(new JwtResponse(jwt, myUserDetails.getUser().getUserId(), myUserDetails.getUsername(), myUserDetails.getUser().getEmail(), roles));
Here my UserDetailsServiceImpl.java :
@Service
@AllArgsConstructor
public class UserDetailsServiceImpl implements UserDetailsService {
@Autowired
private UserRepository userRepository;
public User getByUsername(String username) {
return userRepository.findByUsername(username);
@Override
@Transactional(readOnly = true)
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
User user = this.getByUsername(username);
if (user == null) {
throw new UsernameNotFoundException("user not found");
} else {
List<GrantedAuthority> listAuthorities = new ArrayList<GrantedAuthority>();
listAuthorities.add(new SimpleGrantedAuthority("ROLE_USER"));
return new org.springframework.security.core.userdetails.User(username, user.getPassword(), true, true, true, true, listAuthorities);
For information, I use java 11 and the lastest version of Spring Boot.
The problem lies on the return
statement of UserDetailsServiceImpl.loadUserByUsername(..)
. Of course you can not cast User
to JwtUser
object since they are completely different. You should return the object you created extending UserDetails
, which in your case is JwtUser
.
The following will solve it:
@Override
@Transactional(readOnly = true)
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
User user = this.getByUsername(username);
if (user == null) {
throw new UsernameNotFoundException("user not found");
} else {
List<GrantedAuthority> listAuthorities = new ArrayList<GrantedAuthority>();
listAuthorities.add(new SimpleGrantedAuthority("ROLE_USER"));
return new JwtUser(username, user.getPassword(), true, listAuthorities); // NOTE here
I think you should return JwtUser
instance instead of org.springframework.security.core.userdetails.User
. Cause JwtUser
already implements UserDetails
interface.
Here's an sample.
a cast from one object to another is only possible if there exists a inheritance relationship between these two classes. In your case both classes implements the same interface but there is no inheritance relationship between the class org.springframework.security.core.userdetails.User and your JwtUser.
I think the problem here is a bad use of Spring Security. You are setting the the Authentication in the SecurityContextHolder, calling directly the AuthenticationManager and later calling even the Principal instead of the Authentication from the SecurityContextHolder. I recommend you to do it more in a Standard way, using LoginAuthentication and adding in the Spring Security configuration the successHandler() event, where you can write your own implementation that writes the JwtResponse in the response object.
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.