How to implement JWT authentication in Spring Security and Angular – Part 1

I recently had to implement a bearer token authentication mechanism in a Spring backend and an Angular frontend. I wasn’t surprised to see that there are already a lot of tutorials around, however, I was shocked by how poorly most of them are written and how bad some solutions were. Now, don’t get me wrong: By no means do I want to claim that my solution is the state-of-the art single way to go. However, this has worked for me and I think it’s much easier to understand and follow than other guides. Additionally, there are a few things that almost all tutorials get wrong and I’ll try to address these as well.

I’ll use maven to manage the dependencies in this project.

This guide can be used to implement the mechanism in a completely new project as well as when you want to extend an existing application, like I had to.

Short intro to JWTs

I’ll keep this section short and it’s only there to give you a general idea of what these tokens look like. Feel free to skip this section if you’re not interested in it.

The JSON Web Token is an Internet standard for creating access tokens. They can contain a number of claims, for example, the user’s roles. Typically, a user requests a token from the server which then generates a JWT and issues it for that user. These tokens are, usually, encrypted by the server.

The access token then has to be sent to sever with each request that requires the requesting user to authenticate. For that purpose, the JWT gets included in the header of the HTTP request.

It’s important to note, that the tokens are not secret. You can easily decrypt them and read the contents. Let’s take the following token as an example:

eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJhZG1pbiIsImlzcyI6IkNPTlRST0xfQ0VOVEVSX0JBQ0tFTkQiLCJpYXQiOjE1NjMzNDg5MDQsIm5iZiI6MTU2MzM0ODkwNCwiZXhwIjoxNTYzMzQ5MjA0LCJyb2xlcyI6WyJST0xFX1NQRUNUQVRPUiIsIlJPTEVfVVNFUiIsIlJPTEVfQURNSU5JU1RSQVRPUiJdLCJhcHByb3ZlZCI6dHJ1ZSwiaWQiOjJ9.LnvABsbjZDX4CpKPboYTnF6AV_fswD2G8GFUw2YtUoU

Navigate to a JWT decoder and let it decode the given token:

Figure 1: The contents of the token can easily be restored

The dependencies

So, let’s start with the dependencies you’ll need to include in your maven project. For that purpose, add the following lines to your pom.xml file, if they don’t already exist.

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-security</artifactId>
</dependency>

<!-- Hibernate / JPA dependencies omitted -->

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-web</artifactId>
</dependency>

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-devtools</artifactId>
  <optional>true</optional>
</dependency>

<dependency>
  <groupId>com.h2database</groupId>
  <artifactId>h2</artifactId>
</dependency>

<dependency>
  <groupId>io.jsonwebtoken</groupId>
  <artifactId>jjwt-api</artifactId>
  <version>0.10.6</version>
</dependency>

<dependency>
  <groupId>io.jsonwebtoken</groupId>
  <artifactId>jjwt-impl</artifactId>
  <version>0.10.6</version>
</dependency>

<dependency>
  <groupId>io.jsonwebtoken</groupId>
  <artifactId>jjwt-jackson</artifactId>
  <version>0.10.6</version>
</dependency>

Note, that I used the h2-database in this guide. If you’re using a different database, make sure to change the dependencies accordingly! I also used hibernate for managing the database.

The project scaffolding

Before we configure Spring Security, let’s make sure that there’s a way to store and retreive user information from the data storage.

For that purpose, create a database with your preferred method and write a class that can access the database. Because this can be done in many different ways, I’d only like to share the interface I used and you can implement it any way you like (I included the completed project at the end of this series in case you’re interested in my quick and dirty implementation):

@Repository
public interface IUserDao extends JpaRepository<User, Long>
{
    User findOneById(Long id);
    User findOneByUsername(String username);
}

Now write a class, if you don’t already have one, that represents a user from the database:

@Entity
public class User
{
    // Hibernate annotations omitted
    private String username, password;
    private Long id;
    private Boolean isAdmin;

    public User(String username, String password, Long id, Boolean isAdmin)
    {
        this.username = username;
        this.password = password;
        this.id = id;
        this.isAdmin = isAdmin;
    }

    public User() { }

    // Getters, Setters, Equals, HashCode

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

Then, define a REST so that we have a way to access the user data:

@RestController
@RequestMapping("/users")
public class UserEndpoint
{
    @Autowired
    IUserService userService;

    public UserEndpoint(IUserService userService)
    {
        this.userService = userService;
    }

    public UserEndpoint() { }

    @RequestMapping(value = "/", method = RequestMethod.GET)
    @CrossOrigin
    public List<User> findAll()
    {
        return userService.findAll();
    }

    @RequestMapping(value = "/{id}", method = RequestMethod.GET)
    @CrossOrigin
    public User findOneById(@PathVariable("id") Long id)
    {
        return userService.findOneById(id);
    }

    @RequestMapping(value = "/", method = RequestMethod.POST)
    @ResponseStatus(HttpStatus.CREATED)
    @CrossOrigin
    public User save(@RequestBody User newUser)
    {
        return userService.save(newUser);
    }
}

As you can see, I created a user service that connects the endpoint and the persistence unit:

public interface IUserService
{
    List<User> findAll();
    User findOneById(Long id);
    User save(User newUser);
}

The concrete implementation:

@Service
public class UserService implements IUserService
{
    private final IUserDao userDao;

    public UserService(IUserDao userDao)
    {
        this.userDao = userDao;
    }

    public List<User> findAll()
    {
        return this.userDao.findAll();
    }

    public User findOneById(Long id)
    {
        return this.userDao.findOneById(id);
    }

    @Override
    public User save(User u)
    {
        return userDao.save(u);
    }
}

Now that the project is ready to go, we can begin setting up Spring Security in the next part of this series. In it, you’ll see how you can make sure that Spring restricts access to certain pages and HTTP-methods.

Table of contents

Part 1 – Basics of JWT and the project scaffolding (You are here)
Part 2 – Configure Spring Security
Part 3 – JWT token generation, validation, and user authentication
Part 4 – JWT authentication in an Angular frontend
Part 5 – Token renewal

4 thoughts on “How to implement JWT authentication in Spring Security and Angular – Part 1

Leave your two cents, comment here!

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.