Spring Boot Backend Development Course, Implementing Login and Logout with JWT, Implementing a JWT Service

Implementing Login/Logout with JWT

Table of Contents

  1. Introduction
  2. Introduction to Spring Boot
  3. What is JWT?
  4. Project Setup
  5. Implementing Registration Feature
  6. Implementing Login Feature
  7. Authentication and Authorization using JWT
  8. Creating and Validating JWT Tokens
  9. Implementing Logout Feature
  10. Conclusion

Introduction

Recently, authentication and authorization have become very important issues in web applications. Especially when developing RESTful APIs, there are many considerations in handling user authentication because multiple clients need to be supported. Today, we will explore how to implement a login and logout system based on JWT (JSON Web Token) using Spring Boot.

Introduction to Spring Boot

Spring Boot is a project created to simplify application initialization and configuration in the Spring framework, which is a Java-based web application framework. Spring Boot automatically manages the necessary configurations and dependencies, allowing developers to focus on business logic.

Spring Boot offers several advantages:

  • Allows for quick prototype development.
  • Basic configurations are automatically handled.
  • Includes an embedded Tomcat server, eliminating the need for separate server configuration.

What is JWT?

JWT (JSON Web Token) is a compact and independent standard for securely transmitting information using JSON format. JWT is widely used to handle user authentication and authorization in web applications. The features of JWT include:

  • Self-contained reliability: The transmitted data is signed and can be verified.
  • Simple structure for easy parsing.
  • Can be transmitted via HTTP headers, providing good compatibility with various clients.

JWT consists of three components:

  • Header: Contains token type and signing algorithm information.
  • Payload: Contains user information and claims.
  • Signature: Ensures the integrity of the data by signing based on the header and payload.

Project Setup

To create a Spring Boot project, we use Spring Initializr. Select the necessary dependencies such as Web, JPA, Spring Security, Lombok, and JWT library.


        com.example
        jwt-demo
        0.0.1-SNAPSHOT
        jar

        
            
                org.springframework.boot
                spring-boot-starter-web
            
            
                org.springframework.boot
                spring-boot-starter-data-jpa
            
            
                org.springframework.boot
                spring-boot-starter-security
            
            
                io.jsonwebtoken
                jjwt
                0.9.1
            
            
                org.projectlombok
                lombok
                1.18.12
                provided
            
            
                com.h2database
                h2
                runtime
            
        
        

After adding the above dependencies to the build.gradle file, set up the Spring Boot application. Write database connection and JPA settings in the application.properties file.

Implementing Registration Feature

The registration feature essentially allows the user’s provided information to be stored in the database. A JPA entity class is created to save user information.


        import lombok.AllArgsConstructor;
        import lombok.Getter;
        import lombok.NoArgsConstructor;
        import lombok.Setter;

        import javax.persistence.*;

        @Entity
        @Table(name = "users")
        @Getter @Setter @NoArgsConstructor @AllArgsConstructor
        public class User {
            @Id
            @GeneratedValue(strategy = GenerationType.IDENTITY)
            private Long id;

            @Column(unique = true, nullable = false)
            private String username;

            @Column(nullable = false)
            private String password;

            private String role;
        }
        

Create a repository interface to handle the user information provided during registration.


        import org.springframework.data.jpa.repository.JpaRepository;

        public interface UserRepository extends JpaRepository {
            User findByUsername(String username);
        }
        

Create a service class to handle the registration requests.


        import org.springframework.beans.factory.annotation.Autowired;
        import org.springframework.security.crypto.password.PasswordEncoder;
        import org.springframework.stereotype.Service;

        @Service
        public class UserService {
            @Autowired
            private UserRepository userRepository;

            @Autowired
            private PasswordEncoder passwordEncoder;

            public void registerUser(User user) {
                user.setPassword(passwordEncoder.encode(user.getPassword()));
                user.setRole("ROLE_USER");
                userRepository.save(user);
            }
        }
        

Implementing Login Feature

