{{announcement.body}}
{{announcement.title}}

Authentication with Spring Boot and Spring Security — JWT and Postgres

DZone 's Guide to

Authentication with Spring Boot and Spring Security — JWT and Postgres

Take a look at how you can create authentication with REST API calls using JSON Web Tokens.

· Java Zone ·
Free Resource

I am going to talk about what has become a very common requirement for web/cloud-applications these days: Authentication in the context of REST API calls using JSON Web Token, or commonly known as JAWT these days.

The idea behind JSON WebToken is to provide authentication in a stateless API world. The tokens are generated with a Key on the basis of Subject (could be a unique field or combination for a user e.g id, username etc.) using an encryption algorithm such as SHA-256 etc.

Technologies:

1. Spring Boot 2

2. Spring Security

3. Postgres

4. Spring Data

I am using Postgres as a backend database. But, with minor property changes the same code and approach can be used for other databases, such as MySQL.

Motivation

  1. The motivation for the article has been the observation that teams spend lot of time in the implementation of authentication in their application and generally start from scratch (even when JAWT has been around for quite sometime). Some even delay it for later stages — creating more confusion in their own team and dependent API streams such as mobile, web, etc.
  2. Spring Security provides lot of standard classes and hooks for authentication, but somehow they all fit together and interact is not easily understandable. 
  3. In references, I have given the video link where we got the crux of the implementation, but still we have to make some changes to integrate with web interface in Angular. Backend implementation was not originally provided in the reference video.

Enable Web Security

To begin include the dependency in your pom

Java
 




x


1
<dependency>
2
  <groupId>org.springframework.boot</groupId>
3
  <artifactId>spring-boot-starter-security</artifactId>
4
</dependency>


Enable web security in our application we created a file Securitycontext.java and used the annotation @EnableWebSecurity. There are couple of methods that we have overridden the noticeable ones being -

  1.  configure()  — We explicitly disable csrf and cors, specify the urls where we want Spring Security to be by-passed, create stateless sessions and specify the sequence of filters
Java
 






 

2. AuthenticationManager  We would need an instance of Authentication Manager to generate authentication token after checking valid username and password.

Java
 







Authentication

We created a class AuthenticationController with a post endpoint /v1/login.

Java
 




xxxxxxxxxx
1


 
1
@PostMapping(value = "/login")
2
 
          
3
public ResponseEntity<?> createAuthenticationToken(@RequestBody AuthenticationRequest authenticationRequest) throws Exception



Here, we call  authenticate() method of  AuthenticationManager  class passing username and password received in an enclosing  UserNamePasswordAuthenticationToken .

Java
 







Also, we created a class  JPAUserDetailService that implements  UserDetailsService  that is hooked when we call authenticate method (above). 

In this class, we have overridden the method that is used to check whether the user exists or not.

Java
 




xxxxxxxxxx
1
11


 
1
@Override
2
 
          
3
    public UserDetails loadUserByUsername(String userName) throws UsernameNotFoundException {
4
 
          
5
        Optional<User> user = userRepository.findByUsername(userName);
6
 
          
7
        user.orElseThrow(() -> new UsernameNotFoundException("Not found: " + userName));
8
 
          
9
        return user.map(MyUserDetails::new).get();
10
 
          
11
    }



We are also using userRepository pointing to userDetails table in postgres database. The dependency for which is included in our pom file

XML
 




xxxxxxxxxx
1


 
1
<dependencies>
2
        <dependency>
3
            <groupId>org.springframework.boot</groupId>
4
            <artifactId>spring-boot-starter-data-jpa</artifactId>
5
        </dependency>


There is a  hierarchy of classes and implements that provides for this hook in the background. If this is too verbose, you may skip this part. The AuthenticationManager  interface is implemented by the ProviderManager  class that uses various  AuthenticationProvider . E.g An authentication provider implementation with name  DAOAuthenticationProvider This authentication provider will use  UserDetailService  and will call the implementation method  loadUserByUsername()  for which concrete implementation is provided in our class  JPAUserDetailService .

Java
 






JWT Generation

Include the dependency below in your pom for jwt features

Java
 




xxxxxxxxxx
1


 
1
<dependency>
2
            <groupId>io.jsonwebtoken</groupId>
3
            <artifactId>jjwt</artifactId>
4
            <version>0.9.1</version>
5
        </dependency>


In JWTUtil.java we have various functions dealing with jwt such as generatetoken, extract and validate user details from token, set expiration of token etc. The default time we have set is 10 hours converted in milliseconds below.

Java
 







If the details are correct then the token will be issued. A sample response of the token, when generated successfully, is shown below.

Response

Filters

There is a filter class that works like a gatekeeper for authentication is  JWTFilter  and it uses  JWTUtil  class methods to extract and validate user details from token that is to be passed in header in postman. Below is a sample of how to pass  Authorization  in the header using syntax:  Bearer <space> <<token>> 


Passing authorization


Below are some flows on how the filters and Spring Security function with respect to obtaining token, and subsequent calls requiring authentication.

  1. /v1/login - is an endpoint where we generate the token. In SecurityContext we configured to ignore this URL requiring authentication as this is the first call to generate token so Spring Security is ignored for this call.

/v1/login2. /v1/hello - an endpoint to demonstrate our authentication flow. Here, JWTFilter looks for the authentication header, checks validity of token and whether it belongs to a valid user or not. After these checks, we set the authentication information in the security context. It is important step, as this allows us to preserve the user information that may be required in downstream steps.

Java
 







That's pretty much it. You should be able to see JAWT in action with the steps I discussed. The code is available for you at this link below. I will discuss CORS specific settings in my next article. Please share your feedback and comments.

Topics:
java ,jwt authentication ,microservice ,postgres ,spring boot 2.2 ,spring data jpa ,spring security

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}