Spring Security Basic Authentication
Basic Authentication sends username:password (Base64-encoded) with every request. It’s simple and good for internal APIs.
In-Memory Users (Quick Start)
@Configuration
@EnableWebSecurity
public class SecurityConfig {
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.csrf(csrf -> csrf.disable())
.httpBasic(Customizer.withDefaults())
.authorizeHttpRequests(auth -> auth
.requestMatchers(HttpMethod.GET, "/api/books/**").permitAll()
.requestMatchers("/api/admin/**").hasRole("ADMIN")
.anyRequest().authenticated()
);
return http.build();
}
@Bean
public InMemoryUserDetailsManager userDetailsService() {
UserDetails user = User.builder()
.username("user")
.password(passwordEncoder().encode("password"))
.roles("USER")
.build();
UserDetails admin = User.builder()
.username("admin")
.password(passwordEncoder().encode("admin123"))
.roles("ADMIN", "USER")
.build();
return new InMemoryUserDetailsManager(user, admin);
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}
# Test with curl
curl -u user:password http://localhost:8080/api/books
curl -u admin:admin123 http://localhost:8080/api/admin/stats
Database-Backed Authentication
User Entity
@Entity
@Table(name = "users")
public class AppUser {
@Id @GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(unique = true, nullable = false)
private String username;
@Column(nullable = false)
private String password; // BCrypt hash
@Column(nullable = false)
private String email;
private boolean enabled = true;
@ElementCollection(fetch = FetchType.EAGER)
@CollectionTable(name = "user_roles", joinColumns = @JoinColumn(name = "user_id"))
@Column(name = "role")
private Set<String> roles = new HashSet<>();
}
UserDetailsService
@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 {
AppUser user = userRepository.findByUsername(username)
.orElseThrow(() -> new UsernameNotFoundException("User not found: " + username));
return User.builder()
.username(user.getUsername())
.password(user.getPassword())
.roles(user.getRoles().toArray(new String[0]))
.disabled(!user.isEnabled())
.build();
}
}
Registration
@Service
public class AuthService {
private final UserRepository userRepository;
private final PasswordEncoder passwordEncoder;
public AppUser register(RegisterRequest request) {
if (userRepository.existsByUsername(request.username())) {
throw new DuplicateResourceException("Username taken");
}
AppUser user = new AppUser();
user.setUsername(request.username());
user.setPassword(passwordEncoder.encode(request.password()));
user.setEmail(request.email());
user.setRoles(Set.of("USER"));
return userRepository.save(user);
}
}
Security Config with Database Users
@Configuration
@EnableWebSecurity
public class SecurityConfig {
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.csrf(csrf -> csrf.disable())
.httpBasic(Customizer.withDefaults())
.authorizeHttpRequests(auth -> auth
.requestMatchers("/api/auth/**").permitAll()
.requestMatchers("/api/admin/**").hasRole("ADMIN")
.anyRequest().authenticated()
);
return http.build();
}
@Bean
public AuthenticationManager authenticationManager(
AuthenticationConfiguration config) throws Exception {
return config.getAuthenticationManager();
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}
Spring auto-detects
UserDetailsServiceandPasswordEncoderbeans.
Key Takeaways
- Basic Auth =
Authorization: Basic base64(user:pass)with every request. InMemoryUserDetailsManagerfor quick prototyping; database for production.- Implement
UserDetailsServiceto load users from your database. - Always BCrypt passwords —
passwordEncoder.encode(rawPassword). - Basic Auth is not suitable for public APIs — use JWT instead.
What’s Next?
Next: JWT Authentication — stateless token-based auth for REST APIs.