Codementor Events

A Simple User Authentication API made with Spring Boot

Published Nov 27, 2020

These days its easier than ever to make a proper application that can do what you need it to do. There are thousands of application development frameworks out there, in whatever programming language you are currently using. Spring is one of those frameworks that you can use to develop your dream application, website or server.

Spring is a popular application development framework, developed for the enterprise edition of the Java programming language. According to the Spring website: “Spring makes programming Java quicker, easier, and safer for everybody. Spring’s focus on speed, simplicity, and productivity has made it the world’s most popular Java framework.” MySQL is an open-source relational database management system. It is the database that we will be using to store our registered users. Swagger is an open-source project used to describe and document our API.

The side effect of such a big and popular framework is that is can sometimes be daunting to approach it and start learning how it works. Usually it helps if you have some idea of what you want to do with the framework but following a step-for-step guide is just as useful. So, today we are gonna build a very basic User Authentication API, which will allow the user to register new users and also login. This will by no means be a project from which you can build the back-end of your new business or personal project, but it will give you a foot in the door of the Spring framework.

To start off you will need a few things installed on your computer:

  • You will need to have a Java JDK installed on your system. You can find the instructions for installing the JDK here.
  • You will need an Integrated Development Environment installed. Personally I would recommend IntelliJ IDEA Community Edition.
  • You will need a terminal and the Curl CLI. If you are on MacOS or Linux, then you should be covered. If you are on Windows then you can either try installing Curl or you can use the Windows Subsystem for Linux, this will just allow you to use the Linux terminal on windows.
  • Lastly, we need to install MySQL. You can follow the steps that they gave on their website.

Once you have your development environment up and running you can head over to the Spring Initializr page. This site is used to create the basic startup package for your application so that you have to do less to achieve more. If you wanna follow along precisely then you should setup your project as follows:

The way I have my project set up is as follows:

  • Project: Maven Project.
  • Language: Java.
  • Spring Boot: 2.4.0
  • Group: (Left empty).
  • Artifact: tutorial.
  • Name: tutorial.
  • Description: Basic user authentication application made using Spring and Spring Boot.
  • Package name: .tutorial
  • Packaging: Jar
  • Java: 8
  • Dependencies: Spring Web, MySQL Driver, Spring Data JPA

The dependencies aren’t as important because I will give you a list of the dependencies that we will use, as to ensure that we are both on the same page with the project. Once you have everything selected you can click on “Generate”. This will create a zip file that you should download and unzip into your development folder. Import the project into your IDE of choice. If you are using IntelliJ the steps for importing the project is as follows:

  • Open IntelliJ.
  • Click on “Open or Import”.
  • Navigate to the file that you just unzipped.
  • Click on it once, as to highlight it, then click on “Okay”.

The project will be imported into your IDE and it should start off by downloading the dependencies and indexing your files so that it will know how to setup your project. Feel free to explore around, look in all the folders and open up a few files, just be sure to not accidentally change any files, as that might lead to your project not being able to compile.

Open up the file called “TutorialApplication”. This is your main file. When you run the program it will start here before running the other files. Take a moment to just look at the file and try to see if you can understand what is going on there. Don’t forget to also realize that you have technically created your first Spring application. Before we can run the program we have to edit some files first. So go into “src/main/resources”, and double click on “application.properties”. This is where your application properties are kept, as the name indicates. Type this into the file:

spring.datasource.url = jdbc:mysql://localhost:3306/users
spring.datasource.username = USERNAME
spring.datasource.password = PASSWORD
spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQL5InnoDBDialect
spring.jpa.hibernate.ddl-auto = update

springdoc.api-docs.path=/api-docs

So what this block of code sets the path to the database as “jbdc:mysql://localhost:3306/users” (the database is hosted on the computer at port 3306, and we are specifically interested in the “users” database). We set the username, you will have to set the username you setup, usually it is “root”. Next we set the password for our database, you will put your password here. In the next two lines we just say how the Spring framework should interact with the database and that we wanna be able to update the database when we work with it. The last line is a lot less important, it just points to the new path of our API documentation.

