java.lang.ClassCastException: org.springframework.security.core.userdetails.User cannot be cast to model.User

Instead of using

User loggedInUser = (User)SecurityContextHolder.getContext().getAuthentication().getPrincipal();

try this

Authentication loggedInUser = SecurityContextHolder.getContext().getAuthentication();
String username = loggedInUser.getName();

References: https://www.mkyong.com/spring-security/get-current-logged-in-username-in-spring-security/


Fixed the issue

Solution

Created a CustomUserDetail class which implements Spring's UserDetails interface. Injected my model User class in it.

public class CustomUserDetail implements UserDetails{

    private static final long serialVersionUID = 1L;
    private User user;

    Set<GrantedAuthority> authorities=null;

    public User getUser() {
        return user;
    }

    public void setUser(User user) {
        this.user = user;
    }

    public Collection<? extends GrantedAuthority> getAuthorities() {
        return authorities;
    }

    public void setAuthorities(Set<GrantedAuthority> authorities)
    {
        this.authorities=authorities;
    }

    public String getPassword() {
        return user.getPassword();
    }

    public String getUsername() {
        return user.getProfileName();
    }

    public boolean isAccountNonExpired() {
        return user.isAccountNonExpired();
    }

    public boolean isAccountNonLocked() {
        return user.isAccountNonLocked();
    }

    public boolean isCredentialsNonExpired() {
        return user.isCredentialsNonExpired();
    }

    public boolean isEnabled() {
        return user.isAccountEnabled();
    }

}

CustomUserServiceDetails

public class CustomUserDetailsService implements UserDetailsService {

    @Autowired
    private UserDAO userDAO;

    public CustomUserDetail loadUserByUsername(String name) throws UsernameNotFoundException, DataAccessException {
        // returns the get(0) of the user list obtained from the db
        User domainUser = userDAO.getUser(name);


        Set<Role> roles = domainUser.getRole();
        logger.debug("role of the user" + roles);

        Set<GrantedAuthority> authorities = new HashSet<GrantedAuthority>();
        for(Role role: roles){
            authorities.add(new SimpleGrantedAuthority(role.getRole()));
            logger.debug("role" + role + " role.getRole()" + (role.getRole()));
        }

        CustomUserDetail customUserDetail=new CustomUserDetail();
        customUserDetail.setUser(domainUser);
        customUserDetail.setAuthorities(authorities);

        return customUserDetail;

    }

}

In my controller method

CustomUserDetail myUserDetails = (CustomUserDetail) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        Integer userId=myUserDetails.getUser().getUserId(); //Fetch the custom property in User class

The method .getPrincipal() returns the object created and returned it in the method loadUserByUsername.

If you want an User you must return in the method loadUserByUsername an User, not an org.springframework.security.core.userdetails.User