Simple Access Control in Vaadin
Posted 30 Jan 2020 by Erik Lumme
Some things are best kept secret. This goes for data too. In this tutorial, you will learn how to implement a simple access-control system using plain Vaadin and Java.
We do this in four steps: create the login view, authorize the user, authenticate the user, and create the logout button.
This tutorial does not cover how the user credentials are stored, nor how to protect static resources, such as CSS and images.
The methods used here can be applied to most Vaadin projects, but they are written for the Plain Java Servlet starter found at vaadin.com/start, which at the time of writing uses Vaadin version
After downloading and unzipping the project, it can be run using
mvn jetty:run from the command line. The application and the MainView are then accessible at
Creating the login screen
Logging in requires a login screen. For simplicity’s sake, we use Vaadin’s LoginForm.
Let’s create a class,
LoginView, that extends
VerticalLayout, and has a private field containing the
It’s good practice to defer component initialization until it is attached. This avoids potentially running costly code for a component that is never displayed to the user. Due to Flow bug #4595, in some Vaadin versions the constructor is run even when access to the component is restricted through the
We can do the initialization by overriding the
onAttach method. To only run it once, we check if this is the first attach event, using the
We can then create the initialization method, where we instantiate the login form. We align the form in the center, both horizontally and vertically, and then hide the Forgot password? option from the login form before adding it to the layout.
To enable navigating to the view, we annotate it with
@Route. When no route is specified, the route will be the class name without “view”, in this case
The login event can be handled by this view by implementing
ComponentEventListener<AbstractLogin.LoginEvent>, and in the initialization method by adding the view as a listener using
For now, the component event listener method can just set an error on the form, which displays a message that the username or password is incorrect.
After rebuilding or restarting the application, we can now navigate to
http://localhost:8080/login, and see that no matter the username and password we enter, we always get an error message.
Authorizing the user
Authorization is the process of determining if a user can perform a particular action. In our case, a user is authorized to access any view if the user is authenticated. Authorization is done before entering any view.
Let’s start by creating a class
SecurityService, that is responsible for checking if the user is authenticated. We make this a singleton class by creating a private constructor, and returning a static instance in a
The getInstance() method may be synchronized to protect against creating multiple instances due to concurrent access. In this case, as no state is stored in the class, we omit it to improve performance.
When the user logs in, we store the username as a session attribute under an arbitrary key. As such, we can check if the user is logged in by checking if that attribute is set.
Next, we need to call this method before entering any view. For this, we utilize a
BeforeEnterListener added to every
UI. We can use a VaadinServiceInitListener to add it whenever a
UI is created.
We create a class implementing the
VaadinServiceInitListener interface, and implement the
For this to be registered on startup, we must create the
src/main/resources/META-INF/services/ directory and add a file named
com.vaadin.flow.server.VaadinServiceInitListener. The only content in the file should be the fully qualified name of our service init listener, in our case,
Now that we have hooked onto the service initialization, we can use the initialization event to listen for
UI initializations. Next, we change our class to also implement
UIInitListener, and register it through the
We now go further down the rabbit hole by implementing the uiInit method to add the class as a BeforeEnterListener to the newly created UI. For this, we also need to implement BeforeEnterListener.
Finally, we implement the
beforeEnter method to check if the user is authenticated, and if not, forward the user to the login view.
When navigating to the
LoginView, the code includes a special case to avoid getting stuck in the loop of repeatedly forwarding the user to
LoginView, by triggering the
beforeEnter method again and again.
Instead, if the user is logged in, they are forwarded to the
MainView. No action is taken otherwise.
Running the application now, you can see that the
MainView is no longer accessible, and navigating to
http://localhost:8080 forwards you to the login view.
Authenticating the user
Now we can move on to authenticating the user, by determining if the provided username and password is correct or not.
We add a method to the
authenticate, that takes a username and password as arguments, and returns
true if the authentication is successful. If this is the case, it also stores the username in the session.
This tutorial does not cover the authentication process in detail, instead we store the username and password directly in the class file. This means that anyone with access to the source code can see the credentials. As a minimum, the password should be hashed using a hashing function like
In the login view, we call this method, and only set an error if the method returns false. Otherwise, we redirect the user to the
MainView. As we have now hardcoded the value
MainView.class twice in the project, we should add a method in the security service that returns the default view, and change the prior uses to use this new method.
At this point, we can log in to the application with the credentials
password. We can not yet log out, however.
To be able to log out, we need a method in the
SecurityService for logging out. This method does two things:
- It invalidates the wrapped
HttpSession, closing all
VaadinSessioninstances that it contains. This causes a new
VaadinSessionto be created upon the next navigation, effectively clearing the stored user.
- It redirects the user to the login view.
All servlets in a WAR-file share the same
HttpSession, but have their own
VaadinSession instances. If you only want to close a particular Vaadin session, call
Now we need to call this method from somewhere. We can add a button for logging out to the
MainView, and at the same time move all initialization to
onAttach, as we did in the login view. We also remove the default components from the main view.
The button simply calls the
logOut method. We set the left margin to
auto, in order to float the button to the right.
When we now test the application, we cannot access the
MainView at first. After logging in, but only with the correct credentials, we are forwarded to the main view. Navigating to the login view now brings us right back to the main view.
After clicking the logout button, we can no longer access the main view, unless we log in again.
Congratulations, access control is now set up in your application!
The complete code can be found on GitHub.