4 min read

Basic Authentication in Spring Boot

December 21, 2020

Basic authentication or Basic access authentication is the simplest form of web security implementation. Basic authentication doesn’t require any HTML form to submit the username and password. Instead, it relies on the browser implementation as per RFC7617 and RFC2617 to get the credentials from the user and pass it as an HTTP header to the server.

Basic auth requires credentials to be encoded in base64 and sent to the server in the form of HTTP request headers. For example, Let’s say your username is user and password is Secure1_. For this, the HTTP Authorization header is computed as follows.

  1. Arrange the credentials in the form of <username>:<password> which is user:Secure1_.
  2. Encode the above string into base64. In this example the result is dXNlcjpTZWN1cmUxXw==.
  3. Add an Authorization header to the request as shown below.

    Authorization: Basic dXNlcjpTZWN1cmUxXw===
  4. On receiving this header in the request, the server can decode the username and password from the encoded string.

Now that you know how basic auth works, let’s find out how to enable this to our spring boot application.

Setting up Basic Auth

To set up basic authentication, you need to provide our own HttpSecurity configuration. Similar to providing custom login form, this setup also requires a custom WebSecurityConfigurerAdapter as shown below.

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    public void configure(HttpSecurity httpSecurity) throws Exception {
        httpSecurity
                .authorizeRequests()
                .anyRequest()
                .authenticated()
                .and()
                .httpBasic();
    }
}

This is the only change that you have to do. After adding this configuration to your application restart and access http://localhost:8080/hello. This time the browser will show you a username and password dialogue. The dialogue box itself may look different from browser to browser(see image below). Yet, they all take a username and password.

authentication dialogue from different browsers

After providing a username and password, You will be shown a ”Hello World!” message.

Browser behaviour for Basic Auth

You may wonder how the browser knew when to ask for credentials. This ingenuity is part of the RFC specification. When a request comes to the server who supports basic auth, the server must respond with a 401 Unauthorized response code along with a WWW-Authenticate header. This header contains which authentication type the server supports. In this case, it would specify Basic.

Here is the complete flow of how basic auth works.

UserBrowserApplicationOpen http://localhost:8080/hello1GET /hello2HTTP/1.1 401 Unauthorized                                  WWW-Authenticate: Basic realm="Place To access"3Prompt username/password dialogue4GET /hello                                                   Authorization: Basic dXNlcjp1c2VyQDEyMw==5Valid credentials?6HTTP/1.1 200 OK7HTTP/1.1 403 forbidden8alt[is Valid][is not Valid]UserBrowserApplication

Session Handling with BasicAuth

By default, Spring Security enables session management. This means a JSESSIONID cookie will be exchanged with browser for further requests. At this point, further requests don’t need an Authorization header. But, the default behaviour of the browsers is to send an Authorization header regardless. This behaviour is for the client and server to establish a stateless communication. We will speak about sessions and state in upcoming posts. Just remember that session is nothing, but the concept of server keeping track of the client requests.

We can take full advantage of basic authentication by disabling the session management altogether with a small change to our configuration.

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    public void configure(HttpSecurity httpSecurity) throws Exception {
        httpSecurity
                .authorizeRequests()
                .anyRequest()
                .authenticated()
                .and()
                .httpBasic()
                .and()
                .sessionManagement()
                .sessionCreationPolicy(SessionCreationPolicy.STATELESS);
    }
}

By setting the session creation policy to be STATELESS, the server will not send a JSESSIONID cookie anymore. you can check this in the Chrome developer tools by going to Application > Storage > Cookies.

This may be helpful when you have more than one instance of the same application running behind a load balancer or a gateway. This way, the applications don’t need to share a common session store like Redis.

Things to consider

  1. The passwords in requests with basic auth are encoded and not encrypted. To be secure, only use Basic Auth if the communication between client and server has some form of encryption like SSL/TLS.
  2. Basic Auth is probably best when used with in-memory UserDetailService users like the default user that got created. If the user details are to be fetched from DB or some third party, performance is going to get worse.
  3. Complementing point 2, You can improve the performance by loading the user details from a cache such as Redis.