Basic Authentication with Spring Security
Add Spring Security and your whole API is protected — only requests with a valid username and password get through.
What you will learn
- Add Spring Security to an app
- Protect endpoints with HTTP Basic auth
- Define an in-memory user
Locking the door
Most APIs should not be open to everyone. Spring Security is the standard way to add login and access control. The remarkable thing: just adding the dependency instantly protects every endpoint.
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>Note: Output: With only this added, restart and visit any endpoint: -> 401 Unauthorized (you must log in) Spring also prints a generated password in the console at startup: Using generated security password: 8f3a... The whole API is now locked by default — security is opt-out, not opt-in.
Define your own user
The generated password is only for a first test. Define a real user with a small config class. HTTP Basic auth sends a username and password with each request.
@Configuration
public class SecurityConfig {
@Bean
public UserDetailsService users() {
UserDetails user = User.withDefaultPasswordEncoder()
.username("admin")
.password("secret123")
.roles("ADMIN")
.build();
return new InMemoryUserDetailsManager(user);
}
@Bean
public SecurityFilterChain chain(HttpSecurity http) throws Exception {
http.authorizeHttpRequests(a -> a.anyRequest().authenticated())
.httpBasic(Customizer.withDefaults()); // use HTTP Basic auth
return http.build();
}
}Note: Output:
No credentials:
GET /products -> 401 Unauthorized
With the right user (admin / secret123):
curl -u admin:secret123 http://localhost:8080/products
-> 200 OK, the JSON data
The request now succeeds because it carried valid credentials. -u sends the username and password.
How a protected request flows, step by step
Here is exactly what happens, in order, when a request hits a secured endpoint — first without a login, then with one:
- A request arrives at a protected endpoint, e.g.
GET /products. - Spring Security checks for credentials (a username and password) in the request.
- If there are none (or they are wrong), Spring stops the request and returns 401 Unauthorized — your controller never runs.
- So the client retries with credentials, e.g.
curl -u admin:secret123 ..., which sends the username and password using HTTP Basic. - Spring checks them against your user (
admin/secret123). They match, so it lets the request through. - Your controller method runs and returns the data with a 200 OK — the same response as before, now only for logged-in callers.
Tip: You can protect only some routes. For example, allow GET /products for everyone but require login for changes — by listing rules like requestMatchers(HttpMethod.GET, "/products").permitAll() before anyRequest().authenticated().
Watch out: The in-memory user and withDefaultPasswordEncoder() are great for learning, not for production. Real apps store users in a database with strong password hashing (scrambling a password into unreadable text so the stored version cannot be read back), and serious APIs use tokens like JWT (JSON Web Token — a small signed string the client sends instead of a password on every request) rather than sending a password every time.
Q. What happens the moment you add the Spring Security starter to a Spring Boot app?
✍️ Practice
- Add Spring Security and confirm an endpoint returns 401 with no credentials.
- Define an in-memory user and access the endpoint with
curl -u user:pass.
🏠 Homework
- Protect your CRUD API so that reading is open to all but creating, updating and deleting require login.