September 11, 2019

Welcome to Part 2 of my Build a blog series with Spring Boot and Angular.

In Part 1 , we created our project and basic domain entities and repositories. In this article, we will set up Spring Security and implement the API to register users in our application.

If you are a visual learner like me, you can have a look at the youtube video I have created as a companion to this post.

Setup Spring Security and implement Signup API
Encode passwords using Spring Security

The source code of this project, is hosted on Github –https://github.com/SaiUpadhyayula/spring-ng-blog
https://github.com/SaiUpadhyayula/ng-spring-blog-frontend

What are we going to build in this part?

  • First, we will see how to setup Spring Security in our application
  • Then, we will build an API to register users in our application
  • We will see how to encode the password of the user, before storing them in the database.

So let’s start coding.

Configure Spring Security

Let’s create the following class which holds the complete security configuration of our application, that’s why the class is named SecurityConfig.java

package com.programming.techie.springngblog.config;

import com.programming.techie.springngblog.security.JwtAuthenticationFilter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.BeanIds;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    public void configure(HttpSecurity httpSecurity) throws Exception {
        httpSecurity.csrf().disable()
                .authorizeRequests()
                .antMatchers("/api/auth/**")
                .permitAll()
                .anyRequest()
                .authenticated();
    }

    @Bean
    PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }
}

Let’s understand what did we configure in the above class:

  1. @EnableWebSecurity
    This is the main annotation which enables the Web Security module in our Project.
  2. WebSecurityConfigurerAdapter
    This is the base class for our SecurityConfig class, it provides us the default security configurations, which we can override in our SecurityConfig and customize them.
  3. Configurations
    Next, we have the configure method which we have overridden from the base class which takes HttpSecurity as an argument.

    Here, we are configuring the Spring to allow all the requests which match the endpoint “/api/auth/**” , as these endpoints are used for authentication and registration we don’t expect the user to be authenticated at that point of time.
  4. PasswordEncoder
    Now before storing the user in the database, we ideally want to encode the passwords. One of the best hashing algorithms for passwords is the Bcrypt Algorithm. We are using the BCryptPasswordEncoder class provided by Spring Security. You can read more about this here

Now that is the minimumconfiguration we need to implement the Registration Functionality, in the upcoming blog posts, we will add more functionality to our SecurityConfig class as we implement the Login functionality using JWT. Let’s write the API for registering users.

Implement API to Register Users

So to register users, first of all, we need a Controller class, I will create it inside the following package: com.programming.techie.springngblog.controller. I will name our class file as AuthController.java

package com.programming.techie.springngblog.controller;

import com.programming.techie.springngblog.dto.RegisterRequest;
import com.programming.techie.springngblog.service.AuthService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/api/auth")
public class AuthController {

    @Autowired
    private AuthService authService;

    @PostMapping("/signup")
    public ResponseEntity signup(@RequestBody RegisterRequest registerRequest) {
        authService.signup(registerRequest);
        return new ResponseEntity(HttpStatus.OK);
    }
}

So we have created a RestController and inside this controller, we have first created a method that will be invoked whenever a POST request is made to register the user’s in our application.

The API call should contain the request body which is of type RegisterRequest. We call this kind of classes as a DTO (Data Transfer Object). We will create this class inside a different package called com.programming.techie.springngblog.dto

RegisterRequest.java

package com.programming.techie.springngblog.dto;

public class RegisterRequest {
    private String username;
    private String email;
    private String password;

    public String getUsername() {
        return username;
    }

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

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public String getPassword() {
        return password;
    }

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

This signup method is calling another method inside the AuthService class, which is mainly responsible to create the User object and storing it in the database. Now let’s create this AuthService class inside the com.programming.techie.springngblog.service.

AuthService.java

package com.programming.techie.springngblog.service;

import com.programming.techie.springngblog.dto.RegisterRequest;
import com.programming.techie.springngblog.model.User;
import com.programming.techie.springngblog.repository.UserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;

@Service
public class AuthService {

    @Autowired
    private UserRepository userRepository;
    @Autowired
    private PasswordEncoder passwordEncoder;

    public void signup(RegisterRequest registerRequest) {
        User user = new User();
        user.setUserName(registerRequest.getUsername());
        user.setEmail(registerRequest.getEmail());
        user.setPassword(encodePassword(registerRequest.getPassword()));

        userRepository.save(user);
    }

    private String encodePassword(String password) {
        return passwordEncoder.encode(password);
    }
}

Inside the AuthService class, we are mapping the RegisterRequest object to the User object and when setting the password, we are calling the encodePassword method. This method is using the BCryptPasswordEncoder to encode our password. After that, we save the user into the database.

Lets Review the Project Structure

We have created some classes and packages, the project structure should look something like below:

Let’s Test the API

Now its time to test the API we have created, start the application by typing below command in the terminal

mvn spring-boot:run

and make a POST request to our Signup API using POSTMAN, which looks like below:

You can see that we received a 200 OK response back from the server, which means the User is saved successfully in the database.

So you can see that our User is successfully saved in the database, the password is not in a human-readable format, it is encoded using the BCrypt algorithm.

What’s next?

So this concludes this post, in the next article, we will see how to implement Login API and how to configure JWT in our application.

About the author 

Sai Upadhyayula

{"email":"Email address invalid","url":"Website address invalid","required":"Required field missing"}

Subscribe now to get the latest updates!