Spring Security Basic Authentication

1. Overview

This tutorial shows how to set up, configure and customize Basic Authentication with Spring. We’re going to built on top of the simple Spring MVC example, and secure the UI of the MVC application with the Basic Auth mechanism provided by Spring Security.

2. The Spring Security Configuration

The Configuration for Spring Security is still XML:

<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/security"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns:beans="http://www.springframework.org/schema/beans"
    xsi:schemaLocation="
        http://www.springframework.org/schema/security 
        http://www.springframework.org/schema/security/spring-security-3.1.xsd
        http://www.springframework.org/schema/beans 
        http://www.springframework.org/schema/beans/spring-beans-3.2.xsd">

    <http use-expressions="true">
        <intercept-url pattern="/**" access="isAuthenticated()" />

        <http-basic />
    </http>

    <authentication-manager>
        <authentication-provider>
            <user-service>
                <user name="user1" password="user1Pass" authorities="ROLE_USER" />
            </user-service>
        </authentication-provider>
    </authentication-manager>

</beans:beans>

This is one of the last pieces of configuration in Spring that still need XML – Java Configuration for Spring Security is still a work in progress.

What is relevant here is the <http-basic> element inside the main <http> element of the configuration – this is enough to enable Basic Authentication for the entire application. The Authentication Manager is not the focus of this tutorial, so we are using an in memory manager with the user and password defined in plaintext.

The web.xml of the web application enabling Spring Security has already been discussed in the Spring Logout tutorial.

3. Consuming The Secured Application

The curl command is our go to tool for consuming the secured application.

First, let’s try to request the /homepage.html without providing any security credentials:

curl -i http://localhost:8080/spring-security-mvc-basic-auth/homepage.html

We get back the expected 401 Unauthorized and the Authentication Challenge:

HTTP/1.1 401 Unauthorized
Server: Apache-Coyote/1.1
Set-Cookie: JSESSIONID=E5A8D3C16B65A0A007CFAACAEEE6916B; Path=/spring-security-mvc-basic-auth/; HttpOnly
WWW-Authenticate: Basic realm="Spring Security Application"
Content-Type: text/html;charset=utf-8
Content-Length: 1061
Date: Wed, 29 May 2013 15:14:08 GMT

The browser would interpret this challenge and prompt us for credentials with a simple dialog, but since we’re using curl, this isn’t the case.

Now, let’s request the same resource – the homepage – but provide the credentials to access it as well:

curl -i --user user1:user1Pass http://localhost:8080/spring-security-mvc-basic-auth/homepage.html

Now, the response from the server is 200 OK along with a Cookie:

HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
Set-Cookie: JSESSIONID=301225C7AE7C74B0892887389996785D; Path=/spring-security-mvc-basic-auth/; HttpOnly
Content-Type: text/html;charset=ISO-8859-1
Content-Language: en-US
Content-Length: 90
Date: Wed, 29 May 2013 15:19:38 GMT

From the browser, the application can be consumed normally – the only difference is that a login page is no longer a hard requirement since all browsers support Basic Authentication and use a dialog to prompt the user for credentials.

4. Further Configuration – The Entry Point

By default, the BasicAuthenticationEntryPoint provisioned by Spring Security returns a full html page for a 401 Unauthorized response back to the client. This html representation of the error renders well in a browser, but it not well suited for other scenarios, such as a REST API where a json representation may be preferred.

The namespace is flexible enough for this new requirement as well – to address this – the entry point can be overridden:

<http-basic entry-point-ref="myBasicAuthenticationEntryPoint" />

The new entry point is defined as a standard bean:

@Component
public class MyBasicAuthenticationEntryPoint extends BasicAuthenticationEntryPoint {

    @Override
    public void commence
      (HttpServletRequest request, HttpServletResponse response, AuthenticationException authEx) 
      throws IOException, ServletException {
        response.addHeader("WWW-Authenticate", "Basic realm=\"" + getRealmName() + "\"");
        response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
        PrintWriter writer = response.getWriter();
        writer.println("HTTP Status 401 - " + authEx.getMessage());
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        setRealmName("Baeldung");
        super.afterPropertiesSet();
    }
}

By writing directly to the HTTP Response we now have full control over the format of the response body.

5. The Maven Dependencies

The Maven dependencies for Spring Security have been discussed before in the Spring Security with Maven article – we will need both spring-security-web and spring-security-config available at runtime.

6. Conclusion

In this example we secured an MVC application with Spring Security and Basic Authentication. We discussed the XML configuration and we consumed the application with simple curl commands. Finally took control of the exact error message format – moving from the standard HTML error page to a custom text or json format.

The implementation of this Spring tutorial can be found in the github project – this is an Eclipse based project, so it should be easy to import and run as it is. When the project runs locally, the sample html can be accessed at:

http://localhost:8080/spring-security-mvc-basic-auth/homepage.html

I usually post about Security on Google+ - you can follow me there:

Free eBook - REST Services with Spring
Join more than 2,200 engineers!

,

  • Alex

    Another good and concise tutorial :) Keep good work

  • Stephane

    I wonder where and if the myBasicAuthenticationEntryPoint has to be instantiated somewhere. Can the bean name be anything ?

    • baeldung

      Yes, it will be instantiated during the context bootstrapping process as it is annotated with @Component and the package is scanned for beans (see @ComponentScan annotation here).

    • Stephane

      I now could get the authentication working fine. I add the filter with a:

      FilterRegistration.Dynamic springSecurityFilterChain = servletContext.addFilter(“springSecurityFilterChain”, DelegatingFilterProxy.class);
      springSecurityFilterChain.addMappingForUrlPatterns(null, false, “/*”);

      I also defined the two beans:

      @Bean
      public DelegatingFilterProxy springSecurityFilterChain() {
      DelegatingFilterProxy filterProxy = new DelegatingFilterProxy();
      return filterProxy;
      }

      @Bean
      public MyBasicAuthenticationEntryPoint myBasicAuthenticationEntryPoint() {
      MyBasicAuthenticationEntryPoint myBasicAuthenticationEntryPoint = new MyBasicAuthenticationEntryPoint();
      return myBasicAuthenticationEntryPoint;
      }

      Cheers,

  • Stephane

    My app does not have a web.xml file as it uses annotations instead. I wonder how to activate the DelegatingFilterProxy then. I can include the http-basic xml config with a @ImportResource annotation but I still miss the filter registration bit.

    • baeldung

      I will publish an article about replacing the web.xml with java-only code at some point and will go through how to set up Spring MVC and Spring Security in detail.

  • Dino

    An alternative approach to have a customized content for error, I guess one can leverage the element in web.xml.