Learn / Frameworks / Spring Boot / Spring Security and JWT

Spring Boot · Lesson 6 of 15

Spring Security and JWT

Lock down endpoints, hash passwords and authenticate with a Bearer token.

  • Intermediate
  • 18 min read
  • 3 objectives

Before this lessonLesson 5: Configuration, Profiles and Testing

What you will learn

  • Configure SecurityFilterChain
  • Hash with BCrypt
  • Validate a JWT

Your Progress

0 of 15 lessons 0%

  • Lessons0 / 15
  • Completed0
  • Est. time left~ 4 hours

Create a free account to keep your progress on every device.

Spring Security is a filter chain: every request is authenticated and then authorised. For a JSON API, disable sessions and accept a Bearer JWT.

The filter chain

@Configuration
@EnableWebSecurity
public class SecurityConfig {
    @Bean
    SecurityFilterChain api(HttpSecurity http, JwtAuthFilter jwt) throws Exception {
        return http
            .csrf(csrf -> csrf.disable())
            .sessionManagement(s -> s.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
            .authorizeHttpRequests(auth -> auth
                .requestMatchers("/api/auth/**", "/actuator/health").permitAll()
                .anyRequest().authenticated())
            .addFilterBefore(jwt, UsernamePasswordAuthenticationFilter.class)
            .build();
    }

    @Bean
    PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }
}

Register and login

@PostMapping("/api/auth/register")
public ResponseEntity<Void> register(@Valid @RequestBody RegisterRequest body) {
    if (users.existsByEmail(body.email())) return ResponseEntity.status(409).build();
    users.save(new User(body.email(), encoder.encode(body.password())));
    return ResponseEntity.status(201).build();
}

@PostMapping("/api/auth/login")
public TokenResponse login(@RequestBody LoginRequest body) {
    User user = users.findByEmail(body.email()).orElseThrow(() -> new BadCredentialsException("bad"));
    if (!encoder.matches(body.password(), user.getPasswordHash())) throw new BadCredentialsException("bad");
    return new TokenResponse(jwt.issue(user.getId()));
}

The JWT filter

Read Authorization, verify the signature, and set SecurityContextHolder. Skip the filter when the header is missing so public routes still work.

Up next · Lesson 7Validation and Problem DetailsBean Validation, MethodArgumentNotValidException and RFC 7807 bodies.