Spring Security: Email Verification Registration

Overview

The first action a customer takes after visiting a website is creating an account, usually to place an order, book an appointment, pay for a service, etc. When creating an account it is important to persist the correct email address in the system and verify the user's ownership.

A common and effective strategy to do this is to send a confirmation link to the user's email post registration. Once the user clicks on the unique link, their account gets activated and they can undertake further actions on the website.

Spring allows us to implement this functionality easily, which is exactly what we'll be doing in this article.

Project Setup

As always, it's easiest to start off with a pre-configured Spring Boot project using Spring Initializr. Select dependencies for Web, Security, Mail, JPA, Thymeleaf and MySQL and generate the project:

We'll be using Spring Security and Spring MVC for this project. For the Data Layer, we'll be using Spring Data as it already provides us with CRUD operations for a given entity and dynamic query derivation from repository method names.

ConfirmationToken has a one-to-many relationship with the User entity. Since we set jpa.generate-ddl to true, Hibernate creates the table schema as per the above entities.

Primary keys in both the tables is set to auto-increment because we have annotated the ID columns in both classes with @Generated(strategy = GenerationType.AUTO).

Here is how the generated schema looks like in the database:

Now that the JPA configuration is done we will proceed to write the Data Access Layer. For that we will be using Spring Data as it provides basic CRUD operations out of the box which will be enough for the sake of this example.

Also, when using Spring Data it frees the code of the boiler-plate like getting the entity-manager or getting sessions, etc:

Spring Data automatically provides implementation for querying databases on the basis of an attribute, provided we follow Java Bean specifications. For an example, in our POJO, we have emailId as a bean property and we want to find the User by that property irrespective of the case.

Similarly, we implement the repository for the ConfirmationToken as well:

registerUser() - Accepts the user details entered on the registration page. Spring MVC automatically makes the user input available to us in the method.

We save the user details in the user table and create a random confirmation token. The token is saved with the user's emailId in the confirmation_token table, and sent via a URL to the user's email for verification.

Spring Security Configuration

Let's now configure the Spring Security module to secure our web-application. We need to make sure that no authentication is required for /register and /confirm URLs as they are the landing pages for a new user:

The @SpringBootApplication annotation directs Spring Boot to load all the configuration and component classes and also enables auto-configuration. This is one of the great features of Spring Boot, we can run it using a simple main method.

Running the Application

We begin the testing by selecting and running the RunApplication.java. This starts the embedded Tomcat server on port 8082 and our application gets deployed.

Next, let's open the browser and access our application:

Upon entering the required information, the user will submit:

Upon submission, an email is sent to the user in order to verify the email:

Following the link, the account is verified using a unique token, and the user is redirected to the success page:

This is how it looks like in the database:

Conclusion

Email verification is a very common requirement for web applications. Almost any kind of registration requires a verified email account, especially if the user enters any kind of sensitive information into the system.

In this article, we wrote a simple Spring Boot application to generate unique tokens for new users, send them an email, and verify them in our system.

If you're interested in playing with the source code, as always, it's available on GitHub