Advertisement

Google Ad Slot: content-top

Spring Boot JWT (JSON Web Token)

~1 min read · Spring Boot
On this page

What is JWT?

JWT (JSON Web Token) is a compact, URL-safe means of representing claims to be transferred between two parties. It is commonly used for stateless authentication in APIs.

How JWT Works?

1️⃣ User logs in → Sends username & password

2️⃣ Server validates credentials → Generates a JWT token

3️⃣ Token is returned to the client

4️⃣ Client sends token in Authorization header in each request

5️⃣ Server verifies token before allowing access

Add JWT Dependencies:

Add the following dependencies in pom.xml:

io.jsonwebtoken jjwt-api 0.11.5 io.jsonwebtoken jjwt-impl 0.11.5 runtime io.jsonwebtoken jjwt-jackson 0.11.5 runtime

Configure JwtService Class:

Create a Service class to generate & validate JWT tokens.

import io.jsonwebtoken.Claims; import io.jsonwebtoken.Jwts; import io.jsonwebtoken.SignatureAlgorithm; import io.jsonwebtoken.io.Decoders; import io.jsonwebtoken.security.Keys; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.stereotype.Service; import javax.crypto.KeyGenerator; import javax.crypto.SecretKey; import java.security.Key; import java.security.NoSuchAlgorithmException; import java.util.Base64; import java.util.Date; import java.util.HashMap; import java.util.Map; import java.util.function.Function; @Service public class JwtService { private static final String SECRET = "TmV3U2VjcmV0S2V5Rm9ySldUU2lnbmluZ1B1cnBvc2VzMTIzNDU2Nzg=\r\n"; private String secretKey; public JwtService(){ secretKey = generateSecretKey(); } public String generateSecretKey() { try { KeyGenerator keyGen = KeyGenerator.getInstance("HmacSHA256"); SecretKey secretKey = keyGen.generateKey(); System.out.println("Secret Key : " + secretKey.toString()); return Base64.getEncoder().encodeToString(secretKey.getEncoded()); } catch (NoSuchAlgorithmException e) { throw new RuntimeException("Error generating secret key", e); } } public String generateToken(String username) { Map claims = new HashMap<>(); return Jwts.builder() .setClaims(claims) .setSubject(username) .setIssuedAt(new Date(System.currentTimeMillis())) .setExpiration(new Date(System.currentTimeMillis() + 1000*60*30)) .signWith(getKey(), SignatureAlgorithm.HS256).compact(); } private Key getKey() { byte[] keyBytes = Decoders.BASE64.decode(secretKey); return Keys.hmacShaKeyFor(keyBytes); } public String extractUserName(String token) { // extract the username from jwt token return extractClaim(token, Claims::getSubject); } private T extractClaim(String token, Function claimResolver) { final Claims claims = extractAllClaims(token); return claimResolver.apply(claims); } private Claims extractAllClaims(String token) { return Jwts.parserBuilder() .setSigningKey(getKey()) .build().parseClaimsJws(token).getBody(); } public boolean validateToken(String token, UserDetails userDetails) { final String userName = extractUserName(token); return (userName.equals(userDetails.getUsername()) && !isTokenExpired(token)); } private boolean isTokenExpired(String token) { return extractExpiration(token).before(new Date()); } private Date extractExpiration(String token) { return extractClaim(token, Claims::getExpiration); } }

Create a User Entity:

import jakarta.persistence.*; import lombok.*; @Entity @Table(name = "user") @Getter @Setter @NoArgsConstructor @AllArgsConstructor public class User { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private String username; private String password; private String role; // e.g., ROLE_ADMIN, ROLE_USER }

Implement User Repository:

import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.JpaSpecificationExecutor; import java.util.Optional; public interface UserRepository extends JpaRepository, JpaSpecificationExecutor { Optional findByUsername(String name); }

Implement UserDetailsService for Authentication:

import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.core.userdetails.UsernameNotFoundException; import org.springframework.stereotype.Service; @Service public class CustomUserDetailsService implements UserDetailsService { private final UserRepository userRepository; public CustomUserDetailsService(UserRepository userRepository) { this.userRepository = userRepository; } @Override public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { User user = userRepository.findByUsername(username) .orElseThrow(() -> new UsernameNotFoundException("User not found")); return org.springframework.security.core.userdetails.User .withUsername(user.getUsername()) .password(user.getPassword()) .roles(user.getRole()) // Ensure roles start with "ROLE_" .build(); } }

Create JWT Authentication Filter:

import jakarta.servlet.FilterChain; import jakarta.servlet.ServletException; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationContext; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.web.authentication.WebAuthenticationDetailsSource; import org.springframework.stereotype.Component; import org.springframework.web.filter.OncePerRequestFilter; import java.io.IOException; @Component public class JwtFilter extends OncePerRequestFilter { @Autowired JwtService jwtService; @Autowired ApplicationContext context; @Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { String authHeader = request.getHeader("Authorization"); String token = null; String userName = null; if(authHeader != null && authHeader.startsWith("Bearer ")){ token = authHeader.substring(7); userName = jwtService.extractUserName(token); } if(userName != null && SecurityContextHolder.getContext().getAuthentication()==null){ UserDetails userDetails = context.getBean(CustomUserDetailsService.class).loadUserByUsername(userName); if(jwtService.validateToken(token, userDetails)){ UsernamePasswordAuthenticationToken authToken = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities()); authToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request)); SecurityContextHolder.getContext().setAuthentication(authToken); } } filterChain.doFilter(request, response); } }

Configure Security:

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.authentication.AuthenticationProvider; import org.springframework.security.authentication.dao.DaoAuthenticationProvider; import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; 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.SecurityFilterChain; import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; @Configuration @EnableWebSecurity public class SecurityConfig { @Autowired private UserDetailsService userDetailsService; @Autowired private JwtFilter jwtFilter; @Bean public AuthenticationProvider authProvider() { DaoAuthenticationProvider provider = new DaoAuthenticationProvider(); provider.setUserDetailsService(userDetailsService); provider.setPasswordEncoder(new BCryptPasswordEncoder(12)); return provider; } @Bean public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { http.csrf(customizer -> customizer.disable()) .authorizeHttpRequests(request -> request .requestMatchers("register", "login") .permitAll() .anyRequest().authenticated()) .sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS)) .addFilterBefore(jwtFilter, UsernamePasswordAuthenticationFilter.class); return http.build(); } @Bean public AuthenticationManager authenticationManager(AuthenticationConfiguration config) throws Exception { return config.getAuthenticationManager(); } }

Create Authentication Controller:

import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.web.bind.annotation.*; @RestController @RequestMapping("/") public class AuthController { @Autowired private JwtService JwtService; @Autowired private UserService service; @Autowired private AuthenticationManager authenticationManager; @PostMapping("register") public User register(@RequestBody User user) { return service.saveUser(user); } @PostMapping("login") public String login(@RequestBody User user) { System.out.println(user.getUsername()); System.out.println(user.getPassword()); authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(user.getUsername(), user.getPassword())); return JwtService.generateToken(user.getUsername()); } @GetMapping("auth") public String auth() { return "SuccessFull"; } }

Testing the REST API with Postman:

Once the application is running, test the endpoints:


Register User  POST:http://localhost:8080/register

Login User  GET:http://localhost:8080/login

Set Token for other Route  GET:http://localhost:8080/auth