What is Basic Auth and How to secure APIs using it?
We will learn what is basic auth and how to configure the Config class for authentication and authorization along with creating custom users
In the previous article, we started by creating an employee API and secured it by just adding spring-security dependency and got introduced with form-based login.
In this article, we will keep form-based login aside and get started with Basic Auth.
I hope you have followed the previous article, we have already created the project we will continue working on the same application.
What is Basic Authentication?
Basic authentication is a simple authentication scheme built into the HTTP protocol. The client sends HTTP requests with the Authorization header that contains the word Basic word followed by a space and a base64-encoded string username: password.
Configure Basic Auth To implement Basic Auth, we need to create a config class.
@Configuration
@EnableWebSecurity
public class AppSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.anyRequest()
.authenticated()
.and()
.httpBasic(); // basic auth
}
}
As AppSecurityConfig is a config class, we need to have Configuration annotation and also this configuration is used for spring security we need to also add EnableWebSecurity annotation.
It extends WebSecurityConfigurerAdapter which acts as a base class and it provides various methods whose functionality we can change by overriding the methods.
Override the configure method which takes HttpSecurity as an argument and tells spring security that we need to authorize all requests and the authentication will be Basic Auth.
Now let's start the application and access the API (http://localhost:8080/api/v1/employees/1)
In the previous article, we saw a Sign In form as it was form-based login. But here instead of that, we get a pop that asks username and password.
The default username is user and the password is present in the logs.
Now let us understand how it works behind the scene.
In Basic Auth, on every request, we have to send the Base 64 encoded string of username and password in the header as
Example : Authorization: Basic ZGVtbzpwQDU1dzByZA==
Request 1
Request 2
Whitelisting URL
Suppose we want some endpoint to be free from security(eg: home page of the website), then we can use antMatchers and pass the patterns and permit them all in the Config file.
We have created a simple HTML file(index.html) in src/main/resources/static which will be mapped to ("/"), we want this page to be accessed by everyone.
<h1>Let's Learn Spring Security</h1>
@Configuration
@EnableWebSecurity
public class AppSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/")
.permitAll() // look here
.anyRequest()
.authenticated()
.and()
.httpBasic();
}
}
Creating Custom User
Till now we are using default user and password provided by spring-security now we will create our own users who can access the APIs.
We need to create an UserDetailsService Bean in the config class, where we will declare our users
@Override
@Bean
protected UserDetailsService userDetailsService() {
UserDetails alexJamesUser = User.builder()
.username("alexjames")
.password(passwordEncoder.encode("password"))
.roles("EMPLOYEE") // ROLE_EMPLOYEE
.build();
UserDetails emmaUser = User.builder()
.username("emma")
.password(passwordEncoder.encode("password123"))
.roles("ADMIN") // ROLE_ADMIN
.build();
return new InMemoryUserDetailsManager(
alexJamesUser,
emmaUser
);
}
UserDetailsService is a Core interface that loads user-specific data. It is used throughout the framework as a user DAO.
Using User builder() we are creating each user by providing the username, password, and the roles that the user has(we will learn more about roles and authorities in further articles)
For the password we can't directly use the String, Spring expects the password to be encrypted using an encoder.
@Configuration
public class PasswordConfig {
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder(10);
}
}
We have created a PasswordEncoder Bean which is basically a BCryptPasswordEncoder.
We need to Autowire this encoder in the config class to use it.
As UserDetailsService is an interface, there are multiple Implementing classes we have used InMemoryUserDetailsManager as we are creating user in-memory only.
Let's run the application
Success
Failure
This is how we can create our custom users.
Conclusion
If you find this one helpful, do give it a like👍
Any feedback/suggestions? Do comment below.
You can find the Code of this article here
In this article, we learned about
- Basic Auth
- How to configure spring security by extending WebSecurityConfigurerAdapter.
- Whitelisting URL using antMatchers()
- Creating custom users using InMemoryUserDetailsManager.
While creating users we added roles, from next article we will start with
- What are Roles and Authorities/Permission?
- How to do Role-Based authentication?
- How to do Permission-Based authentication? and much more
Stay tuned for the next one. Till then Bye👋