title: Questions about Spring Security
body: <p>I am actually beginner in Spring framework. For today i've faced with problems and i want ask you a couple questions to figure it out.</p>
  
  <p>I want to make simple user login/authorisation app with Android client.</p>
  
  <p>First of all I want to post my code:</p>
  
  <p>Model:</p>
  
  <pre><code>@Entity
  @Table(name = "Users")
  public class User {
      public User() {
      }
  
      @Id
      @GeneratedValue(generator = "increment")
      @GenericGenerator(name = "increment", strategy = "increment")
      @Column(name = "Id", unique = true, nullable = false)
      private long id;
  
      @Column(name = "userName", nullable = false)
      private String userName;
  
      @Column(name = "userPassword", nullable = false)
      private String userPassword;
  
      @Transient
      private String confirmPassword;
  
  
      public long getId() {
          return id;
      }
  
      public String getUsername() {
          return userName;
      }
  
      public String getPassword() {
          return userPassword;
      }
  
      public String getConfirmPassword() {
          return confirmPassword;
      }
  
      public void setId(long id) {
          this.id = id;
      }
  
      public void setName(String userName) {
          this.userName = userName;
      }
  
      public void setPassword(String userPassword) {
          this.userPassword = userPassword;
      }
  
      public void setConfirmPassword(String confirmPassword) {
          this.confirmPassword = confirmPassword;
      }
  }
  </code></pre>
  
  <p>Services:</p>
  
  <p>User details:</p>
  
  <pre><code>@Service("userDetailsServiceImpl")
  public class UserDetailsServiceImpl implements UserDetailsService {
  
      @Autowired
      private UserRepository userRepository;
  
  
      @Override
      @Transactional(readOnly = true)
      public UserDetails loadUserByUsername(String userName) throws UsernameNotFoundException {
          User user = userRepository.findByUserName(userName);
  
          Set&lt;GrantedAuthority&gt; grantedAuthorities = new HashSet&lt;GrantedAuthority&gt;();
  
          return new org.springframework.security.core.userdetails.User(user.getUsername(), user.getPassword(), grantedAuthorities);
      }
  }
  </code></pre>
  
  <p>Impl of <code>UserSerice</code> interface:</p>
  
  <pre><code>@Service
  public class UserServiceImpl implements UserService {
  
      @Autowired
      private UserRepository userRepository;
  
      @Autowired
      private BCryptPasswordEncoder passwordEncoder;
  
  
      public void save(User user) {
          user.setPassword(passwordEncoder.encode(user.getPassword()));
          userRepository.save(user);
      }
  
      public User findByUserName(String userName) {
          return userRepository.findByUserName(userName);
      }
  }
  </code></pre>
  
  <p>User validator:</p>
  
  <pre><code>@Component
  public class UserValidator implements Validator {
  
      @Autowired
      private UserService userService;
  
  
      @Override
      public boolean supports(Class aClass) {
          return User.class.equals(aClass);
      }
  
      @Override
      public void validate(Object o, Errors errors) {
          User user = (User) o;
  
          ValidationUtils.rejectIfEmptyOrWhitespace(errors, "username", "Required");
  
          if (user.getUsername().length() &lt; 8 || user.getUsername().length() &gt; 32) {
              errors.rejectValue("username", "Size.userForm.username");
          }
  
          if (userService.findByUserName(user.getUsername()) != null) {
              errors.rejectValue("username", "Duplicate.userForm.username");
          }
  
          ValidationUtils.rejectIfEmptyOrWhitespace(errors, "password", "Required");
          if (user.getPassword().length() &lt; 8 || user.getPassword().length() &gt; 32) {
              errors.rejectValue("password", "Size.userForm.password");
          }
  
          if (!user.getConfirmPassword().equals(user.getPassword())) {
              errors.rejectValue("confirmPassword", "Different.userForm.password");
          }
      }
  }
  </code></pre>
  
  <p>Impl of <code>SecurityService</code></p>
  
  <pre><code>@Service
  public class SecurityServiceImpl implements SecurityService {
      @Autowired
      private AuthenticationManager authenticationManager;
  
      @Autowired
      private UserDetailsService userDetailsService;
  
      @Override
      public String findLoggedInUsername() {
          Object userDetails = SecurityContextHolder.getContext().getAuthentication().getDetails();
          if (userDetails instanceof UserDetails) {
              return ((UserDetails) userDetails).getUsername();
          }
  
          return null;
      }
  
      @Override
      public void autoLogin(String username, String password) {
          UserDetails userDetails = userDetailsService.loadUserByUsername(username);
          UsernamePasswordAuthenticationToken authenticationToken =
                  new UsernamePasswordAuthenticationToken(userDetails, password, userDetails.getAuthorities());
  
          authenticationManager.authenticate(authenticationToken);
  
          if (authenticationToken.isAuthenticated()) {
              SecurityContextHolder.getContext().setAuthentication(authenticationToken);
  
          }
      }
  }
  </code></pre>
  
  <p>SecurityConfig:</p>
  
  <pre><code>@Configuration
  @EnableWebSecurity
  @EnableGlobalMethodSecurity(securedEnabled = true)
  @ComponentScan("com.webserverconfig.user")
  public class SecurityConfig extends WebSecurityConfigurerAdapter {
  
      @Autowired
      @Qualifier("userDetailsServiceImpl")
      UserDetailsService userDetailsService;
  
  
      @Autowired
      public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
          auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
      }
  
      @Bean
      public PasswordEncoder passwordEncoder() {
          PasswordEncoder encoder = new BCryptPasswordEncoder();
          return encoder;
      }
  
      @Bean
      @Override
      public AuthenticationManager authenticationManagerBean() throws Exception {
          return super.authenticationManagerBean();
      }
  }
  </code></pre>
  
  <p>And the lsat one -> Controller:</p>
  
  <pre><code>@RestController
  @RequestMapping("/user")
  public class UserController {
  
      @Autowired
      private UserService userService;
  
      @Autowired
      private SecurityService securityService;
  
      @Autowired
      private UserValidator userValidator;
  
  
      @RequestMapping(value = "/registration", method = RequestMethod.POST)
      @ResponseBody
      @ResponseStatus(value = HttpStatus.CREATED)
      public User registration(@RequestBody User user, BindingResult bindingResult, Model model) {
          userValidator.validate(user, bindingResult);
  
          if (bindingResult.hasErrors()) {
              //What should i return here to my Android client ?
          }
  
          userService.save(user);
  
          securityService.autoLogin(user.getUsername(), user.getConfirmPassword());
  
          return user;
  
      }
  
  }
  </code></pre>
  
  <p>I am missing some classes here for saving space.</p>
  
  <p>I am asking you for help me with my questions, please:</p>
  
  <p>1) When i am trying to send JSON using Postman:</p>
  
  <pre><code>{
    "id": 1,
    "userName": "Andrew",
    "userPassword": "apoyark123",
    "confirmPassword": "apoyark123"
  }
  </code></pre>
  
  <p>I am getting next erorr:</p>
  
  <pre><code>DefaultHandlerExceptionResolver - Failed to read HTTP message: org.springframework.http.converter.HttpMessageNotReadableException: Could not read document: Unrecognized field "userName" (class com.webserverconfig.user.entity.User), not marked as ignorable (4 known properties: "id", "name", "password", "confirmPassword"])
   at [Source: java.io.PushbackInputStream@ddd416; line: 3, column: 16] (through reference chain: com.webserverconfig.user.entity.User["userName"]); nested exception is com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field "userName" (class com.webserverconfig.user.entity.User), not marked as ignorable (4 known properties: "id", "name", "password", "confirmPassword"])
   at [Source: java.io.PushbackInputStream@ddd416; line: 3, column: 16] (through reference chain: com.webserverconfig.user.entity.User["userName"])
  </code></pre>
  
  <p>Am i missing some annotation ? </p>
  
  <p><strong>This issue resolved by Mehdi in the first comment. !!!</strong></p>
  
  <p><strong>Please help me with second question.</strong></p>
  
  <p>2) I am haven't tested security validation part yet, because this code doesn't working, but i have a question -> How my client will understand that login/authorisation have gone wrong/good ?</p>
  
  <p>If we take a look on controller's method <code>registration(...)</code> -> what should i return to the client if first "if" false ?</p>
  
  <p>What if validation is not correct ? What should i return to the client and how ?</p>