DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Please enter at least three characters to search
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Zones

Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

The software you build is only as secure as the code that powers it. Learn how malicious code creeps into your software supply chain.

Apache Cassandra combines the benefits of major NoSQL databases to support data management needs not covered by traditional RDBMS vendors.

Generative AI has transformed nearly every industry. How can you leverage GenAI to improve your productivity and efficiency?

Modernize your data layer. Learn how to design cloud-native database architectures to meet the evolving demands of AI and GenAI workloads.

Related

  • Authentication With Remote LDAP Server in Spring Web MVC
  • Authentication With Remote LDAP Server in Spring WebFlux
  • How to Implement Two-Factor Authentication in A Spring Boot OAuth Server? Part 2: Under the Hood
  • How to Implement Two-Factor Authentication in a Spring Boot OAuth Server? Part 1: Configuration

Trending

  • A Modern Stack for Building Scalable Systems
  • How To Introduce a New API Quickly Using Quarkus and ChatGPT
  • MCP Servers: The Technical Debt That Is Coming
  • The Human Side of Logs: What Unstructured Data Is Trying to Tell You
  1. DZone
  2. Coding
  3. Frameworks
  4. Authentication with Spring Boot and Spring Security — JWT and Postgres

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.

By 
Aakash Sharma user avatar
Aakash Sharma
·
Apr. 21, 20 · Tutorial
Likes (7)
Comment
Save
Tweet
Share
23.0K Views

Join the DZone community and get the full member experience.

Join For Free

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
 




xxxxxxxxxx
1
15
9


 
1
 httpSecurity.cors().disable().csrf().disable()
2
.authorizeRequests().antMatchers("/v1/login").permitAll().  
3
anyRequest().authenticated()
4
.and().
5
exceptionHandling().
6
and().sessionManagement()
7
.sessionCreationPolicy(SessionCreationPolicy.STATELESS);
8
httpSecurity.addFilterBefore(jwtRequestFilter, UsernamePasswordAuthenticationFilter.class);


 

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

Java
 




xxxxxxxxxx
1


 
1
@Override
2

          
3
    @Bean
4

          
5
    public AuthenticationManager authenticationManagerBean() throws Exception {
6

          
7
        return super.authenticationManagerBean();
8

          
9
    }



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
 




xxxxxxxxxx
1


 
1
Authentication authenticate = authenticationManager.authenticate(
2

          
3
                new UsernamePasswordAuthenticationToken(authenticationRequest.getUsername(), authenticationRequest.getPassword())
4

          
5
        );



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
 




xxxxxxxxxx
1
19


 
1
protected final UserDetails retrieveUser(String username,
2
            UsernamePasswordAuthenticationToken authentication)
3
            throws AuthenticationException {
4
        prepareTimingAttackProtection();
5
        try {
6
            UserDetails loadedUser = this.getUserDetailsService().loadUserByUsername(username);
7
            if (loadedUser == null) {
8
                throw new InternalAuthenticationServiceException(
9
                        "UserDetailsService returned null, which is an interface contract violation");
10
            }


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
 




xxxxxxxxxx
1


 
1
private String createToken(Map<String, Object> claims, String subject) {
2
        return Jwts.builder().setClaims(claims).setSubject(subject).setIssuedAt(new Date(System.currentTimeMillis()))
3
                .setExpiration(new Date(System.currentTimeMillis() + 1000 * 60 * 60 * 10))
4
                .signWith(SignatureAlgorithm.HS256, SECRET_KEY).compact();
5
    }



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
 




xxxxxxxxxx
1
15


 
1
if (jwtUtil.validateToken(jwt, userDetails)) {
2

          
3

          
4

          
5
                UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = new UsernamePasswordAuthenticationToken(
6

          
7
                        userDetails, null, userDetails.getAuthorities());
8

          
9
                usernamePasswordAuthenticationToken
10

          
11
                        .setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
12

          
13
                SecurityContextHolder.getContext().setAuthentication(usernamePasswordAuthenticationToken);
14

          
15
            }



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.

Spring Security Spring Framework authentication Spring Boot PostgreSQL JWT (JSON Web Token)

Opinions expressed by DZone contributors are their own.

Related

  • Authentication With Remote LDAP Server in Spring Web MVC
  • Authentication With Remote LDAP Server in Spring WebFlux
  • How to Implement Two-Factor Authentication in A Spring Boot OAuth Server? Part 2: Under the Hood
  • How to Implement Two-Factor Authentication in a Spring Boot OAuth Server? Part 1: Configuration

Partner Resources

×

Comments
Oops! Something Went Wrong

The likes didn't load as expected. Please refresh the page and try again.

ABOUT US

  • About DZone
  • Support and feedback
  • Community research
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • support@dzone.com

Let's be friends:

Likes
There are no likes...yet! 👀
Be the first to like this post!
It looks like you're not logged in.
Sign in to see who liked this post!