The login feature is the process where a user provides authentication information to receive a JWT token from the server. To achieve this, we write a filter class that handles authentication.


        import org.springframework.beans.factory.annotation.Autowired;
        import org.springframework.security.authentication.AuthenticationManager;
        import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
        import org.springframework.security.core.Authentication;
        import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

        public class JwtAuthenticationFilter extends UsernamePasswordAuthenticationFilter {
            @Autowired
            private AuthenticationManager authenticationManager;

            @Autowired
            private JwtTokenProvider jwtTokenProvider;

            @Override
            public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) {
                String username = request.getParameter("username");
                String password = request.getParameter("password");
                UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(username, password);
                return authenticationManager.authenticate(authRequest);
            }

            @Override
            protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authResult) throws IOException, ServletException {
                String token = jwtTokenProvider.createToken(authResult.getName());
                response.addHeader("Authorization", "Bearer " + token);
                response.getWriter().write("Login Successful");
            }
        }
        

Authentication and Authorization using JWT

This section implements the method to authenticate users when calling an API using JWT. We will create a filter that blocks requests if the JWT token is missing or invalid.


        import org.springframework.security.core.Authentication;
        import org.springframework.security.core.context.SecurityContextHolder;
        import org.springframework.stereotype.Component;
        import org.springframework.web.filter.GenericFilterBean;

        import javax.servlet.FilterChain;
        import javax.servlet.ServletException;
        import javax.servlet.http.HttpServletRequest;
        import javax.servlet.http.HttpServletResponse;
        import java.io.IOException;

        @Component
        public class JwtAuthenticationFilter extends GenericFilterBean {
            @Autowired
            private JwtTokenProvider jwtTokenProvider;

            @Override
            public void doFilter(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {
                String token = request.getHeader("Authorization");

                if (token != null && jwtTokenProvider.validateToken(token)) {
                    Authentication authentication = jwtTokenProvider.getAuthentication(token);
                    SecurityContextHolder.getContext().setAuthentication(authentication);
                }

                chain.doFilter(request, response);
            }
        }
        

Creating and Validating JWT Tokens

Create a utility class for generating and validating JWT tokens. This class will include various methods for handling JWT.


        import io.jsonwebtoken.Claims;
        import io.jsonwebtoken.JwtBuilder;
        import io.jsonwebtoken.JwtParser;
        import io.jsonwebtoken.Jwts;
        import io.jsonwebtoken.SignatureAlgorithm;
        import org.springframework.stereotype.Component;

        import java.util.Date;
        import java.util.HashMap;
        import java.util.Map;

        @Component
        public class JwtTokenProvider {
            private final String SECRET_KEY = "mySecretKey";

            public String createToken(String username) {
                Map claims = new HashMap<>();
                return Jwts.builder()
                        .setClaims(claims)
                        .setSubject(username)
                        .setIssuedAt(new Date())
                        .setExpiration(new Date(System.currentTimeMillis() + 1000 * 60 * 60 * 10)) // 10 hours
                        .signWith(SignatureAlgorithm.HS256, SECRET_KEY)
                        .compact();
            }

            public boolean validateToken(String token) {
                try {
                    Jwts.parser().setSigningKey(SECRET_KEY).parseClaimsJws(token);
                    return true;
                } catch (Exception e) {
                    return false;
                }
            }
            
            public Authentication getAuthentication(String token) {
                // Implement user authentication logic
            }
        }
        

Implementing Logout Feature

The logout feature allows the user to terminate authentication, which is usually implemented by deleting the JWT token from the client. Furthermore, if the server needs to invalidate the token, a blacklist must be managed.


        import org.springframework.web.bind.annotation.*;

        @RestController
        @RequestMapping("/auth")
        public class AuthController {
            @PostMapping("/logout")
            public ResponseEntity logout(HttpServletRequest request) {
                String token = request.getHeader("Authorization");
                // Logic for registering the token in the blacklist
                return ResponseEntity.ok("Logout Successful");
            }
        }
        

Conclusion

In this tutorial, we explored how to implement login/logout features based on JWT using Spring Boot. JWT is a useful tool for handling authentication and authorization in web services, and it will be a great help in future application development. Additionally, researching more about security and session management can help ensure better security.

If you want to expand your knowledge related to authentication and authorization with JWT, it is recommended to study security best practices along with protocols like OAuth2 and OpenID Connect.