🔐 Spring Security: Using JWT and Basic Auth for Different URL Patterns

🔐 Spring Security: Using JWT and Basic Auth for Different URL Patterns


Hello, fellow developers! 👋

If you’ve ever scratched your head wondering, “How can I use both JWT and Basic Auth in the same Spring Boot application for different URL patterns?” — you’re not alone. This blog post is for developers like you who want to secure different parts of a Spring Boot app using different authentication mechanisms.

Java & Spring Boot Interview Prep Mastery BundleThe Ultimate Guide to Ace Your Next Technical Interview🚀 Boost Your Confidence, Land Your Dream Job!🔥 What’s Inside?1. 📖 100 Core Java Interview Questions✅ Master OOP, Multithreading, Collections, Exception Handling, and Java 8+ Features✅ Covers JVM Internals, Memory Management, and Performance Tuning✅ Real-World Examples & Best Practices2. 💻 50 Java Coding Problems✅ Arrays, Strings, Linked Lists, Trees, Dynamic Programming, and More!✅ Step-by-Step Explanations & Optimized Solutions✅ Commonly Asked in FAANG & Top Tech Companies3. 🌟 50 Spring Boot Interview Questions✅ Spring Boot Fundamentals, REST APIs, Spring Security, Microservices✅ Database Integration (JPA, Hibernate), Testing, and Deployment✅ Docker, Kubernetes, and Best Practices🎯 Who Is This For?✔ Java Developers preparing for technical interviews✔ Software Engineers targeting FAANG & top tech companies✔ Spring Boot Developers looking to deepen their knowledge✔ Students & Beginners wanting to crack coding interviews

favicon
codewithnik.gumroad.com

By the end, you’ll be able to:

✅ Secure some APIs with Basic Auth

✅ Secure others with JWT

✅ Configure everything cleanly with Spring Security

Let’s dive right in!




✨ Why Would You Need Multiple Authentication Types?

There are plenty of real-world use cases:

  • Public APIs secured via Basic Auth (for clients using tools like Postman or curl)
  • Mobile/web clients using JWT tokens for stateless authentication
  • Admin endpoints that are locked down with Basic Auth
  • User endpoints that use JWT-based login flow

Instead of choosing either JWT or Basic Auth, Spring Security gives us the power to use both, tailored to specific URL patterns.




🧠 High-Level Approach