See that wasn’t so bad, although it wasn’t very interesting either. You can now close that file, we won’t be touching on it again in this tutorial. Next open the “pom.xml” file in your main folder. This is another file that handles your project setup. It is also where we state what dependencies we are gonna use. I am not gonna explain what each dependency does, since we’ll be here all day if we did that.

Find the “<dependencies></dependencies> bracket, it should be between line 21 and 41. Once you found it you can replace it with this block of code:

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-jpa</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-devtools</artifactId>
  <scope>runtime</scope>
  <optional>true</optional>
    </dependency>
    <dependency>
  <groupId>mysql</groupId>
  <artifactId>mysql-connector-java</artifactId>
  <scope>runtime</scope>
    </dependency>
    <dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-test</artifactId>
  <scope>test</scope>
    </dependency>
    <dependency>
  <groupId>javax.validation</groupId>
  <artifactId>validation-api</artifactId>
  <version>2.0.1.Final</version>
    </dependency>
    <dependency>
  <groupId>org.springdoc</groupId>
  <artifactId>springdoc-openapi-ui</artifactId>
  <version>1.2.32</version>
    </dependency>
</dependencies>

Once you saved your project there will popup an “m” with a reload icon on it. Click on it. It will download the dependencies and ensure that everything is valid. The last thing we need to do is create the “users” database. Open up your terminal and type in this command:

mysql -u root -p

It will ask you for your password, enter the password. You should now see something like this:

Next type this command to show all your active databases:

SHOW DATABASES;

Remember to add the semi-colon on the end otherwise it will just go on to the next line, I have made that mistakes so many times now. You should now see a table with all your databases. Next lets create the users database. Type this command:

CREATE DATABASE users;

This will create the new users database. That should be all we have to do to setup the database. You can now type

exit

to exit out of the MySQL terminal. Go back to your IDE and open up “TutorialApplication”, its under “src/main/java/tutorial”. Right click in the file and click on the green triangle, with “Run TutorialApplic…main()” next to it. The bottom terminal will open up and you will see a lot of text being printed out.

You did it! You created the foundation on which you can build a better application. Take this time to appreciate the work you have put in to get the foundation done. Next we need to create the the rest of the application, so lets get cracking.

In the project tab on the left, right click on the “tutorial” package and then click on “new” and then “package”. Name this new package “user”. Right click on the newly created package, “user”, and then click “new”, and “Java Class”. The first class will be called “User”:

You should now have a new file, Java class, under your user package, called User, with content similar to this:

package tutorial.user;

public class User {
    
}

We will also need another Java class, called “UserController”, so go through those same steps that you went trough before to create the Java class. Next we will need to create an Interface, called “UserRepository”. The steps are similar to creating the class but instead of click on Class you will click on Interface:

The final piece of our puzzle is an Enum, called “Status”. So as before create the Enum under the “user” package.

We will start by editing the “User” class. I will put the code first and then go through it afterwards, that way you can copy and paste it in your IDE and make notes via comments.

tutorial/src/main/java/tutorial/user/User.java:

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;
import javax.validation.constraints.NotBlank;
import java.util.Objects;

@Entity
@Table(name = "users")
public class User {
    private @Id @GeneratedValue long id;
    private @NotBlank String username;
    private @NotBlank String password;
    private @NotBlank boolean loggedIn;

    public User() {
    }

    public User(@NotBlank String username, 
                @NotBlank String password) {
        this.username = username;
        this.password = password;
        this.loggedIn = false;
    }

    public long getId() {
        return id;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public boolean isLoggedIn() {
        return loggedIn;
    }

    public void setLoggedIn(boolean loggedIn) {
        this.loggedIn = loggedIn;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (!(o instanceof User)) return false;
        User user = (User) o;
        return Objects.equals(username, user.username) &&
                Objects.equals(password, user.password);
    }

    @Override
    public int hashCode() {
        return Objects.hash(id, username, password, 
                            loggedIn);
    }

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", username='" + username + '\'' +
                ", password='" + password + '\'' +
                ", loggedIn=" + loggedIn +
                '}';
    }
}

