No one can deny from the fact that Security is a vital feature of a production ready application. Although we can secure one web application using In-memory authentication, JDBC Authentication or via UserDetailsService. But when one application uses the services of other application internally, then implementation of security with webservices concept becomes important. In this situation we secure our application using a token which has a particular period of validity. Further, we are going to learn ‘How to implement JWT Authentication in Spring Boot Project?’ to understand the concept behind JWT(JSON Web Token) Authentication as a whole. As JWT stands for ‘JSON Web Token’, it is clear that the token holds the data in the form of JSON only.
Moreover, unlike aforementioned techniques of authentication, JWT comes under stateless authentication. In brief, it doesn’t have data. Generally, this type of authentication is used in Webservices, horizontal scaling of servers or even in OAuth technique up to some extent. To illustrate the webservice, let’s visualize the process of booking an order from Amazon. Here, the user interacts with Amazon app, whereas Amazon app internally interacts with payment gateway app via a webservice call. Now let’s start discussing about our topic ‘How to implement JWT Authentication in Spring Boot Project?’ and related points.
Table of Contents (Click on links below to navigate)
Once you complete going through this article, you will be able to answer :
1) What is stateless & stateful authentication in a security context?
2) What is the difference between stateless & stateful authentication?
3) Then What is a Token and what is a JWT(JSON Web Token)?
4) What are the benefits of using JWT authentication?
5) How does JWT work internally?
6) In which context we use JWT authentication?
7) Further, What is the difference between JWT authentication & a stateful authentication?
8) Additionally, How to generate an encoded token as JWT and How to decode it back?
9) How to implement JWT Authentication in Spring Boot Project step by step?
10) Finally, How to test the JWT security enabled Application?
What is Stateless and Stateful Authentication?
Generally there are two types of authentication techniques. Both happen in a client server concept in such a way that Server provides a service to a Client only after authentication. Here clients can be a browser or another server again.
Stateful Authentication
In this type of Authentication, there is a session management involved between client & server. When a client requests for a service from a server, it first logins to the server. Then server creates a session and stores this information in the form of key – value pairs. This session is a kind of memory at server side. We also call it HttpSession as Http protocol manages it. Further, in response to client requests, the server provides a session id with the response in the form of Cookie to the client. That cookie gets stored in the client browser. When same client makes request for the second time, cookie also comes with the request header. Consequently, the server checks the request header and if it finds the same SID (Session id) in the cookie it assumes that the request came from the same client. In this way session management happens.
When a client logs out from the server, the session gets destroyed accordingly. As a result, the server removes the session information (key-value) from the memory accordingly. Equally important, For every new client, the server creates a new session(memory).
Stateless Authentication
When a client sends a request to the server for a service, it first logins to the server. Consequently, the server generates a token (data in encoded format) and sends to the client with the response. While making second request, Client sends the same token along with the request to the server. Now, the server reads token from the request and validates the token. In fact, from the first request server checks the valid login(credentials) of the client. If it is a valid login, then only, server creates a token. Furthermore, on the second request it validates the token. If the token is valid it sends the requested response, otherwise asks the client to login again. However, every token will have a valid time period, such as 30 minutes, 1 hour etc. Based on business requirements, token validity period can be configured.
In case of Token, there is no concept of logout. Instead, the client can make a request & get the response until the token expires.
What is a Token, What is JWT authentication all about and What is the benefit of using it?
In a nutshell, Token is a data in an encoded format. It can be generated using a secret key(a kind of password). JWT is an abbreviation to ‘JSON Web Token’, which is a standard mechanism to generate tokens. It defines a compact and self-contained way of transmitting information securely between parties(multiple servers) as a JSON object. JWT has three parts : Header, Payload & Signature. Each part is separated by comma. Its an open source API. JWT concept exists not only in Java, but also in other languages.
Header : contains JWT Specific Information
Payload : contains Claims (Client ID, Client Name, Issuer Name, Audience Name, Date of issue, Expiry date etc…)
Signature: Base64 encoded form of Header & Payload. Additionally, signed with a secret key
Below is the example in format: aaaaaaaaaaaa.bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb.cccccccccccccccccccccccccccccccccc
Example of an encodedJWT :eyJhbGciOiJIUzUxMiJ9.eyJqdGkiOiIzNDMyIiwic3ViIjoiZHMyNTI1IiwiaXNzIjoiQUJDX0x0ZCIsImF1ZCI6IlhZWl9MdGQiLCJpYXQiOjE2MDc0NDI1NzQsImV4cCI6MTYwNzQ0NjE3NH0.3fIcXIvL9Uz0WtZgaXC95Wj8Hn7ONWKkaaspRwCT6v5Q8QSxZx7hiDQY3klYUMkfe5t2ioasYzEulM_OGc_GEw
How does JWT authentication work?
When a client requests for a service from a server, it first logins to the server. Consequently, the server generates a token(data in encoded format) and send to the client with the response. While making a second request Client sends token along with the request to the server. Now server reads token from the request and validate the token. While validating the token which client sends with the request, server requires that secret key again to decode it. Further to validate the token server always requires the secret key. Even after the successful login, server generates token using secret key only for the first time. In summary, server requires the secret key while generating the token & even at the time of validating it too.
Unlike stateful authentication, here server maintains the token at the server side only. As aforementioned, in stateful authentication browser(client) stores session ID in the form of cookies.
Suppose we are booking an order through amazon app. There are at least three participants on the whole to complete the booking. User, Amazon app and Payment gateway app. Here payment gateway app authenticates amazon app not the client. This happens because of token authentication technique. Further amazon app will not use payment gateway’s service once payment is complete. Hence token authentication is preferable in this situation. For further internal details on JWT, kindly visit JWT website.
How to generate an encoded Token as JWT & decode it(read the Claims) again?
Here Claims is a process of reading or parsing JWT details by providing two inputs : Token & Secret Key
In order to implement the POC(Proof Of Concept) on ‘How to generate & read Claims back’, we should think of finding a JAVA API for JWT. Undoubtedly, we already have jjwt.jar to make it possible. Now let’s create a POC to implement our functionality step by step.
Step#1: Create a simple Maven project in Eclipse or STS.
Open your eclipse and select File>New>Other, then search for ‘Maven Project’. Then click on ‘Next’, Select ‘create a simple project’ checkbox. Now click on ‘Next’. Enter ‘Group Id’ and ‘Artifact id’ as your project details. Finally click on ‘Finish’.
Step#2: Include jjwt dependency in your pom.xml.
Include ‘jjwt‘ dependency as given below. Additionally if you are using JDK8 or later version you need to include ‘jaxb‘ dependency as well.
Consequently we will create two classes : JWTUtil.java & JWT_Test.java
In JWTUtil.java we will have implementation logic which can work as a utility class. Further we will test our POC from JWT_Test.java accordingly.
JWTUtil.java
ackage com.dev.spring.security.jwt;
import java.util.Base64;
import java.util.Date;
import java.util.concurrent.TimeUnit;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
public class JWTUtil {
// code to generate Token
public static String generateToken(String subject, String secret_key) {
return Jwts.builder()
.setId("tk9931")
.setSubject(subject)
.setIssuer("ABC_Ltd")
.setAudience("XYZ_Ltd")
.setIssuedAt(new Date(System.currentTimeMillis()))
.setExpiration(new Date(System.currentTimeMillis() + TimeUnit.HOURS.toMillis(1)))
.signWith(SignatureAlgorithm.HS512, Base64.getEncoder().encode(secret_key.getBytes()))
.compact();
}
//code to get Claims
public static Claims getClaims(String token, String secret_key) {
return Jwts.parser()
.setSigningKey(Base64.getEncoder().encode(secret_key.getBytes()))
.parseClaimsJws(token)
.getBody();
}
}
------------------------TOKEN----------------------------------------------------
eyJhbGciOiJIUzUxMiJ9.eyJqdGkiOiJ0azk5MzEiLCJzdWIiOiJUb2tlbjEiLCJpc3MiOiJBQkNfTHRkIiwiYXVkIjoiWFlaX0x0ZCIsImlhdCI6MTYwNzUwNjY0OCwiZXhwIjoxNjA3NTEwMjQ4fQ.lFA0_Jvnt0o69CnotXbTIyYANpWjjeTGxvv6avVihlCqKnuw1bXADp_y3s-NMdohcD2Sq0Cft16wLo7rwvTHpQ
------------------------CLAIMS----------------------------------------------------
Token ID: tk9931
Token Subject: Token1
Token Issuer: ABC_Ltd
Token Issue Date: Wed Dec 09 15:07:28 IST 2020
Token Expiration Date: Wed Dec 09 16:07:28 IST 2020
Token Audience: XYZ_Ltd
How to implement JWT Authentication in Spring Boot Project?
To illustrate the implementation of JWT Authentication, we will definitely require a webservice call. For that we will register some users into DB using REST webservice. To make this happen, we will use POSTMAN software as we will not have a registration form in this case. Then we will apply JWT security features into our code. Finally we will verify the security features we incorporated through testing. Let’s start implementing it accordingly.
What Software/Technologies would you need?
♦STS (Spring Tool Suite) : Version-> 4.7.1.RELEASE
⇒Dependent Starters : Spring Security, Spring Web, Lombok, Spring Data JPA, MySQL Driver, Spring Boot DevTools
♦MySQL Database : Version ->8.0.19 MySQL Community Server
♦JDK8 or later versions (Extremely tested on JDK8, JDK11 and JDK14)
Step#1 : Create a Spring Boot Starter Project in STS(Spring Tool Suite)
While creating Starter Project select ‘Spring Security’, ‘Spring Web’, ‘Spring Data JPA’, ‘MySQL Driver’, ‘Lombok’ and ‘Spring Boot DevTools’ as starter project dependencies. Additionally add ‘jaxb’ dependency in pom.xml as aforementioned. Even If you don’t know how to create Spring Boot Starter Project, Kindly visit Internal Link. Also, if you want to know more about Lombok, then visit Internal Link.
#application.properties
------------------------------------------------------------------
#-------------------- Server Properties ---------------server.port=8080#--------------------- DB Connection Properties ------------------#AutoLoading of driver class since JDBC 4#spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driverspring.datasource.url=jdbc:mysql://localhost:3306/testJWTSecurityspring.datasource.username=rootspring.datasource.password=devs#--------------------JPA Properties-----------------spring.jpa.show-sql=truespring.jpa.hibernate.ddl-auto=update#spring.jpa.database-platform=org.hibernet.dialect.MySQL8Dialect#------------------Security Specific Properties-------app.secret.key=[email protected]!gt*K
package com.dev.spring.security.jwt.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
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.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import com.dev.spring.security.jwt.filter.SecurityFilter;
@EnableWebSecurity
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private UserDetailsService userDetailsService;
@Autowired
private BCryptPasswordEncoder bCryptEncoder;
@Autowired
private UnAuthorizedUserAuthenticationEntryPoint authenticationEntryPoint;
@Autowired
private SecurityFilter secFilter;
//Required in case of Stateless Authentication
@Override @Bean
protected AuthenticationManager authenticationManager() throws Exception {
return super.authenticationManager();
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService)
.passwordEncoder(bCryptEncoder);
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().disable() //Disabling CSRF as not using form based login
.authorizeRequests()
.antMatchers("/user/saveUser","/user/loginUser").permitAll()
.anyRequest().authenticated()
.and()
.exceptionHandling()
.authenticationEntryPoint(authenticationEntryPoint)
.and()
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
//To Verify user from second request onwards............
.and()
.addFilterBefore(secFilter, UsernamePasswordAuthenticationFilter.class)
;
}
}
Finally your project structure should look like below screenshot.
How to test the JWT security enabled Application ?
Although the word ‘testing’ looks very easy to a developer but it is equally important as it provides the result of our implementation on the whole. Therefore, follow the steps given below:
1) Register User through a REST call using Postman
Enter URL http://localhost:8080/user/saveUser in Postman, select POST method, then Select Body>Raw>JSON respectively. Now paste below JSON data and then click on ‘Send’ button.
output on Postman : User with id ‘1’ saved succssfully!
2) Login as a User to generate token
Enter URL http://localhost:8080/user/loginUser in Postman, select POST method, then Select Body>Raw>JSON respectively. Now paste below JSON data and then click on ‘Send’ button.
3) Access data/resource within token validity period
Enter URL http://localhost:8080/user/getData in Postman URL bar, select POST method, then Select Headers. Under Headers select key as ‘Authorization’. Now paste token as a value of Authorization as in below screenshot. Then click on ‘Send’ button.
As a successful response, you should get the below output :
You are accessing data after a valid Login. You are :ds2525
Summary
After going through all the theoretical & examples part of ‘How to implement JWT Authentication in Spring Boot Project?’, finally, we are able to implement JWT authentication security in a Spring Boot project. Of course, In this article we have thoroughly learned about the JWT authentication features. Similarly, we expect from you to further extend this example and implement it in your project accordingly. Additionally, If there is any change in future, we will update the article accordingly. Moreover, Feel free to provide your comments in comments section.
7 thoughts on “How to implement JWT Authentication in Spring Boot Project?”
On the second postamn test (‘Login as a User to generate token’), data should be :
{“username”: “ds2525”, “password”: “donotforgetme”}
not
{“username”: “ds2424”, “password”: “donotforgetme”}
@Antoine, Thanks for notifying the issue. I am more than happy after reading your comments. I have corrected it. Please feel free to comment if you find any further issue.
On the second postamn test (‘Login as a User to generate token’), data should be :
{“username”: “ds2525”, “password”: “donotforgetme”}
not
{“username”: “ds2424”, “password”: “donotforgetme”}
@Antoine, Thanks for notifying the issue. I am more than happy after reading your comments. I have corrected it. Please feel free to comment if you find any further issue.
Hey there, You’ve done a great job. I will certainly personally suggest to my friends. I’m confident they will be benefited from this site.
Really its very nice blog and I got cleared all my doubts related JWT, Thanks to you for such a nice and detailed explainations. 🙂