Last updated: 2024-04-19

  1. Learn
  2. Spring Security
  3. Form Login

Form Login with Spring Boot and Thymeleaf

The form-based login is often the first choice to protect the web frontend of a Spring Boot application. It ensures that certain areas of our application are only accessible once a user has authenticated himself with a username and password, and this status is stored in the session. What are the steps required to add form based login to our Spring Boot application?

Start with a simple application

First, we use the Bootify Builder to create a simple Spring Boot application in the current version 3.3.1 - to do this, we simply click on start project. There we select Thymeleaf + Bootstrap as frontend stack - Thymeleaf is the most used template engine of Spring Boot and allows server-side rendering. Bootstrap will be integrated into our app as a WebJar. Select any database which you would like to connect to - an embedded database will do for now as well.

In the Entities Tab we create the tables User as well as TodoList, and connect them with an N:1 relation. For the TodoList we activate the CRUD option for the frontend - this will be the area we secure with Spring Security afterwards.

Preview of our very simple database schema

Preview of our very simple database schema

Now we can already download the finished application and import it into our favorite IDE.

The first version of our application in IntelliJ

The first version of our application in IntelliJ

Configuration of Spring Security

The form-based login is provided with the help of Spring Security. So we first need the relevant dependencies, which we add to our build.gradle or pom.xml respectively.

The module spring-boot-starter-security integrates Spring Security. With thymeleaf-extras-springsecurity6 a little helper is included which provides the authentication state in our Thymeleaf templates - more about that later.

With this we can already provide the central security configuration - here directly in our final version.

Our configuration for the form login

Theoretically, Spring Security can provide the login form with less configuration, but this would lack the design and some messages which we would like to present to the user. But let's go through the config first.

BCryptPasswordEncoder is standard nowadays to store the hash of a password together with its individual salt inside a single field. If we don't have a legacy requirement, we should use this one. Also, we provide the AuthenticationManager as a bean to be able to integrate it into other services.

As a third bean we create the SecurityFilterChain as this is the required approach since Spring 3.0. We should configure both CORS and CSRF properly to close the corresponding attack vectors. The default configuration is usually sufficient for this.

At our config class we have placed the annotation @EnableMethodSecurity and will protect the desired controller endpoints with @PreAuthorize(...) later on. Therefore we allow access to the whole application with permitAll(). Without the annotation based security, we should configure the paths to the protected resources at this place as well.

The formLogin() and the logout() methods are customized for our subsequent controller so that we can always display an appropriate message to the user. Spring Security automatically provides an endpoint for the login where username and password can be submitted to via POST request. Here we change the name of the username field to "email". The logout is modified to redirect back to the login page with a parameter afterwards.

Loading users from our database

To load the users from the already created table, we need to provide an implementation of UserDetailsService as a bean - it will be automatically found and used as a user source.

UserDetailsService implementation automatically used as the user source

In our repository we should add a method User findByEmailIgnoreCase(String email) to execute a search query against the database - ignoring upper/lower case allows the user small mistakes when writing their email. The role here is always ROLE_USER for each user. Since we don't have a registration endpoint available at this point, we can add a simple data loader along with our application for now. The profile "local" is required for it to become active.

Helper class to initialize a first user locally

Add login controller

With this we can already add the LoginController. Since the POST endpoint is automatically provided by Spring Security, a GET endpoint is sufficient here to show the template to the user.

Backend for rendering the login page

The request parameters that we had already specified in our security configuration are converted to corresponding messages here. In our simple application from Bootify the corresponding helpers are already included. Here we also need the AuthenticationRequest object with getters and setters.

The corresponding template for our controller could then look like this.

As Thymeleaf doesn't allow direct access to request object anymore, we're providing the requestUri in the model.

Providing the requestUri - as part of the AuthenticationController or a general ControllerAdvice

With this template we send a POST request to the /login endpoint. The INFO or ERROR messages are automatically displayed by the layout. All used messages have to be present in our messages.properties.

Last we can extend our layout.html. With this we also always show a login / logout link in the header. Spring Security also automatically provides a /logout endpoint, but we have to address it via POST.

Adding login / logout links to our layout

In the html tag we've extended the namespace to use the helpers from the thymeleaf-extras-springsecurity6 module. As a final step we only need to add the annotation @PreAuthorize("hasAuthority('ROLE_USER')") at our TodoListController.

Starting our application

With this we have all needed pieces of our puzzle together! Now we start our application and when we want to see the todo lists, we should be redirected to the login page. Here we can log in with [email protected] / testtest.

Automatic redirect to the login

Automatic redirect to the login

In the Free plan of Bootify, Spring Boot prototypes with its own database schema, REST API and frontend can be generated. In the Professional plan, among other things, Spring Security with the form-based login is available to generate the setup described here - exactly matching the created database and the selected settings. A registration endpoint and role source can be specified as well.

See Pricing
or read quickstart