Fullstack Java Authentication: Implementing JWT in Spring Security

In modern fullstack applications, security is a critical pillar of development. Whether you're building a REST API or a web-based dashboard, protecting your application from unauthorized access is essential. JSON Web Tokens (JWT) offer a powerful and stateless solution for handling authentication in distributed systems. In the Java ecosystem, Spring Security provides a robust framework for implementing JWT-based authentication.

In this blog, we’ll walk through how to implement JWT in Spring Security, covering the key components and best practices for secure fullstack authentication.


🔐 Why Use JWT?

JWT (JSON Web Token) is a compact, self-contained token format used to securely transmit information between parties. It is widely used for stateless authentication, meaning there's no need to store session data on the server.

Key advantages:

  • Stateless and scalable
  • Easy to transmit in HTTP headers
  • Can include user claims (like roles and permissions)


🛠️ How JWT Authentication Works

  • User logs in with credentials.
  • Backend verifies credentials and generates a JWT.
  • JWT is returned to the client and stored (e.g., in localStorage).
  • Client sends JWT in Authorization header for each subsequent request.
  • Backend validates JWT and processes the request.


🧱 Components Needed in Spring Security

To implement JWT in Spring Security, you’ll need:

  • Authentication endpoint
  • JWT utility class (for token creation and validation)
  • Custom filter to intercept and validate JWT
  • Spring Security configuration


✅ Step-by-Step JWT Implementation in Spring Security

1. Add Dependencies (Maven)

xml


<dependency>

  <groupId>org.springframework.boot</groupId>

  <artifactId>spring-boot-starter-security</artifactId>

</dependency>

<dependency>

  <groupId>io.jsonwebtoken</groupId>

  <artifactId>jjwt</artifactId>

  <version>0.9.1</version>

</dependency>

2. Create a JWT Utility Class

This class will handle token creation and validation:


java

public class JwtUtil {

    private String SECRET_KEY = "my_secret_key";


    public String generateToken(UserDetails userDetails) {

        return Jwts.builder()

            .setSubject(userDetails.getUsername())

            .setIssuedAt(new Date(System.currentTimeMillis()))

            .setExpiration(new Date(System.currentTimeMillis() + 1000 * 60 * 60 * 10))

            .signWith(SignatureAlgorithm.HS256, SECRET_KEY).compact();

    }


    public String extractUsername(String token) {

        return Jwts.parser().setSigningKey(SECRET_KEY)

            .parseClaimsJws(token).getBody().getSubject();

    }


    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 Jwts.parser().setSigningKey(SECRET_KEY)

            .parseClaimsJws(token).getBody().getExpiration();

    }

}

3. Create a Filter to Intercept Requests

java


public class JwtRequestFilter extends OncePerRequestFilter {


    @Autowired

    private JwtUtil jwtUtil;


    @Autowired

    private UserDetailsService userDetailsService;


    @Override

    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)

        throws ServletException, IOException {


        final String authorizationHeader = request.getHeader("Authorization");


        String username = null;

        String jwt = null;


        if (authorizationHeader != null && authorizationHeader.startsWith("Bearer ")) {

            jwt = authorizationHeader.substring(7);

            username = jwtUtil.extractUsername(jwt);

        }


        if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {

            UserDetails userDetails = this.userDetailsService.loadUserByUsername(username);

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

                UsernamePasswordAuthenticationToken authToken = new UsernamePasswordAuthenticationToken(

                        userDetails, null, userDetails.getAuthorities());

                authToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));

                SecurityContextHolder.getContext().setAuthentication(authToken);

            }

        }

        chain.doFilter(request, response);

    }

}

4. Configure Spring Security

java


@EnableWebSecurity

public class SecurityConfigurer extends WebSecurityConfigurerAdapter {


    @Autowired

    private JwtRequestFilter jwtRequestFilter;


    @Override

    protected void configure(HttpSecurity http) throws Exception {

        http.csrf().disable()

            .authorizeRequests().antMatchers("/authenticate").permitAll()

            .anyRequest().authenticated();

        http.addFilterBefore(jwtRequestFilter, UsernamePasswordAuthenticationFilter.class);

    }

}

🚀 Final Thoughts

JWT and Spring Security make a powerful combination for building secure, scalable, and stateless authentication in fullstack Java applications. Once implemented, you can easily integrate your backend with modern frontend frameworks like React or Angular, passing tokens via HTTP headers.

Remember to:

  • Keep your secret key safe
  • Use HTTPS in production
  • Set token expiration wisely
  • Consider refreshing tokens securely

Learn FullStack Java Course in Hyderabad
Read More : Fullstack Java Development: JavaScript and Java Integration


Visit Our IHUB Talent Institute Hyderabad
Get Direction 

Comments

Popular posts from this blog

How to Use Tosca's Test Configuration Parameters

Installing Java and Eclipse IDE for Selenium Automation

How Flutter Works Behind the Scenes