So going from the top:

  • @Entity: This annotation allows our class to be serialized and deserialized into and from JSON. It also allows us to create a table in the database we created earlier.
  • @Table(name = “users”): This annotation tells the program to call the table “users”.
  • The variables: Each variable is representative to a field in our database. So in our database table will contain records. Each record will have a field of id (long), a field of username (String), a field of password (String), and a field of loggedIn (boolean).
  • @Id: This sets the id variable as the id field in the database. Databases records work with id’s.
  • @GeneratedValue: This tells the program to generate the id value when a new record is added, that way we won’t have to worry about accidentally overriding records in our database.
  • @NotBlank: This ensures that we won’t be able to add a record to the database that doesn’t have a name, password or value for loggedIn.
  • User(@NotBlank String username, @NotBlank String password): This is a constructor. Its a function that will be ran when this class object is created. It takes a username and password, and then sets the username and the password to the ones that were given, it also sets the value for loggedIn as false so that the user isn’t automatically logged in when their profile has been added.
  • Getters and Setters: These are used to set and return the various variables in our class. The reason for these have more to do with Java and the prefer method for data handling and less to do with the Spring framework.
  • equals(Object o): This will be used later when we want to compare an object passed to the program with an object from our database.
  • hashCode(): This function is used to generate a hash value of our object.
  • toString(): This function, has the name might suggest, is used to return some information about our class object in the form of a String. This is especially useful during debugging. I used it a lot when I initially created this program as I had issue with comparing objects to one another.

The next file we will work on is the UserRepository file.

tutorial/src/main/java/tutorial/user/UserRepository.java:

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

@Repository
public interface UserRepository extends 
                                JpaRepository<User, Long> {
}

Now I will admit this file looks a bit empty, especially in comparison to the User.java file, but don’t let the simplicity fool you, it is a very powerful file. The framework does a lot of work under the hood so you don’t necessarily see it, but this file will allow us to interface with our database.

  • @Repository: This tells Spring that this is the interface to use for our database management functions.
  • JpaRepository<User, Long>: This links the interface to our database table. We tell it to look at our User table, and we tell it that the value of our id field is Long.

Next up is our Status enum:

tutorial/src/main/java/tutorial/user/Status.java:

public enum Status {
    SUCCESS,
    USER_ALREADY_EXISTS,
    FAILURE
}

There isn’t really anything interesting about this enum, it will be used as a way to give feedback to the user as to whether there current action was successful or whether it failed.

Lastly is the UserController class:

tutorial/src/main/java/tutorial/user/UserController.java:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.validation.Valid;
import java.util.List;

@RestController
public class UserController {
    @Autowired
    UserRepository userRepository;

    @PostMapping("/users/register")
    public Status registerUser(@Valid @RequestBody User newUser) {
        List<User> users = userRepository.findAll();

        System.out.println("New user: " + newUser.toString());

        for (User user : users) {
            System.out.println("Registered user: " + newUser.toString());

            if (user.equals(newUser)) {
                System.out.println("User Already exists!");
                return Status.USER_ALREADY_EXISTS;
            }
        }

        userRepository.save(newUser);
        return Status.SUCCESS;
    }

    @PostMapping("/users/login")
    public Status loginUser(@Valid @RequestBody User user) {
        List<User> users = userRepository.findAll();

        for (User other : users) {
            if (other.equals(user)) {
                user.setLoggedIn(true);
                userRepository.save(user);
                return Status.SUCCESS;
            }
        }

        return Status.FAILURE;
    }

    @PostMapping("/users/logout")
    public Status logUserOut(@Valid @RequestBody User user) {
        List<User> users = userRepository.findAll();

        for (User other : users) {
            if (other.equals(user)) {
                user.setLoggedIn(false);
                userRepository.save(user);
                return Status.SUCCESS;
            }
        }

        return Status.FAILURE;
    }

    @DeleteMapping("/users/all")
    public Status deleteUsers() {
        userRepository.deleteAll();
        return Status.SUCCESS;
    }
}