Here’s how we’re going to do it:

  1. Create two SecurityFilterChain beans:
    • One for Basic Auth endpoints (/api/admin/**)
    • One for JWT-secured endpoints (/api/user/**)
  2. Define an authentication provider for each type.
  3. Register both configurations with proper @Order.



📦 Dependencies (Spring Boot 3.x)

Add the following to your pom.xml:


    
        org.springframework.boot
        spring-boot-starter-security
    
    
        io.jsonwebtoken
        jjwt-api
        0.11.5
    
    
        io.jsonwebtoken
        jjwt-impl
        0.11.5
        runtime
    
    
        io.jsonwebtoken
        jjwt-jackson
        0.11.5
        runtime
    

Enter fullscreen mode

Exit fullscreen mode




🔐 1. Basic Authentication for /api/admin/**

Let’s start with securing admin APIs using Basic Auth.

@Configuration
@Order(1)
public class BasicAuthSecurityConfig {

    @Bean
    public SecurityFilterChain basicAuthFilterChain(HttpSecurity http) throws Exception {
        http
            .securityMatcher("/api/admin/**")
            .authorizeHttpRequests(auth -> auth.anyRequest().authenticated())
            .httpBasic(Customizer.withDefaults())
            .sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
            .csrf(csrf -> csrf.disable());

        return http.build();
    }

    @Bean
    public UserDetailsService basicUserDetailsService() {
        UserDetails admin = User.withUsername("admin")
                                .password(passwordEncoder().encode("admin123"))
                                .roles("ADMIN")
                                .build();
        return new InMemoryUserDetailsManager(admin);
    }

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }
}
Enter fullscreen mode

Exit fullscreen mode

📝 Try accessing:

curl -u admin:admin123 http://localhost:8080/api/admin/dashboard




🧾 2. JWT Authentication for /api/user/**

We’ll now secure user APIs using JWTs. First, create a JWT utility class.



🔧 JWT Utility Class

@Component
public class JwtUtils {

    private final String secret = "mysecretkey";

    public String generateToken(String username) {
        return Jwts.builder()
                .setSubject(username)
                .setIssuedAt(new Date())
                .setExpiration(new Date(System.currentTimeMillis() + 86400000))
                .signWith(Keys.hmacShaKeyFor(secret.getBytes()))
                .compact();
    }

    public String extractUsername(String token) {
        return Jwts.parserBuilder()
                .setSigningKey(secret.getBytes())
                .build()
                .parseClaimsJws(token)
                .getBody()
                .getSubject();
    }

    public boolean validateToken(String token) {
        try {
            extractUsername(token);
            return true;
        } catch (Exception e) {
            return false;
        }
    }
}
Enter fullscreen mode

Exit fullscreen mode



🧱 JWT Filter

@Component
public class JwtAuthFilter extends OncePerRequestFilter {

    @Autowired
    private JwtUtils jwtUtils;

    @Autowired
    private UserDetailsService jwtUserDetailsService;

    @Override
    protected void doFilterInternal(HttpServletRequest request,
                                    HttpServletResponse response,
                                    FilterChain filterChain) throws ServletException, IOException {
        final String authHeader = request.getHeader("Authorization");

        if (authHeader != null && authHeader.startsWith("Bearer ")) {
            String jwt = authHeader.substring(7);
            String username = jwtUtils.extractUsername(jwt);

            if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {
                UserDetails userDetails = jwtUserDetailsService.loadUserByUsername(username);

                if (jwtUtils.validateToken(jwt)) {
                    UsernamePasswordAuthenticationToken auth =
                        new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());

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

                    SecurityContextHolder.getContext().setAuthentication(auth);
                }
            }
        }

        filterChain.doFilter(request, response);
    }
}
Enter fullscreen mode

Exit fullscreen mode



🔐 JWT Security Configuration

@Configuration
@Order(2)
public class JwtSecurityConfig {

    @Autowired
    private JwtAuthFilter jwtAuthFilter;

    @Bean
    public SecurityFilterChain jwtFilterChain(HttpSecurity http) throws Exception {
        http
            .securityMatcher("/api/user/**")
            .authorizeHttpRequests(auth -> auth.anyRequest().authenticated())
            .sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
            .addFilterBefore(jwtAuthFilter, UsernamePasswordAuthenticationFilter.class)
            .csrf(csrf -> csrf.disable());

        return http.build();
    }

    @Bean
    public UserDetailsService jwtUserDetailsService() {
        UserDetails user = User.withUsername("john")
                               .password(passwordEncoder().encode("john123"))
                               .roles("USER")
                               .build();
        return new InMemoryUserDetailsManager(user);
    }
}
Enter fullscreen mode

Exit fullscreen mode




🚀 Testing It Out



🧪 Basic Auth

curl -u admin:admin123 http://localhost:8080/api/admin/dashboard
Enter fullscreen mode

Exit fullscreen mode



🧪 JWT Flow

  1. Simulate login and generate token (you can hardcode for now).
String jwt = jwtUtils.generateToken("john");
Enter fullscreen mode

Exit fullscreen mode

  1. Access secure API:
curl -H "Authorization: Bearer " http://localhost:8080/api/user/profile
Enter fullscreen mode

Exit fullscreen mode




💡 Final Thoughts

This dual-authentication strategy is incredibly useful when:

  • You need backward compatibility for legacy clients (Basic Auth)
  • You want modern stateless security for SPAs/mobile apps (JWT)
  • You’re building multi-tenant or role-separated services

Spring Security’s filter chains and @Order mechanism make it super easy to support both.




🔍 SEO Keywords (for Google’s love ❤️)

  • Spring Security multiple authentication providers
  • Spring Boot Basic Auth and JWT together
  • Spring Security filter chain for different URL patterns
  • Secure REST API with JWT and Basic Auth
  • Spring Security custom SecurityFilterChain



🙋 Need Help?

Got stuck? Want the full source code or a GitHub repo? Drop a comment below or message me on LinkedIn!

Until next time, happy coding!

– Your friendly Spring Coach 💻☕



Source link

Leave a Reply

Your email address will not be published. Required fields are marked *