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.
