Correct way of handling banned users

Disclaimer: I do not really understand fully, how Vaadin is wired to Spring security.

I have a requirement where banned users need to be gracefully kept out.
So I did the following.

  1. Downloaded a project with with authentication from the vaadin playground (https://start.vaadin.com)
  2. Modified the User.java to include private boolean banned = false; and the getter/setters
  3. Modified the UserDetailsServiceImpl#loadUserByUsername to throw a DisabledException if the user was banned
   @Override
    @Transactional
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        User user = userRepository.findByUsername(username)
                .orElseThrow(() -> new UsernameNotFoundException("No user present with username: " + username));

        if (user.isBanned()){
            throw new DisabledException("You are banned");
        }
        return new org.springframework.security.core.userdetails.User(user.getUsername(), user.getHashedPassword(),
                getAuthorities(user));
    }
  1. Declared a @Bean in SecurityConfiguration
    @Bean
    public AuthenticationManager authenticationManager(AuthenticationConfiguration config) throws Exception {
        return config.getAuthenticationManager();
    }
  1. Injected AuthenticationManager into the LoginView
  2. Disabled setAction in the LoginView
  3. In the LoginView, hooked up a login listener, to handle the DisabledException by showing the user a feedback dialog, else it pass the buck
        addLoginListener(loginEvent -> {
            try {
                var token = new UsernamePasswordAuthenticationToken(
                        loginEvent.getUsername(), loginEvent.getPassword());
                var authResult = authManager.authenticate(token);
                SecurityContextHolder.getContext().setAuthentication(authResult);

                // Successful login → navigate to main view
                UI.getCurrent().navigate("");
            } catch (AuthenticationException authenticationException) {
                //Check if this was caused by a DisabledException (banned user)
                Throwable cause = authenticationException.getCause();
                if (cause instanceof DisabledException) {
                    setOpened(false);
                    showDialog();
                } else {
                    setI18n(LoginI18n.createDefault());
                    setError(true); // show error box
                }
            }
        });
  1. Closing the dialog programatically logs out the user using authenticatedUser.logout(); which brings back the LoginView

Everything works fine as expected and the console is without any warning/error messages.

My question is: Is this the optimal way of handling this requirement or is there anything superior?

That looks really weird in a Spring Boot application. Vaadin’s LoginForm is build that it should work out-of-the-box with Spring Security. Only thing that is missing would be a Login Failure Listener that listens to your exception and redirects the user to e.g. /login?error=banned and an appropriate parameter handling on your login page depending on this error

1 Like

Your authentication system should not inform the user that an account name is present (or not present), regardless of banned status. The authentication system’s task is to ensure the user is who they claim to be, via password or some other means. What you want is a job for the authorization system; a banned user presumably has access only public content (or a page that simply informs them that they have been banned, etc.). Their identity doesn’t change; if you implement the possibility of reversing bans, that should not change your authentication.

5 Likes