This is the business class of your program. Here is where we handle the requests sent to our program.

  • @RestController: This tells Spring that this will be used to control the functionality of our API, and any requests sent to our program.
  • @Autowired: This just handles the code injection for our UserRepository so that we won’t have to setup a constructor.
  • @PostMapping(“/users/register”): This tells Spring that whenever our program receives a Post Request to /users/register that the registerUser function should be called and then it pasts the received data to the registerUser function.
  • registerUser(@Valid @RequestBody User newUser): This function requires a valid json object similar to our User class, that way we will be sure that the object we receive is useable in our program. The function starts by creating a list of users in our database, called users. Note the part of “userRepository.findAll()”, this queries our database and returns all the users we have currently saved. The function then loops over all the users in our database and compares it to the user we just got, it does this to ensure that the user isn’t already part of our database. If it find that the user is already in our database, it returns Status.USER_ALREADY_EXITS. Otherwise it will add the new user into our database and return a status of SUCCESS.
  • loginUser(@Valid @RequestBody User user): Same as before, this function receives a user object and then compares it against the users in our database. If it find that this user is in our database it will set it’s loggedIn variable to true, to indicate that our user has just logged in. If the user was successfully logged in it returns a status of SUCCESS. If it fails it returns a status of FAILURE.
  • logUserOut(@Valid @RequestBody User user): This function is similar to loginUser, except this time we set the user’s loggedIn variable to false to indicate that the user isn’t currently logged in. If the logout was successful we return a status of SUCCESS, otherwise we return a status of FAILURE.
  • @DeleteMapping(“/users/all”): This tells Spring to call the following function whenever a Delete Request has been issued to /users/all.
  • deleteAll(): This function simply deletes all the users in our database. It is a useful function to have during testing.

And that is it for our program, you should now be able to run the program and interact with it through your terminal.

Let’s first test whether or not we can register a new user into our database, open your terminal and paste this bit of code into your terminal:

curl -H "Content-Type: application/json" -X POST -d '{
    "username": "test",
    "password": "test"
}' http://localhost:8080/users/register

This commands sends a post request to our program with a json package. The json package contains a username and a password, you might’ve noticed that in our User class constructor we specifically requested a username and password. We specifically send this Post Request to http://localhost:8080/users/register. Our program is running on localhost on port 8080, and we have a PostMapping listening for when data is sent to “/users/register”. If we run this in our terminal (whilst our application is running in the background) we’ll see something like this:

Notice that we received back a String with the content of “SUCCESS”, meaning our application received the new user and added them to our database. What happens when we run that same command again?

This time we received a message of “USER_ALREADY_EXISTS”, so our program made sure not to add multiples of the same user to our database. Next lets see if we can log our new user in, you can run this command in your terminal:

curl -H "Content-Type: application/json" -X POST -d '{
    "username": "test",
    "password": "test"
}' http://localhost:8080/users/login

Same as before it sends a json object with our user credentials to “/users/login”, the part of our program that specifically handles user login. This is what it looks like when we run the command:

We get back a message of “SUCCESS” so now our user is logged in, but what would’ve happened if we sent the wrong user credentials? Lets test that by running this command:

curl -H "Content-Type: application/json" -X POST -d '{
    "username": "hello",
    "password": "world"
}' http://localhost:8080/users/login

We never registered the user so that user shouldn’t be in our database and thus shouldn’t be able to log into our application. This is what it looks like:

As seen here, our program sends back a message of “FAILURE” indicating that it was able to stop an unregistered user of logging in. That’s it, that’s our entire program. We were able to create a user registration and authentication system using Java and Spring. If you want to clean up after yourself you can clear the database with this command:

curl -X DELETE http://localhost:8080/users/all

And if you also wanna delete the users database from your system, then you can do this. Open your terminal and type

mysql -u root -p

and then enter your password. You should now be back in your MySQL terminal and now if you want to delete the “users” database you can run this command:

DROP DATABASE users;

One last thing before we end this tutorial, you can look at your API setup if you open your browser tab and then go to: http://localhost:8080/api-docs. This will open up some JSON about your API.

The complete code for this project can be found at bitbucket.

Have a lovely day!

Discover and read more posts from Nilmadhab mondal
get started
post commentsBe the first to share your opinion
Show more replies